{"id":85581,"date":"2023-04-05T10:27:01","date_gmt":"2023-04-05T07:27:01","guid":{"rendered":"https:\/\/tere-tech.eu\/balticfinns\/?page_id=85581"},"modified":"2023-05-16T16:31:20","modified_gmt":"2023-05-16T13:31:20","slug":"ne-edullisemmat-asunnot-alueineen","status":"publish","type":"page","link":"https:\/\/tere-tech.eu\/balticfinns\/index.php\/ne-edullisemmat-asunnot-alueineen\/","title":{"rendered":"Ne edullisemmat asunnot alueineen"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Etujen muutokset asuinalueilta<\/h2>\n\n\n\n<script src=\"\/balticfinns\/wp-content\/plugins\/flat-prices\/libs\/echarts.min.js?982005891\"><\/script>\n<script src=\"\/balticfinns\/wp-content\/plugins\/flat-prices\/libs\/echarts-main.js?108537755\"><\/script>\n\n<script src=\"\/nodejs\/wp\/helpers.js?108537755\"><\/script>\n\n\n\n<div id=\"proffChanges\" style=\"width: 900px; height: 800px\"><\/div>\n\n\n\n<p class=\"has-base-background-color has-background has-medium-font-size\"><strong>Etujen kasvut ulkokeh\u00e4ll\u00e4 ostajalle<\/strong> kertovat miten myyntikotien arvostukset ovat ymp\u00e4rist\u00f6\u00f6ns\u00e4 n\u00e4hden kasvaneet alueittain viimeisen seurantajakson ajalta. Alta l\u00f6yd\u00e4t suoraan tarkat tiedot mit\u00e4 avoimia asuntomyyntej\u00e4 n\u00e4m\u00e4 etujaan &amp; arvostustaan kasvattaneet oikeasti ovat ja kuinka paljon kukin myynti on liikahtanut markkinoilla (+ paljon muuta hyv\u00e4\u00e4 lis\u00e4tietoa).<\/p>\n\n\n\n<link rel=\"stylesheet\" href=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/font-awesome\/4.7.0\/css\/font-awesome.min.css?1231785755\">\n\n<div style=\"display: none\">\n    <div id=\"serviceBubble\">        \n\n    <i v-show=\"backImg === ''\" class=\"fa fa-spinner fa-pulse fa-3x fa-fw\" \n               style=\"color: black; font-size:x-large; float:right\"><\/i>\n        \n    <div v-show=\" backImg !== '' \" class=\"img-container bubble_look\">\n      <img v-bind:src=\"backImg\" \n           v-bind:data-src=\"bubbleStyle2\" \n           alt=\"House's foto\" \n           loading=\"lazy\">\n      \n      <div class=\"overlay-text\">\n        <span class=\"text-line\">\n            {{ placeType.toUpperCase() }}<\/span>\n        <span class=\"text-line\">\n            {{ placeName }}<\/span>\n        <span class=\"text-line\">\n            {{ placeDist }} \n            <span v-if=\" placeDist > 0 \">km<\/span>\n        <\/span>\n      <\/div>\n      \n      <button title=\"Open big full foto\" \n              class='btn btn-info overlay-button' \n              @click=\"openWin(placeType, placeName)\"\n              target=\"_blank\">\n          <span class=\"glyphicon glyphicon-new-window\" \n                style=\"font-size: large; color: navy; padding: 4px\">\n          <\/span>\n      <\/button>\n      \n      <button v-show=\"onRestaurants\" \n              class='btn btn-info overlay-button'\n              >\n          <a :href=\"tAdvisor\" target=\"_blank\">\n          <img title=\"Check reviews\" \n               style=\"padding: 5px\"\n               :src=\"imgAdv\">\n          <\/a>\n      <\/button>\n    <\/div>\n  <\/div>\n<\/div>\n\n<!-- <\/template> -->\n\n<script>\n\/*\n  satImg = {lat: 59.434735167900556, lng: 24.75067913532257, zoom: 0.15, layers: 'of10000'};\n  imgOut = {h: 360, w: 340};\n  service = {type: 'restaurant', name: 'Hese', dist: '0.7'};\n *\/\n\n    vueServiceBubble = {};\n    function newServiceBubble(service, satImg, imgOut, id) {\n        if (typeof vueServiceBubble[id] === 'object') {\n            return;\n        }\n        const template = jQuery(\"#serviceBubble\").html();\n        if (!id) {\n            id = 'serviceBubble';\n        } else {\n            if (jQuery(\"#\" + id).css(\"height\")) {\n                const pxH = jQuery(\"#\" + id).css(\"height\").replace(\"px\", \"\");\n                if (pxH) {\n                    imgOut.h = pxH;\n                    imgOut.w = jQuery(\"#\" + id).css(\"width\").replace(\"px\", \"\");\n                }\n                \/\/ await sleep(500);\n            } else {\n                console.warn(\"Image's element not existing: \" + id);\n                return;\n            }\n            \/\/ const template = jQuery(\"#serviceBubble\").html();\n            jQuery(\"#\" + id).html(template);\n        }\n        vueServiceBubble[id] = new Vue({\n          el: \"#\" + id,\n          data: {\n                placeType: service.type,\n                placeName: service.name,\n                placeDist: service.dist,\n\n                lat: satImg.lat,\n                lng: satImg.lng,\n                zoom: satImg.zoom,\n                layers: satImg.layers,\n                \n                waitingStuff: true,\n                \n                bbox: {leftdown: {}, rightup: {}},\n\n                h: imgOut.h,\n                w: imgOut.w,\n\n                maxH: window.innerHeight,\n                maxW: window.innerWidth,\n\n                backImg: '',\n                onRestaurants: false,\n                tAdvisor: 'https:\/\/www.tripadvisor.com\/Restaurants',\n                imgAdv: '\/nodejs\/flat-prices\/icons\/tadvisor.png'\n          },\n          mounted() {\n              this.getLatLngBox();\n              const eatThere = ['restaurant', 'cafe'];\n              if (eatThere.indexOf(this.placeType) > -1) {\n                  this.onRestaurants = true;\n              }\n          },\n          methods: {\n              getLatLngBox: async function() {\n                const q = '\/nodejs\/bbox?lng=' + satImg.lng + '&lat=' + satImg.lat + \n                          '&zoom=' + this.zoom + '&h=' + imgOut.h + '&w=' + imgOut.w;\n                  let bbox = 0;\n                  await jQuery.getJSON(q, function(data) {\n                      bbox = data;\n                  });\n                  if (bbox) {\n                      await sleep(1000);\n                      \/\/ Preventing too many calls \/ sec here for node...\n                  }\n                  \/\/ console.info(this.placeType, bbox);\n                  this.bbox = bbox;\n              },\n              bubbleImg(max) {\n                  \/\/ const locs = this.bbox;\n                  const ld = this.bbox.leftdown;\n                  const ru = this.bbox.rightup;\n                  \n                  const server = 'https:\/\/kaart.maaamet.ee\/wms\/';\n                  const fixedArgs = 'REQUEST=GetMap&SERVICE=WMS&VERSION=1.1.1&FORMAT=image\/png&BGCOLOR=0xFFFFFF&TRANSPARENT=TRUE&SRS=EPSG:3301&';\n                  const layersOut = 'LAYERS=' + this.layers + '&';\n                  const box = 'BBOX=' + ld.lng + ',' + ld.lat + ',' + ru.lng + ',' + ru.lat + '&'; \/\/541491.80101501,6589457.0255543,541625.95709475,6589616.0160731&';\n                  let sizeOut = 'WIDTH=' + this.w + '&HEIGHT=' + this.h + '&';\n                  if (max) {\n                      sizeOut = 'WIDTH=' + this.maxW + '&HEIGHT=' + this.maxH + '&';\n                  }\n                  const url = server + 'alus?' + fixedArgs + layersOut + box + sizeOut + 'STYLES=';\n                  return url;\n                  \/*\n                  return rootHB + 'genkml.php?url=1&lng=' +lng+ '&lat=' + lat + \n                          '&zoom=' +zoom+ '&layer=' + layers + '&w=' +w+ '&h=' +h;\n                  *\/\n              },\n              openWin(part1, part2) {                  \n                  const title = part1.toUpperCase() + ', ' + part2;\n                  const url = 'https:\/\/tere-tech.eu\/nodejs\/components\/airbrowser.php?layers=airfoto';\n                  const args = 'lat=' + this.lat + '&lng=' + this.lng + \n                              '&zoom=' + this.zoom + '&title=' + title;\n\n                  this.maxH = window.innerHeight;\n                  this.maxW = window.innerWidth;\n                  window.open(url + '&' + args, \"\",\n                                \"width=\" + this.maxW + \",height=\" + this.maxH + \n                                \",location=no\");\n              }\n              \/*\n              bubbleStyle2() {\n                      this.backImg = this.bubbleImg();\n                      return 'background-image: url(' + this.backImg + \n                              '); width: ' + this.w + 'px; height: ' + this.h + 'px;';\n              }\n              *\/\n          },\n      computed: {\n          \/*\n              bubbleStyle() {\n                  if (this.bbox.leftdown.lat > 0) {\n                      this.backImg = this.bubbleImg();\n                      return 'background-image: url(' + this.backImg + \n                              '); width: ' + this.w + 'px; height: ' + this.h + 'px;';\n                  }\n                  return '';\n              },\n              *\/\n              bubbleStyle2() {\n                  if (this.bbox.leftdown.lat > 0) {\n                      this.backImg = this.bubbleImg();\n                      return this.backImg;\n                  }\n                  return '';\n              }\n          }\n      });\n    }\n<\/script>\n\n<style scoped>\n    .bubble_look {\n       display: inline-block; \n       border: 8px inset gray;\n       color: white;\n       font-size: large;\n       text-shadow: 2px 2px blue;\n    }\n    \n    .img-container {\n      position: relative;\n    }\n\n    .overlay-text {\n      position: absolute;\n      top: 0;\n      left: 0;\n      z-index: 2;\n      display: flex;\n      flex-direction: column;\n      align-items: flex-start;\n    }\n\n    .text-line {\n      font-weight: bold;\n      color: white;\n      font-size: 20px;\n      margin-bottom: 5px;\n    }\n\n    .overlay-button {\n      position: absolute;\n      top: 0;\n      right: 0;\n      z-index: 2;\n    }\n<\/style><br\/>\n\n<div id='gainsBetterTable'>\n    <div style='display:none' v-show='fullLoaded'>\n        <h2>{{ mainTitle }}<\/h2> \n\n        <span style=\"font-size: large\">\n            <b class=\"gain_group\"\n               :title=\"descMore\"\n               style=\"background-color:green; color:white;\">\n                (<span class=\"glyphicon glyphicon-plus\"><\/span>) \n                {{ pcsUpdated[selectArea] }}\n            <\/b>\n            <b class=\"gain_group\"\n               :title=\"descNewOnes\"\n               style=\"background-color:darkorange; color:black;\">\n                (<span class=\"glyphicon glyphicon-star\"><\/span>) \n                {{ pcsNew[selectArea] }}\n            <\/b>\n        <\/span>\n    \n        <table>\n            <tr><td>\n\n            <b style=\"font-size: large; float:right\">\n            <input type=\"checkbox\" class=\"rooms_checkbox\"\n               v-model=\"filterRooms[1]\"> 1 {{ descRooms }}\n            <input type=\"checkbox\" class=\"rooms_checkbox\"\n                   v-model=\"filterRooms[2]\"> 2 {{ descRooms }}\n            <input type=\"checkbox\" class=\"rooms_checkbox\"\n                   v-model=\"filterRooms[3]\"> 3 {{ descRooms }}\n            <input type=\"checkbox\" class=\"rooms_checkbox\"\n                   v-model=\"filterRooms[4]\"> >3 {{ descRooms }}\n            <\/b>\n\n            <\/td><\/tr>\n            <tr><td>\n\n            <span style=\"float:right; font-size: xx-large; display:none\" \n                  v-show='fullLoaded'>\n                <b style='color: gray'>{{ descMenu }}<\/b>\n                <select @change=\"zeroLists()\" v-model=\"selectArea\">\n                    <option value=\"\">{{ descSelect.toUpperCase() }}<\/option>\n                    <option v-for=\"item in subs\" :value=\"item\"> \n                        {{ item }}\n                        [{{ countsOfActive(item) }}]\n                    <\/option>\n                <\/select>\n            <\/span>\n\n            <\/td><\/tr>\n        <\/table>\n    <\/div>\n\n    <table style='display:none' v-show='fullLoaded'>\n        <thead>\n            <th><\/th>\n            <th>{{ descHome }}<\/th>\n            <th>{{ descStatus }}<\/th>\n        <\/thead>\n        <tbody> \n            <tr v-for=\"item in keys\" v-bind:key=\"item.key\"\n                v-if=\"showAll || homeVisible(item)\">\n                <td v-show=\"!item.chart\">\n                    <div v-bind:id=\" 'flat_' + item.key \" \n                         :style=\"fotoDims\">\n                        [ {{ item.address }} image ]\n                    <\/div>\n                <\/td>\n                <td v-show=\"item.chart\">\n                    <div v-bind:id=\" 'chart_' + item.key \" \n                         :style=\"fotoDims\">\n                    <\/div>\n                <\/td>\n                <td style=\"font-size: xx-large; color: #0505bd\">\n                    <b style=\"color:blue; font-size: x-large; text-decoration: underline\">\n                        {{ item.address.toUpperCase() }}\n                    <\/b>\n                    \n                    <br\/>\n                    \n                    <img v-bind:src=\"alePath + 'ale_m2.png'\">\n                    {{ item.m2.replace('.', ',') }} m2<br\/>\n                    \n                    <img v-bind:src=\"alePath + 'ale_rooms.png'\">\n                    {{ item.rooms }} {{ descRooms }}<br\/>\n                    \n                    <img v-bind:src=\"alePath + 'ale_floor.png'\">\n                    {{ fixFloors(item.floors) }}<br\/>\n                    \n                    <img v-bind:src=\"alePath + 'ale_years.png'\">\n                    {{ builtYear(item.built) }}\n                    \n                    <p>\n                    <button :disabled='!enoughRights' \n                            @click='makeTheBid(item)'\n                            class='btn btn-info btn-block btn-lg'>\n                        <img src='\/balticfinns\/wp-content\/uploads\/2021\/09\/ethereum.png' width='24'>\n                        {{ descAct1 }} \n                        <a href=\"\/balticfinns\/index.php\/deals-types-sopimustyypit\/\" \n                           title=\"Check out Web3's deals all details\" target=\"_blank\" rel=\"noopener\">\n                            <span class=\"glyphicon glyphicon-question-sign\" \n                                  style=\"font-size: xx-large;\"><\/span>\n                        <\/a>\n                        <br\/>\n                        <b>{{ descAct2 }}<\/b>\n                    <\/button>\n                    <\/p>\n                <\/td>\n                <td style=\"font-size: x-large;\">\n                    <div class=\"prices_figs\">\n                        <span v-if=\"item.event === '-'\" class=\"glyphicon glyphicon-flag\"><\/span>\n                        <span v-if=\"item.event === 0\" class=\"glyphicon glyphicon-arrow-right\" \n                              title='Viime muutos: 0%'\n                              style=\"color: darkorange;\"><\/span>\n                        <span v-if=\"item.event > 0\" class=\"glyphicon glyphicon-arrow-up\" \n                              :title='\"Viime muutos: +\" + Math.round(item.event) + \"%\"'\n                              style=\"color: darkred;\"><\/span>\n                        <span v-if=\"item.event < 0\" class=\"glyphicon glyphicon-arrow-down\" \n                              :title='\"Viime muutos:\" + Math.round(item.event) + \"%\"'\n                              style=\"color: green;\"><\/span>\n                    \n                        {{ descSale }}\n                            <button @click=\"goPortal(item)\" \n                                    class=\"btn btn-success\" \n                                    style=\"cursor:pointer; float:right;\" \n                                    v-bind:title=\"descLink\"> \n                                <img style=\"width: 32px; height: 32px; padding: 4px\" \n                                     :src=\"alePath + 'kv.gif'\"> \n                                <span class=\"glyphicon glyphicon-new-window\" \n                                      style=\"font-size: large; color: black; padding: 4px;\"><\/span>\n                            <\/button>\n                        \n                            <span style='font-size: xx-large;'>\n\n                                <span class=\"glyphicon glyphicon-hourglass\" \n                                      style=\"color: navy;\"><\/span>\n                            <\/span>\n                            \n                        <br\/>\n                        <img v-bind:src=\"alePath + 'price2.png'\" style=\"width: 60px\">\n                        <b class=\"kpi\">\n                            {{ item.price }} \u20ac <\/b>\n                        <br>\n                        <img v-bind:src=\"alePath + 'price2.png'\" style=\"width: 60px\">\n                        \/\n                        <img v-bind:src=\"alePath + 'ale_m2.png'\" width=\"32\">\n                        {{ (item.price \/ item.m2).toFixed(0).replace('.', ',') }} \u20ac\/m2\n                    <\/div>\n\n                    <div class=\"gains_figs\">\n                        <p>\n                            <b v-show=\"!item.newbie\" class=\"gain_group\"\n                               :title=\"descMore\"\n                               style=\"background-color:green; color:white;\">\n                                (<span class=\"glyphicon glyphicon-plus\"><\/span>)<\/b>\n                            <b v-show=\"item.newbie\" class=\"gain_group\"\n                               :title=\"descNewOnes\"\n                               style=\"background-color:darkorange; color:black;\">\n                                (<span class=\"glyphicon glyphicon-star\"><\/span>)<\/b>\n                            {{ descGain }}\n                            \n                            \n                            <button @click=\"goHB(item)\" \n                                    class=\"btn btn-info\" \n                                    style=\"cursor:pointer; float:right;\" \n                                    :title=\"descHB\"> \n                                <img :src=\"alePath + 'hawk_small.png'\" style=\"width:36px; height:36px\">\n                                <span class=\"glyphicon glyphicon-new-window\" \n                                      style=\"font-size: large; color: white; padding: 4px;\"><\/span>\n                            <\/button>\n                            <button class=\"btn btn-success style_gmail\" \n                               @click=\"getMailLink(item)\" \n                               :title=\"descMail\" \n                               target=\"_blank\">\n                                <span class=\"style_gmail2\">\n                                    <svg style=\"display:block;\" \n                                         focusable=\"false\" \n                                         aria-hidden=\"true\" \n                                         xmlns=\"http:\/\/www.w3.org\/2000\/svg\" \n                                         width=\"100%\" \n                                         height=\"100%\" \n                                         viewBox=\"0 0 32 32\">\n                                        <path fill=\"white\" d=\"M2.902 6.223h26.195v19.554H2.902z\"><\/path>\n                                        <path fill=\"#E14C41\" \n                                              class=\"\" \n                                              d=\"M2.902 25.777h26.195V6.223H2.902v19.554zm22.44-4.007v3.806H6.955v-3.6h.032l.093-.034 6.9-5.558 2.09 1.77 1.854-1.63 7.42 5.246zm0-.672l-7.027-4.917 7.028-6.09V21.1zm-1.17-14.67l-.947.905c-2.356 2.284-4.693 4.75-7.17 6.876l-.078.06L8.062 6.39l16.11.033zm-10.597 9.61l-6.62 5.294.016-10.914 6.607 5.62\">                                        \n                                        <\/path>\n                                    <\/svg>\n                                <\/span>\n                            <\/button>\n                        <\/p>\n                        \n                        <div>\n                            <img v-bind:src=\"alePath + 'c_bag.png'\">\n                            \/\n                            <img v-bind:src=\"alePath + 'ale_years.png'\" width=\"16\">\n                            <b>\n                                +{{ Math.round(item.gainOfWeek \/ 7) }} \u20ac\/{{ descUnit2 }} \n                                ({{ (gainPrcnt(item, true) \/ 7).toFixed(1) }}%)\n                            <\/b>\n                        <\/div>\n                        \n                        <div>\n                            <img v-bind:src=\"alePath + 'c_bag.png'\">\n                            \/\n                            <img v-bind:src=\"alePath + 'ale_years.png'\" width=\"24\">\n                            <b>\n                                +{{ item.gainOfWeek }} \u20ac\/{{ descUnit1 }} \n                                ( {{ Math.round(gainPrcnt(item, true)) }}%\n                                <span v-show=\"gainPrcnt(item, 1) === maxWeekly\">\n                                    <span class=\"glyphicon glyphicon-certificate bestGainers\"><\/span>\n                                <\/span>\n                                )\n                            <\/b>\n                        <\/div>\n                        \n                        <div>\n                            <button v-if='!enoughRights' \n                                    @click=\"joinIn()\"\n                                    class='btn bnt-info mem_butt' style=\"float:right\">\n                                {{ descJoin }}\n                                <span class=\"glyphicon glyphicon-new-window mem_butt\" \n                                      style=\"padding: 4px;\"><\/span>\n                            <\/button>\n                            \n                            <div v-if='enoughRights'>\n                                <img v-bind:src=\"alePath + 'c_bag.png'\">\n                                <b class=\"kpi\">\n                                    +{{ item.gain }} \u20ac \n                                    (\n                                    {{ Math.round(gainPrcnt(item)) }}% \n                                    <span v-show=\"gainPrcnt(item, 0) === maxAll\"> \n                                        <span class=\"glyphicon glyphicon-certificate bestGainers\"><\/span>\n                                    <\/span>\n                                    )\n                                <\/b>\n                                <div>\n                                    <img v-bind:src=\"alePath + 'c_bag.png'\"> \n\n                                    <input type=\"checkbox\" class=\"gain_checkbox\"\n                                           v-model=\"keys[item.key].chart\"\n                                           @click=\"showChart(item.key, item.address)\">\n\n                                    <button class=\"prices_figs\" \n                                          style=\"cursor: pointer; border-radius: 8px;\" \n                                          @click=\"switchGain(item)\">\n                                        {{ descCheck }}\n                                        <img v-bind:src=\"alePath + 'price2.png'\" \n                                             style=\"width: 40px;\">\n                                    <\/button>\n                                <\/div>\n                            <\/div>\n                        <\/div>\n                        \n                        <br\/>\n                        <div>\n                            <span class=\"glyphicon glyphicon-gift\" \n                                  style=\"font-size: xx-large; color: green; padding: 4px;\"><\/span>\n                            {{ gainClusionMsg(item.event) }}\n                            <span v-if=\"item.event === 0\" class=\"glyphicon glyphicon-equalizer\"><\/span>\n                            <span v-if=\"item.event < 0\">\n                                <span class=\"glyphicon glyphicon-hourglass\" style=\"color: navy;\"><\/span>\n                                <span class=\"glyphicon glyphicon-arrow-down\" style=\"color: green;\"><\/span>\n                            <\/span>\n                        <\/div>\n                    <\/div>\n                <\/td>\n            <\/tr>\n        <\/tbody>\n    <\/table>\n<\/div>\n\n<!-- <\/template> -->\n\n<script>\n    \/\/ Shows & calculates gains tables for each area of city when asked in WP's dynamic page.\n    \n    async function gainsTable(data, areas) { \n        if (!data) {\n            console.error('No gains data given for its table !');\n            return;\n        }\n        let gainers = data.changeAmounts.gainMore;\n        gainers = gainers.concat(data.newSales);\n        let subsF = {};\n        let keys = [];\n        console.info(gainers);\n        for (let i in gainers) {\n            const sub = gainers[i].area;\n            subsF[sub + data.date] = 1;\n            if (typeof keys[sub] === 'undefined') {\n                keys[sub] = [];\n            }\n            const k = gainers[i].key;\n            keys.push(k);\n        }\n        const files = Object.keys(subsF);\n        const qData = {date: data.date, areas: files, keys: keys};\n        console.info('Going out for indexed homes ...');\n        homes = 0;\n        await jQuery.post(\"\/nodejs\/keys2offers\/\", qData, function(list) {\n              homes = list;\n              console.log(homes);\n        }, \"json\");\n        \n        if (typeof homes !== 'object') {\n            console.warn('Failed to fetch gains table: ', homes);\n            return; \n        }\n        userInfo = await getUserInfo();\n        \n        myBorders = {};\n        await getBorders('Tallinn', '', 1, 1);\n\n        vueGainTable = new Vue({\n          el: \"#gainsBetterTable\",\n          data: {\n              domain: window.location.protocol + '\/\/' + window.location.host,\n              mainTitle: getMsg(1249),\n              subs: areas,\n              chartData: data,\n              date: data.date,\n              fullLoaded: false,\n              hasRights: false,\n              inFiles: files,\n              filterRooms: [1, 1, 1, 0, 0],\n              \n              fotoDims: 'width: 440px; height: 380px; background-color: #EEE',\n              \n              showAll: false,\n              homeDetails: [],\n              homePcs: {},\n              roomsPcs: {},\n              pcsUpdated: {},\n              pcsNew: {},\n              \/\/ gainsCharts: {},\n              allCharts: false,\n              \n              selectArea: '',\n              alePath: '\/nodejs\/flat-prices\/icons\/',\n              \n              descMenu: getMsg(1245),\n              descSelect: getMsg(1246), \/\/ ***\n              \n              descLink: getMsg(221),\n              descHB: getMsg(1233),\n              descRooms: getMsg(1234),\n              descHome: getMsg(1235),\n              descStatus: getMsg(1236), \n              \n              descMore: getMsg(1230),\n              descNewOnes: getMsg(1232),\n              \n              descAct2: getMsg(1237),\n              descAct1:  getMsg(1238),\n              descMail: \"Gmail market's valuation link for this sale & check it again later\",\n              \n              descSale: getMsg(1239),\n              descGain: getMsg(1240),\n              \n              descJoin: getMsg(1241),\n              descCheck: getMsg(1242),\n              \n              descUnit1: getMsg(1243),\n              descUnit2: getMsg(1244),\n              \n              keys: {},\n              \n              homeDetailsVisible: false,\n              \n              zoom: 0.22, \n              layers: 'of10000',\n              \n              imgList: {},\n              imgList2: [],\n              \n              fotoDown: 0,\n              salesInTable: 0,\n              \n              borders: myBorders,\n              \n              maxWeekly: 0,\n              maxAll: 0,\n              \n              fotosDone: {}\n          },\n          mounted() {\n              \/\/ this.borders = myBorders;\n              this.setHomes(homes);\n              this.fullLoaded = true;\n              \/\/ this.getFotos();\n          },\n          beforeUpdate() {\n              this.salesInTable = 0;\n          },\n          updated() {\n              let visibles = [];\n              for (let k in this.keys) {\n                  const h = this.keys[k];\n                  if (this.homeVisible(h)) {\n                      visibles.push(h);\n                  }\n              }\n              this.homePcs[this.selectArea] = visibles.length;\n              console.info('IN TABLE: ', visibles);\n              this.getFotos2(visibles);\n          },\n          methods: {\n              setHomes(newOnes) {\n                  let minPcs = 1000;\n                  let homesNew = [];\n                  for (let sub in newOnes) {\n                      \/\/ let cH = homes;\n                      homesNew = homesNew.concat(newOnes[sub]);\n                      if (newOnes[sub].length < minPcs) {\n                          minPcs = newOnes[sub].length;\n                          this.selectArea = sub;\n                      }\n                      this.homePcs[sub] = newOnes[sub].length;\n                      if (this.subs.indexOf(sub) === -1) {\n                          this.subs.push(sub);\n                      }\n                      this.roomsPcs[sub] = {};\n                  }\n                  this.indexTable(homesNew);\n                  \n                  this.homeDetails = homesNew;\n                  this.homeDetailsVisible = true;\n                  \/\/ jQuery(\"#gainsBetterTable\").css(\"display\", \"block\");\n              },\n              homeVisible(item) {\n                  if (typeof item !== 'object') {\n                      return false;\n                  }\n                  if (this.selectArea === item.town_area && this.inArea(item) && this.checkRooms(item.rooms)) {\n                      return true;\n                  }\n                  return false;\n              },\n              getFotos2: async function(imgList) {\n                  if (!imgList.length) {\n                      return;\n                  }\n                  const everyPcs = 5;\n                  const imgOut = {h: 0, w: 0};\n                  let satImg = {lat: 0, lng: 0, \n                                zoom: this.zoom, layers: this.layers};\n                  let service = {type: '', name: '', dist: ''};\n                  console.info('Getting next fotos: ' + imgList.length);\n                  for (let i in imgList) {\n                      const id = 'flat_' + imgList[i].key;\n                      if (!this.fotosDone[id]) {\n                          this.fotosDone[id] = 1;\n                      \n                          const poi = imgList[i].poi;\n                          satImg.lat = poi.lat;\n                          satImg.lng = poi.lon;\n\n                          service.type = imgList[i].address;\n                          service.name = imgList[i].town_area;\n\n\n                          console.info('New Foto: ' + id);\n\n                          newServiceBubble(service, satImg, imgOut, id);\n\n                          this.fotoDown++;\n                          if (this.fotoDown % everyPcs === 0) {\n                              console.info('SLEEP ...', this.fotoDown);\n                              await sleep(2000);\n                          }\n                      }\n                  }\n              },\n              pushImg(poi, key, addr, area) {\n                  if (!poi) {\n                      return '';\n                  }\n                  this.salesInTable++;\n                  this.imgList['flat_' + key] = [addr, area, poi];\n                  return '';\n              },\n              getFotos: async function() {\n                  if (this.imgList === {}) {\n                      return;\n                  }\n                  const everyPcs = 5;\n                  const imgOut = {h: 0, w: 0};\n                  let satImg = {lat: 0, lng: 0, \n                                zoom: this.zoom, layers: this.layers};\n                  let service = {type: '', name: '', dist: ''};\n                  for (let id in this.imgList) {\n                      const poi = this.imgList[id][2];\n                      satImg.lat = poi.lat;\n                      satImg.lng = poi.lon;\n                      \n                      service.type = this.imgList[id][0];\n                      service.name = this.imgList[id][1];\n\n                      newServiceBubble(service, satImg, imgOut, id);\n                      \n                      this.fotoDown++;\n                      if (this.fotoDown % everyPcs === 0) {\n                          console.info('SLEEP ...', this.fotoDown);\n                          await sleep(2000);\n                      }\n                  }\n                  \/\/ await nextTick();\n                  \/\/ this.homePcs[this.selectArea] = this.salesInTable;\n              },\n              checkRooms(nro) {\n                  if (nro < 4) {\n                      return this.filterRooms[nro];\n                  }\n                  return this.filterRooms[4];\n              },\n              showChart(key, street) {\n                  \/\/ console.info(this.keys[key].chart);\n                  if (this.keys[key].chartDone) {\n                      return;\n                  }\n                  let that = this;\n                  const q = '\/nodejs\/gains_of_sale?k=' + key + '&s=' + this.selectArea;\n                  jQuery.getJSON(q, function(events) {\n                      console.info(events);\n                      that.keys[key].chartDone = true;\n                      const id = 'chart_' + key;\n                        let myEChart = new hbEcharts(id);\n                        myEChart.gainsChart(\n                          street,\n                          'Price',\n                          'Gain',\n                          events.sales.dates,\n                          events.sales.prices,\n                          events.gains,\n                          '\u20ac'\n                        );\n                  });\n              },\n              getImg(poi, id, addr, area) {\n                  if (!(poi.lat > 0 && poi.lon > 0)) {\n                      return '';\n                  }                  \n                    const satImg = {lat: poi.lat, lng: poi.lon, \n                                    zoom: this.zoom, layers: this.layers};\n                    const imgOut = {h: 200, w: 200};\n                    const service = {type: addr, name: area, dist: ''};\n                    \/\/ newServiceBubble(service, satImg, imgOut, 'flat_' + id);\n                    return '';\n              },\n              indexTable(homes) { \n                  \/\/ let toHome = {}; \n                  for (let h in homes) {\n                      this.keys[homes[h].key] = homes[h];\n                      this.statRooms(homes[h]);\n                  }\n                  let weeklyMoves = this.chartData.changeAmounts.gainMore;\n                  console.info('Updated', weeklyMoves);\n                  for (let i in weeklyMoves) {\n                      const key = weeklyMoves[i].key;\n                      \/\/ console.info(key);\n                      if (typeof this.keys[key] === 'object') {\n                          this.keys[key].gain = -weeklyMoves[i].to;\n                          this.keys[key].gainOfWeek = weeklyMoves[i].diff;\n                          this.keys[key].chart = false;\n                          this.keys[key].chartDone = false;\n                          this.updatePcs(this.pcsUpdated, weeklyMoves[i].area);\n                      } else {\n                          console.warn('Not home found for key: ', key);\n                      }\n                      \/\/ this.gainsCharts[key] = false;\n                  }\n                  weeklyMoves = this.chartData.newSales;\n                  console.info('New', weeklyMoves);\n                  for (let i in weeklyMoves) {\n                      const key = weeklyMoves[i].key;\n                      if (typeof this.keys[key] === 'object') {\n                          this.keys[key].gain = -weeklyMoves[i].to;\n                          this.keys[key].gainOfWeek = this.keys[key].gain;\n                          this.keys[key].chart = false;\n                          this.keys[key].chartDone = false;\n                          this.keys[key].newbie = true;\n                          this.updatePcs(this.pcsNew, weeklyMoves[i].area);\n                      } else {\n                          console.warn('Not home found for key: ', key);\n                      }\n                  }\n              },\n              updatePcs(arr, sub) {\n                  if (typeof arr[sub] !== 'number') {\n                      arr[sub] = 0;\n                  }\n                  arr[sub]++;\n              },\n              statRooms(home) {\n                  const sub = home.town_area;\n                  const rooms = home.rooms;\n                  if (typeof this.roomsPcs[sub][rooms] !== 'number') {\n                      this.roomsPcs[sub][rooms] = 0;\n                  }\n                  this.roomsPcs[sub][rooms]++;                  \n              },\n              countsOfActive(sub) {\n                  let sum = 0;\n                  const filters = this.filterRooms;\n                  for (let r in filters) {\n                      if (filters[r] && this.roomsPcs[sub][r] > 0) {\n                          sum = sum + this.roomsPcs[sub][r];\n                      }\n                  }\n                  return sum;\n              },\n              builtYear(nro) {\n                  if (+nro > 1000) {\n                      return nro;\n                  }\n                  return '';\n              },\n              fixFloors(floorStr) {\n                  if (typeof floorStr !== 'string') {\n                      return floorStr;\n                  }\n                  const pair = floorStr.split('\/');\n                  if (pair.length === 2) {\n                      if (+pair[0] > +pair[1]) {\n                          return pair[1] + '\/' + pair[0];\n                      }\n                  }\n                  return floorStr;\n              },\n              gainPrcnt(item, weekly) {\n                  let gainW = 0;\n                  if (weekly) {\n                      gainW = this.prcntIt(+item.gainOfWeek, item.price);\n                      if (gainW > this.maxWeekly) {\n                          this.maxWeekly = gainW;\n                      }\n                  } else {\n                      \/\/ gainW = +item.gain;\n                      gainW = this.prcntIt(+item.gain, item.price);\n                      if (gainW > this.maxAll) {\n                          this.maxAll = gainW;\n                      }\n                  }\n                  \/\/ let prcnt = Math.round(100 * gainW \/ (item.price));\n                  return gainW;\n              },\n              prcntIt(from, total) {\n                  return 100 * from \/ (total);\n              },\n              gainClusionMsg(pChange) {\n                    if (+pChange < 0) {\n                        return getMsg(1248);\n                    }\n                    return getMsg(1247);\n                },\n              goPortal(home) {\n                  if (home.linkID) {\n                    urlX = \"https:\/\/www.kv.ee\/\" + home.linkID;\n                    window.open(urlX);\n                    return;\n                    }\n                    link2flat(home.address, +home.m2, +home.price);\n              },\n              goHB(saleOfHome) {\n                  const lat = saleOfHome.poi.lat;\n                  const lng = saleOfHome.poi.lon;\n                  const k = saleOfHome.key;\n                  const sub = saleOfHome.town_area;\n                  const url = this.domain + '\/balticfinns\/hb.php?k=' + k + \n                              '&sub=' + sub + '&d=' + this.date;\n                  \/\/ const url = this.domain + '\/balticfinns\/hb.php#18\/' + lat + '\/' + lng;\n                          \/\/ '\/' + this.date + '\/' + k;\n                  window.open(url);\n              },\n              switchGain(item) {\n                  this.keys[item.key].chart = !this.keys[item.key].chart;\n                  this.showChart(item.key, item.address);\n              },\n              inArea(sale) {\n                  if (typeof sale.poi !== 'object') {\n                      console.warn('Not lat & lng found', sale);\n                      return false;\n                  }\n                  const latLng = [sale.poi.lat, sale.poi.lon];\n                  if (vueDB.inside(latLng, this.selectArea)) {\n                      return true;\n                  }\n                  console.warn('Home was dropped from table', sale.address.toUpperCase(), latLng);\n                  this.findItsArea(sale, latLng);\n                  return false;\n              },\n              findItsArea: async function(sale, poi) {\n                  const addr = sale.address.toUpperCase();\n                  for (let sub in this.borders) {\n                      if (vueDB.inside(poi, sub)) {\n                          console.warn(addr + ' sale belongs to area ' + sub);\n                      }\n                  }\n              },\n            genHome(active) {\n                \/\/ return {};\n        \n                active.bidTotal = active.price + active.gain;\n                  const poi = {lat: active.poi.lat, lng: active.poi.lng, lon: active.poi.lng};\n                  const h = {address: active.address, town_area: this.town_area,\n                          bid: active.bidTotal, gain: active.bidTotal,\n                          m2: active.m2, size: active.m2, rooms: active.rooms,\n                          built: active.built, floors: active.floors,\n                          material: active.material, key: \"-\", \n                          date: this.date, poi: poi};\n                  return h;\n                  \n              },\n              zeroLists() {\n                  this.imgList = {};\n                  this.maxWeekly = 0;\n                  this.maxAll = 0;\n                  this.fotosDone = {};\n              },\n              makeTheBid(item) {\n                  \/*\n              }\n                  ccc.login(userInfo, 0); \n                  ccc.setHome(this.genHome(item), 1); \n                  vueHB.hideAllControls();\n                  *\/\n              },\n              getMailLink(sale) {\n                  const mailer = 'https:\/\/mail.google.com\/mail\/u\/0\/';\n                  const subject = 'Edullinen+ja+kannattava+asuntomyynti:+' + \n                          sale.address + '+(' + sale.rooms + 'H. ' + sale.price + '+euro)';\n                  const script = window.location.host + '\/balticfinns\/hb.php';\n                  const url = script + '?k=' + sale.key + \n                          '%26sub=' + sale.town_area + '%26d=' + this.date;\n                  const body = 'Link:' + url;\n                  const act = mailer + '?ui=2&fs=1&tf=cm&su=' + subject + '&body=' + body;\n                  window.open(act);\n                  return act;\n                },\n                joinIn() {\n                    console.info('Go to join member page !');\n                    const reDir = '\/balticfinns\/index.php\/ne-edullisemmat-asunnot-alueineen\/';\n                    const url = 'https:\/\/tere-tech.eu\/balticfinns\/wp-login.php?redirect_to=' + reDir;\n                    window.open(url);\n                }\n              \/*\n              showPL(profit) {\n                  if (this.hasRights) {\n                      return '+' + profit + ' \u20ac';\n                  }\n                  return '(N\u00e4kyvyys j\u00e4senillemme)';\n              }\n              *\/\n          },\n          computed: {\n                enoughRights() {\n                    if (userLevel('administrator') || userLevel('house_developer') || \n                          userLevel('home_buyer') || userLevel('home_seller')) {\n                              return true;\n                    }\n                    return false;\n                }\n          }\n        });\n\/*\n        async function getUserInfo() {\n            const q = '\/balticfinns\/wp-content\/plugins\/flat-prices\/contracts\/user_info.php';\n            const response = await fetch(q);\n            const data = await response.json();\n            return data;\n        };\n        *\/\n    }\n\n\n<\/script>\n\n<style scoped>\n    .prices_figs {\n        color: darkred;\n        background-color: #ffd392;\n        text-shadow: 1px 2px black;\n        border: 5px outset gray;\n    }\n    .gains_figs {\n        color: green;\n        background-color: #adf9ad;\n        text-shadow: 2px 1px black;\n        border: 5px outset gray;\n    }\n    .kpi {\n        border: 4px double navy; \n        font-size: x-large; \n        padding: 4px;\n        border-radius: 8px;\n    }\n    .gain_group {\n        padding:6px;\n        border: 1px solid black;\n        font-size: xx-large;\n    }\n    .bestGainers {\n        color: lime;\n        font-size: large;\n        text-shadow: 2px 3px darkgreen;\n    }\n    .mem_butt {\n        font-size: medium; \n        color: white; \n    }\n    .gain_checkbox {\n        width: 30px; \n        height: 30px;\n    } \n    .rooms_checkbox {\n        width: 20px; \n        height: 20px;\n    }\n    .style_gmail {\n        float:right;\n    }\n    .style_gmail2 {\n        background-color:#5cb85c;\n        width:24px;\n        height:24px;\n        margin: 4px;\n        border: 1px solid white;\n        display:inline-block;\n        overflow:hidden;\n    }\n<\/style>\n\n\n\n<script>\n\ndiffTops('proffChanges');\n\n<\/script>\n\n\n\n<table class=\"announcement\"  style=\"text-shadow:1px 1px navy; font-size: large\" ><tr><td><ul><li><a class=\"noteitem\" href=\"\/balticfinns\/hb.php\" target=\"_blank\"><img src=\"\/balticfinns\/wp-content\/plugins\/flat-prices\/icons\/hawk_small.png\" > HOME BROWSER | KOTISELAIN<\/a><\/li><\/ul><\/td><td><a href=\"\/balticfinns\/wp-login.php?redirect_to=hb.php\" target=\"_blank\"><span class=\"glyphicon glyphicon-log-in\" style=\"font-size:xx-large; color:navy\"><\/span><\/a><\/td><\/tr><\/table><div style=\"text-align: center\">\n    <b>\n        <a href=\"mailto:info@tere-tech.com\">\n            <span class=\"glyphicon glyphicon-envelope\" style=\"font-size:x-large\"><\/span> \n            info@tere-tech.com\n        <\/a>\n    <\/b>\n<\/div>\n\n","protected":false},"excerpt":{"rendered":"<p>Etujen muutokset asuinalueilta Etujen kasvut ulkokeh\u00e4ll\u00e4 ostajalle kertovat miten myyntikotien arvostukset ovat ymp\u00e4rist\u00f6\u00f6ns\u00e4 n\u00e4hden kasvaneet alueittain viimeisen seurantajakson ajalta. Alta l\u00f6yd\u00e4t suoraan tarkat tiedot mit\u00e4 avoimia asuntomyyntej\u00e4 n\u00e4m\u00e4 etujaan &amp; arvostustaan kasvattaneet oikeasti ovat ja kuinka paljon kukin myynti on liikahtanut markkinoilla (+ paljon muuta hyv\u00e4\u00e4 lis\u00e4tietoa).<\/p>\n","protected":false},"author":1,"featured_media":85918,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"_links":{"self":[{"href":"https:\/\/tere-tech.eu\/balticfinns\/index.php\/wp-json\/wp\/v2\/pages\/85581"}],"collection":[{"href":"https:\/\/tere-tech.eu\/balticfinns\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/tere-tech.eu\/balticfinns\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/tere-tech.eu\/balticfinns\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tere-tech.eu\/balticfinns\/index.php\/wp-json\/wp\/v2\/comments?post=85581"}],"version-history":[{"count":45,"href":"https:\/\/tere-tech.eu\/balticfinns\/index.php\/wp-json\/wp\/v2\/pages\/85581\/revisions"}],"predecessor-version":[{"id":85704,"href":"https:\/\/tere-tech.eu\/balticfinns\/index.php\/wp-json\/wp\/v2\/pages\/85581\/revisions\/85704"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tere-tech.eu\/balticfinns\/index.php\/wp-json\/wp\/v2\/media\/85918"}],"wp:attachment":[{"href":"https:\/\/tere-tech.eu\/balticfinns\/index.php\/wp-json\/wp\/v2\/media?parent=85581"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}