{"id":9,"date":"2025-06-29T21:40:35","date_gmt":"2025-06-29T21:40:35","guid":{"rendered":"https:\/\/blocoelivre.pt\/?page_id=9"},"modified":"2025-06-29T22:10:06","modified_gmt":"2025-06-29T22:10:06","slug":"map","status":"publish","type":"page","link":"https:\/\/blocoelivre.pt\/index.php\/map\/","title":{"rendered":"Mapa de propostas"},"content":{"rendered":"\n<script src=\"https:\/\/apis.google.com\/js\/api.js\"><\/script>\n        <script\n            src=\"https:\/\/maps.googleapis.com\/maps\/api\/js?key=AIzaSyBE2cM45EVUcFqJOMQiDNr8JFc8u2jBY3I&#038;callback=initMap&#038;v=weekly\"\n            defer><\/script>\n<link href=\"https:\/\/cdn.jsdelivr.net\/npm\/bootstrap@5.3.3\/dist\/css\/bootstrap.min.css\" rel=\"stylesheet\"\n    integrity=\"sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH\" crossorigin=\"anonymous\" \/>\n\n\n\n<div class=\"content\"><div id=\"map\">\n<\/div>\n<\/div>\n\n\n\n<div class=\"list\">\n            <div class=\"listHeader\">\n                <p style=\"display: none\">todo:<\/p>\n                <ul style=\"display: none\">\n                    <li>navbar a dar<\/li>\n                    <li>pesquisa<\/li>\n                    <li>freguesias<\/li>\n                <\/ul>\n                <input type=\"search\" class=\"form-control\" placeholder=\"\ud83d\udd0d Procurar propostas\"\n                    style=\"margin-bottom: 10px\" \/>\n                <button class=\"resetButton btn btn-light btn-outline-danger\"\n                    onclick=\"resetButton()\">\n                    Repor Mapa\n                <\/button>\n            <\/div>\n\n            <div class=\"accordion\" id=\"itemsAccordion\"><\/div>\n        <\/div>\n\n\n\n<style>\n\n\/* Propriedades do mapa *\/\n:root {\n    --bloco-color: #cc1515;\n    --bloco-color-light: #ff00000f;\n}\n.list {\n    padding: 10px;\n    padding-bottom: 0;\n    display: grid;\n    grid-template-rows: fit-content(0) 1fr;\n    overflow: auto;\n}\n.accordion {\n    overflow: auto;\n    --bs-accordion-active-bg: var(--bloco-color);\n    --bs-accordion-active-color: white;\n}\n.accordion-button {\n    padding: 10px;\n}\n.accordion-body {\n    padding: 10px;\n    background-color: var(--bloco-color-light);\n}\n.program {\n    padding: 5px;\n}\n.firstitem {\n    border-top: var(--bs-accordion-border-width) solid var(--bs-accordion-border-color);\n    border-top-left-radius: var(--bs-accordion-border-radius);\n    border-top-right-radius: var(--bs-accordion-border-radius);\n    overflow: hidden;\n}\n.parent {\n    overflow: hidden;\n    max-height: 100%;\n    height: 100%;\n}\n.content {\n    height: 500px;\n}\n#map {\n    border: 5px solid var(--bloco-color);\n    border-left: 0;\n    border-right: 0;\n    height: 100%;\n}\n.resetButton {\n    width: 100%;\n    max-height: fit-content;\n    text-align: center;\n    margin-bottom: 10px;\n    color: var(--bloco-color);\n}\n<\/style>\n\n\n\n<script>\n            let resetButton = () => {\n                if(current!=null) document.querySelector(\"#\" + current + \">h2>button\").click(); else resetMap();\n            }\n\n            let current = null;\n            let itemCount = 0;\n            let addItem = (header, body, id) => {\n                const item = document.createElement(\"div\");\n                item.className = \"accordion-item\";\n                item.id = id;\n                item.innerHTML = `\n        <h2 class=\"accordion-header\">\n            <button class=\"accordion-button  collapsed\" type=\"button\" data-bs-toggle=\"collapse\" data-bs-target=\"#collapse${itemCount}\"\n              aria-expanded=\"false\" \" aria-controls=\"collapse${itemCount}\" >\n              ${header}\n            <\/button>\n          <\/h2>\n            <div id=\"collapse${itemCount}\" class=\"accordion-collapse collapse\" data-bs-parent=\"#itemsAccordion\">\n            <div class=\"accordion-body\">\n             ${body}\n            <\/div>\n          <\/div>\n          `;\n                itemCount++;\n                document.getElementById(\"itemsAccordion\").appendChild(item);\n            };\n\n            let createBaseGeoJSON = () => {\n                return {\n                    type: \"FeatureCollection\",\n                    features: [],\n                };\n            };\n\n            let filter = (text) => {\n                let items = Array.from(document.getElementsByClassName(\"accordion-item\"));\n                let first = true;\n                items.forEach((e) => {\n                    let setVisible = true;\n\n                    e.classList.remove(\"firstitem\");\n                    e.style[\"border-top\"] = \"\";\n                    if (\n                        e\n                            .querySelector(\"button\")\n                            .textContent.toUpperCase()\n                            .search(text.target.value.toUpperCase()) == -1\n                    ) {\n                        e.style.display = \"none\";\n                        setVisible = false;\n                    } else {\n                        e.style.display = \"\";\n                        if (first) {\n                            first = false;\n                            e.classList.add(\"firstitem\");\n                            e.style[\"border-top\"] =\n                                \"var(--bs-accordion-border-width) solid var(--bs-accordion-border-color)\";\n                        }\n\n                        setVisible = true;\n                    }\n\n                    let style = {};\n                    style[\"visible\"] = setVisible;\n                    map.data.overrideStyle(map.data.getFeatureById(e.id), style);\n                });\n            };\n\n            const input = document.querySelector(\"input\");\n            input.addEventListener(\"input\", filter);\n\n            function initMap() {\n                map = new google.maps.Map(document.getElementById(\"map\"), {\n                    zoom: 13.0,\n                    center: { lat: 41.11, lng: -8.62 },\n                    maxZoom: 16,\n                    disableDefaultUI: true,\n                    styles: [\n                        \/\/ Repeat this object for each feature.\n                        {\n                            featureType: \"poi.business\",\n                            stylers: [{ visibility: \"off\" }],\n                        },\n                    ],\n                });\n            }\n\n            let resetMap = () => {\n                map.data.revertStyle();\n                map.setZoom(13);\n                map.setCenter({ lat: 41.11, lng: -8.62 });\n                current = null;\n                input.value = \"\";\n                input.dispatchEvent(new Event(\"input\"));\n            };\n\n            let = fillMap = (geoJson) => {\n                map.data.addGeoJson(geoJson).forEach((element) => {\n                    for (let i = 0; i < 1; i++) {\n                        addItem(\n                            element.getProperty(\"name\"),\n                            element.getProperty(\"description\"),\n                            element.getId()\n                        );\n                    }\n\n                    document\n                        .querySelector(\"#\" + element.getId() + \">h2>button\")\n                        .addEventListener(\"click\", () => {\n                            \/\/ Reset map an remove selection if the accordion is closing\n                            if (element.getId() == current) {\n                                resetMap();\n                                return;\n                            }\n\n                            \/\/ change color of all elements and make the new one blocoRed\n                            current = element.getId();\n                            let defaultStyle = {};\n                            defaultStyle[\"fillColor\"] = \"#505050\";\n                            defaultStyle[\"strokeColor\"] = \"#404040\";\n                            let style = {};\n                            style[\"fillColor\"] = \"#cc1515\";\n                            style[\"strokeColor\"] = \"#cc1515\";\n                            map.data.revertStyle();\n                            map.data.setStyle(defaultStyle);\n                            map.data.overrideStyle(element, style);\n\n                            \/\/ change map to get into view of object\n                            maxLat = null;\n                            minLat = null;\n                            minLng = null;\n                            maxLng = null;\n                            element.getGeometry().forEachLatLng((latlng) => {\n                                if (maxLat == null || latlng.lat() > maxLat) maxLat = latlng.lat();\n                                if (minLat == null || latlng.lat() < minLat) minLat = latlng.lat();\n                                if (maxLng == null || latlng.lng() > maxLng) maxLng = latlng.lng();\n                                if (minLng == null || latlng.lng() < minLng) minLng = latlng.lng();\n                            });\n                            map.fitBounds(\n                                { north: maxLat, south: minLat, west: minLng, east: maxLng },\n                                0\n                            );\n                        });\n                });\n\n                map.data.addListener(\"click\", (element) => {\n                    if (current == element.feature.getId()) {\n                        return;\n                    }\n\n                    \/\/ Scroll to the matching accordion item\n                    document\n                        .querySelector(\"#\" + element.feature.getId() + \">h2>button\")\n                        .scrollIntoView(true, { behavior: \"smooth\" });\n                    document\n                        .querySelector(\"#\" + element.feature.getId() + \">h2>button\")\n                        .click();\n                });\n\n                window.initMap = initMap;\n            };\n\n            function start() {\n                \/\/ fetch data from sheets\n                gapi.client\n                    .init({\n                        apiKey: \"AIzaSyBE2cM45EVUcFqJOMQiDNr8JFc8u2jBY3I\",\n                    })\n                    .then(function () {\n                        return gapi.client.request({\n                            path: \"https:\/\/sheets.googleapis.com\/v4\/spreadsheets\/1htO7n_tHD7SQwVvDOAXBqazIHHAFCj2C_iVYZvF28lY\/values\/B2:D1000\",\n                        });\n                    })\n                    .then(\n                        function (response) {\n                            let geoJson = createBaseGeoJSON();\n                            if (response.result.values != null) {\n                                let currentLine = 0;\n                                \/\/ response structure:\n                                \/\/ name, description, geojson\n                                \/\/ name, description, geojson\n                                \/\/ ....\n                                response.result.values.forEach((line) => {\n                                    let newFeature = JSON.parse(line[2]).features[0];\n                                    newFeature[\"properties\"][\"name\"] = line[0];\n                                    newFeature[\"properties\"][\"description\"] = line[1];\n                                    newFeature[\"id\"] = \"feature_\" + currentLine++;\n                                    geoJson.features.push(newFeature);\n                                });\n                            }\n                            fillMap(geoJson);\n                        },\n                        function (reason) { }\n                    );\n            }\n\n            gapi.load(\"client\", start);\n\n            let navToContentMap = {\n                mapaSelector: [\"content\", \"list\"],\n                programaSelector: [\"program\"],\n            };\n\n            let selectContent = (selector, other) => {\n                let navs = Array.from(document.getElementsByClassName(\"nav-link\"));\n                navs.forEach((nav) => {\n                    if (nav.id == selector) {\n                        let text = nav.textContent;\n                        nav.innerHTML = \"<h5>\" + text + \"<\/h5>\";\n                        nav.classList.add(\"active\");\n\n                        navToContentMap[nav.id].forEach(\n                            (className) =>\n                                (document.querySelector(\".\" + className).style.display = \"\")\n                        );\n                    } else {\n                        let text = nav.textContent;\n                        nav.innerHTML = text;\n                        nav.classList.remove(\"active\");\n                        navToContentMap[nav.id].forEach(\n                            (className) =>\n                                (document.querySelector(\".\" + className).style.display = \"none\")\n                        );\n                    }\n                });\n                document.querySelector(\".navbar-toggler\").click();\n            };\n\n        <\/script>\n","protected":false},"excerpt":{"rendered":"<p>todo: navbar a dar pesquisa freguesias Repor Mapa<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"inline_featured_image":false,"footnotes":""},"class_list":["post-9","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/blocoelivre.pt\/index.php\/wp-json\/wp\/v2\/pages\/9","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blocoelivre.pt\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/blocoelivre.pt\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/blocoelivre.pt\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blocoelivre.pt\/index.php\/wp-json\/wp\/v2\/comments?post=9"}],"version-history":[{"count":7,"href":"https:\/\/blocoelivre.pt\/index.php\/wp-json\/wp\/v2\/pages\/9\/revisions"}],"predecessor-version":[{"id":41,"href":"https:\/\/blocoelivre.pt\/index.php\/wp-json\/wp\/v2\/pages\/9\/revisions\/41"}],"wp:attachment":[{"href":"https:\/\/blocoelivre.pt\/index.php\/wp-json\/wp\/v2\/media?parent=9"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}