{"id":17124,"date":"2026-05-03T13:56:56","date_gmt":"2026-05-03T10:56:56","guid":{"rendered":"https:\/\/ncyprus.com.tr\/map-explorer\/"},"modified":"2026-05-03T13:56:56","modified_gmt":"2026-05-03T10:56:56","slug":"map-explorer","status":"publish","type":"page","link":"https:\/\/ncyprus.com.tr\/nl\/map-explorer\/","title":{"rendered":"<span data-no-translation>Kaartverkenner<\/span>"},"content":{"rendered":"<style>\n        .ncy-map-explorer-wrapper {\n            display: flex;\n            width: 100%;\n            height: calc(100vh - 100px); \/* Adjust based on header height *\/\n            min-height: 600px;\n            background: #fff;\n            overflow: hidden;\n            font-family: 'Inter', sans-serif;\n            border-top: 1px solid #eaeaea;\n        }\n\n        \/* LEFT PANEL: Grid *\/\n        .ncy-map-sidebar {\n            width: 45%;\n            min-width: 400px;\n            max-width: 600px;\n            height: 100%;\n            background: #f9f9fb;\n            border-right: 1px solid #eaeaea;\n            display: flex;\n            flex-direction: column;\n            z-index: 10;\n        }\n        \n        .ncy-map-sidebar-header {\n            padding: 25px 30px;\n            background: #fff;\n            border-bottom: 1px solid #eaeaea;\n            box-shadow: 0 4px 20px rgba(0,0,0,0.02);\n            z-index: 2;\n        }\n        .ncy-map-sidebar-header h1 {\n            margin: 0 0 5px 0;\n            font-size: 24px;\n            font-weight: 700;\n            color: #101828;\n            letter-spacing: -0.5px;\n        }\n        .ncy-map-sidebar-header p {\n            margin: 0;\n            color: #667085;\n            font-size: 14px;\n        }\n\n        \/* Map Filters - Premium UI *\/\n        .ncy-map-filters {\n            display: flex;\n            flex-direction: column;\n            gap: 15px;\n            padding: 20px 30px;\n            background: #fff;\n            border-bottom: 1px solid #eaeaea;\n        }\n        .ncy-filters-row {\n            display: flex;\n            gap: 12px;\n            flex-wrap: wrap;\n        }\n\n        \/* Custom Selects *\/\n        .ncy-select-wrapper {\n            position: relative;\n            flex: 1;\n            min-width: 140px;\n        }\n        .ncy-select-wrapper select {\n            width: 100%;\n            appearance: none;\n            -webkit-appearance: none;\n            padding: 12px 35px 12px 15px;\n            border: 1px solid #e4e4e7;\n            border-radius: 10px;\n            font-size: 14px;\n            font-weight: 500;\n            color: #101828;\n            background: #f9f9fb;\n            cursor: pointer;\n            transition: all 0.3s ease;\n        }\n        .ncy-select-wrapper select:hover {\n            border-color: #B59A6D;\n            background: #fff;\n        }\n        .ncy-select-wrapper select:focus {\n            outline: none;\n            border-color: #B59A6D;\n            box-shadow: 0 0 0 4px rgba(181, 154, 109, 0.15);\n            background: #fff;\n        }\n        .ncy-select-wrapper::after {\n            content: '\u25be';\n            position: absolute;\n            right: 15px;\n            top: 50%;\n            transform: translateY(-50%);\n            pointer-events: none;\n            color: #667085;\n            font-size: 16px;\n        }\n        \n        \/* RTL Support for Selects *\/\n        [dir=\"rtl\"] .ncy-select-wrapper select {\n            padding: 12px 15px 12px 35px;\n        }\n        [dir=\"rtl\"] .ncy-select-wrapper::after {\n            right: auto;\n            left: 15px;\n        }\n\n        \/* Price Slider *\/\n        .ncy-price-filter-wrap {\n            margin-top: 10px;\n            padding: 0 10px;\n        }\n        .ncy-price-labels {\n            display: flex;\n            justify-content: space-between;\n            font-size: 13px;\n            font-weight: 600;\n            color: #667085;\n            margin-bottom: 12px;\n        }\n        .ncy-price-labels span {\n            color: #101828;\n        }\n        .noUi-target {\n            background: #eaecf0;\n            border: none;\n            box-shadow: none;\n            height: 6px;\n            border-radius: 4px;\n        }\n        .noUi-connect {\n            background: #B59A6D;\n        }\n        .noUi-handle {\n            border: 3px solid #fff;\n            background: #B59A6D;\n            border-radius: 50%;\n            box-shadow: 0 2px 6px rgba(0,0,0,0.15);\n            width: 20px !important;\n            height: 20px !important;\n            top: -7px !important;\n            right: -10px !important;\n            cursor: grab;\n        }\n        .noUi-handle::after, .noUi-handle::before {\n            display: none;\n        }\n\n        .ncy-map-results {\n            flex-grow: 1;\n            overflow-y: auto;\n            padding: 20px 30px;\n            background: #f9f9fb;\n            position: relative;\n        }\n\n        \/* Property Card Mini *\/\n        .ncy-mini-card {\n            display: flex;\n            background: #fff;\n            border-radius: 12px;\n            margin-bottom: 20px;\n            border: 1px solid #eaecf0;\n            overflow: hidden;\n            transition: all 0.3s ease;\n            text-decoration: none;\n            color: inherit;\n        }\n        .ncy-mini-card:hover {\n            transform: translateY(-3px);\n            box-shadow: 0 12px 24px rgba(16, 24, 40, 0.06);\n            border-color: #B59A6D;\n        }\n        .ncy-mini-img {\n            width: 140px;\n            min-width: 140px;\n            height: auto;\n            background-size: cover;\n            background-position: center;\n        }\n        .ncy-mini-content {\n            padding: 15px;\n            flex-grow: 1;\n        }\n        .ncy-mini-title {\n            font-size: 16px;\n            font-weight: 600;\n            color: #101828;\n            margin: 0 0 8px 0;\n            line-height: 1.4;\n            display: -webkit-box;\n            -webkit-line-clamp: 2;\n            -webkit-box-orient: vertical;\n            overflow: hidden;\n        }\n        .ncy-mini-price {\n            font-size: 18px;\n            font-weight: 700;\n            color: #B59A6D;\n            margin-bottom: 10px;\n        }\n        .ncy-mini-meta {\n            display: flex;\n            gap: 15px;\n            font-size: 13px;\n            color: #667085;\n        }\n\n        \/* Loading Overlay *\/\n        .ncy-map-loading {\n            position: absolute;\n            top: 0; left: 0; right: 0; bottom: 0;\n            background: rgba(249, 249, 251, 0.8);\n            backdrop-filter: blur(4px);\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            z-index: 10;\n            opacity: 0;\n            pointer-events: none;\n            transition: opacity 0.2s ease;\n        }\n        .ncy-map-loading.active {\n            opacity: 1;\n            pointer-events: all;\n        }\n        .ncy-spinner {\n            width: 40px; height: 40px;\n            border: 3px solid rgba(181, 154, 109, 0.2);\n            border-top-color: #B59A6D;\n            border-radius: 50%;\n            animation: ncySpin 1s linear infinite;\n        }\n        @keyframes ncySpin { 100% { transform: rotate(360deg); } }\n\n        \/* RIGHT PANEL: Map *\/\n        .ncy-map-container {\n            flex-grow: 1;\n            height: 100%;\n            position: relative;\n            z-index: 1;\n        }\n        #ncy-leaflet-map {\n            width: 100%;\n            height: 100%;\n        }\n\n        \/* Custom Map Markers (Airbnb Style) *\/\n        .ncy-price-marker {\n            background: #fff;\n            color: #101828;\n            border: 1px solid #eaecf0;\n            padding: 6px 12px;\n            border-radius: 20px;\n            font-weight: 700;\n            font-size: 14px;\n            box-shadow: 0 4px 12px rgba(0,0,0,0.1);\n            cursor: pointer;\n            transition: all 0.2s ease;\n            white-space: nowrap;\n            text-align: center;\n        }\n        .ncy-price-marker:hover, .ncy-price-marker.active {\n            background: #101828;\n            color: #fff;\n            border-color: #101828;\n            transform: scale(1.05);\n            z-index: 1000 !important;\n        }\n        \n        \/* Map Popup overrides *\/\n        .leaflet-popup-content-wrapper {\n            border-radius: 12px;\n            padding: 0;\n            overflow: hidden;\n            box-shadow: 0 20px 40px rgba(16, 24, 40, 0.15);\n            border: 1px solid rgba(255,255,255,0.4);\n            backdrop-filter: blur(10px);\n            background: rgba(255,255,255,0.95);\n        }\n        .leaflet-popup-content {\n            margin: 0;\n            width: 260px !important;\n        }\n        .ncy-popup-img {\n            width: 100%;\n            height: 140px;\n            background-size: cover;\n            background-position: center;\n        }\n        .ncy-popup-body {\n            padding: 15px;\n        }\n        .ncy-popup-title {\n            font-size: 15px;\n            font-weight: 600;\n            margin: 0 0 5px 0;\n            color: #101828;\n            line-height: 1.3;\n        }\n        .ncy-popup-price {\n            font-size: 16px;\n            color: #B59A6D;\n            font-weight: 700;\n            margin-bottom: 10px;\n        }\n        .ncy-popup-btn {\n            display: block;\n            width: 100%;\n            text-align: center;\n            background: #101828;\n            color: #fff !important;\n            padding: 8px 0;\n            border-radius: 6px;\n            text-decoration: none;\n            font-weight: 600;\n            font-size: 13px;\n        }\n        .ncy-popup-btn:hover {\n            background: #B59A6D;\n        }\n\n        \/* Responsive *\/\n        @media (max-width: 991px) {\n            .ncy-map-explorer-wrapper {\n                flex-direction: column;\n                height: auto;\n            }\n            .ncy-map-sidebar {\n                width: 100%;\n                min-width: 100%;\n                height: 500px;\n            }\n            .ncy-map-container {\n                height: 500px;\n            }\n        }\n    <\/style>\n\n    <div class=\"ncy-map-explorer-wrapper\">\n        <!-- Sidebar -->\n        <div class=\"ncy-map-sidebar\">\n            <div class=\"ncy-map-sidebar-header\">\n                <h1>Interactive Map Explorer<\/h1>\n                <p>Drag the map to discover premium properties in that area.<\/p>\n            <\/div>\n            <div class=\"ncy-map-filters\">\n                <div class=\"ncy-filters-row\">\n                    <!-- Region Filter -->\n                    <div class=\"ncy-select-wrapper\">\n                        <select id=\"ncy-filter-region\">\n                            <option value=\"\">All Regions<\/option>\n                            <option value=\"alsancak\">Alsancak<\/option><option value=\"arapkoy\">Arapk\u00f6y<\/option><option value=\"aygun\">Ayg\u00fcn<\/option><option value=\"bafra\">Bafra<\/option><option value=\"bahceli\">Bah\u00e7eli<\/option><option value=\"bogaz\">Bo\u011faz<\/option><option value=\"cengizkoy\">Cengizkoy<\/option><option value=\"edremit\">Edremit<\/option><option value=\"esentepe\">Esentepe<\/option><option value=\"famagusta\">Famagusta<\/option><option value=\"gaziveren\">Gaziveren<\/option><option value=\"gonyeli\">G\u00f6nyeli<\/option><option value=\"guzelyurt\">Guzelyurt<\/option><option value=\"iskele-iskele\">\u0130skele<\/option><option value=\"karsiyaka\">Kar\u015f\u0131yaka<\/option><option value=\"kyrenia\">Kyrenia<\/option><option value=\"lapta\">Lapta<\/option><option value=\"lefke\">Lefke<\/option><option value=\"nicosia\">Nicosia<\/option><option value=\"otuken-iskele\">\u00d6t\u00fcken<\/option><option value=\"tatlisu\">Tatlisu<\/option><option value=\"yeni-bogazici\">Yeni Bo\u011fazi\u00e7i<\/option><option value=\"yeni-erenkoy\">Yeni Erenk\u00f6y<\/option><option value=\"zeytinlik\">Zeytinlik<\/option>                        <\/select>\n                    <\/div>\n\n                    <!-- Type Filter -->\n                    <div class=\"ncy-select-wrapper\">\n                        <select id=\"ncy-filter-type\">\n                            <option value=\"\">All Types<\/option>\n                            <option value=\"apartments\">Apartments<\/option><option value=\"bungalow\">Bungalow<\/option><option value=\"houses\">Houses<\/option><option value=\"loft\">Loft<\/option><option value=\"townhome\">Townhome<\/option><option value=\"villa\">Villa<\/option>                        <\/select>\n                    <\/div>\n\n                    <!-- Beds Filter -->\n                    <div class=\"ncy-select-wrapper\">\n                        <select id=\"ncy-filter-beds\">\n                            <option value=\"\">Beds (Any)<\/option>\n                            <option value=\"1\">1+ Bedrooms<\/option>\n                            <option value=\"2\">2+ Bedrooms<\/option>\n                            <option value=\"3\">3+ Bedrooms<\/option>\n                            <option value=\"4\">4+ Bedrooms<\/option>\n                        <\/select>\n                    <\/div>\n                <\/div>\n\n                <!-- Price Slider -->\n                <div class=\"ncy-price-filter-wrap\">\n                    <div class=\"ncy-price-labels\">\n                        <div>Min Price: <span id=\"ncy-price-min-label\">\u00a30<\/span><\/div>\n                        <div>Max Price: <span id=\"ncy-price-max-label\">\u00a35M+<\/span><\/div>\n                    <\/div>\n                    <div id=\"ncy-price-slider\" data-no-translation><\/div>\n                    <input type=\"hidden\" id=\"ncy-filter-min-price\" value=\"0\">\n                    <input type=\"hidden\" id=\"ncy-filter-max-price\" value=\"5000000\">\n                <\/div>\n            <\/div>\n            <div class=\"ncy-map-results\" id=\"ncy-map-results\">\n                <div class=\"ncy-map-loading\" id=\"ncy-map-loading\">\n                    <div class=\"ncy-spinner\"><\/div>\n                <\/div>\n                <div id=\"ncy-properties-list\">\n                    <!-- Rendered via AJAX -->\n                <\/div>\n            <\/div>\n        <\/div>\n\n        <!-- Map -->\n        <div class=\"ncy-map-container\" data-no-translation>\n            <div id=\"ncy-leaflet-map\"><\/div>\n        <\/div>\n    <\/div>\n\n    <script>\n    document.addEventListener(\"DOMContentLoaded\", function() {\n        if (typeof L === 'undefined' || typeof noUiSlider === 'undefined') return;\n\n        \/\/ Init Map (Center on Northern Cyprus - Kyrenia\/Iskele area)\n        const map = L.map('ncy-leaflet-map', {\n            zoomControl: false\n        }).setView([35.3369, 33.3175], 9);\n        \n        L.control.zoom({ position: 'bottomright' }).addTo(map);\n\n        \/\/ Premium CartoDB Voyager Map Tiles (Clean, beautiful)\n        L.tileLayer('https:\/\/{s}.basemaps.cartocdn.com\/rastertiles\/voyager\/{z}\/{x}\/{y}{r}.png', {\n            attribution: '&copy; <a href=\"https:\/\/carto.com\/\">CartoDB<\/a>',\n            subdomains: 'abcd',\n            maxZoom: 20\n        }).addTo(map);\n\n        let markersLayer = L.featureGroup().addTo(map);\n        let fetchTimeout = null;\n        let mapIsMoving = false;\n\n        \/\/ Initialize Price Slider\n        const priceSlider = document.getElementById('ncy-price-slider');\n        const isRtl = document.documentElement.getAttribute('dir') === 'rtl';\n\n        noUiSlider.create(priceSlider, {\n            start: [0, 5000000],\n            connect: true,\n            direction: isRtl ? 'rtl' : 'ltr',\n            range: {\n                'min': 0,\n                'max': 5000000\n            },\n            step: 50000\n        });\n\n        priceSlider.noUiSlider.on('update', function(values, handle) {\n            let val = parseInt(values[handle]);\n            let formatted = val >= 1000000 ? '\u00a3' + (val\/1000000).toFixed(1) + 'M' : (val >= 1000 ? '\u00a3' + (val\/1000).toFixed(0) + 'K' : '\u00a3' + val);\n            if (val === 5000000 && handle === 1) formatted = '\u00a35M+';\n\n            if (handle === 0) {\n                document.getElementById('ncy-price-min-label').innerHTML = formatted;\n                document.getElementById('ncy-filter-min-price').value = val;\n            } else {\n                document.getElementById('ncy-price-max-label').innerHTML = formatted;\n                document.getElementById('ncy-filter-max-price').value = val;\n            }\n        });\n\n        priceSlider.noUiSlider.on('change', function() {\n            clearTimeout(fetchTimeout);\n            fetchTimeout = setTimeout(fetchProperties, 100);\n        });\n\n        const formatPrice = (price) => {\n            if(!price || price == 0) return 'POA';\n            if(price >= 1000000) return '\u00a3' + (price\/1000000).toFixed(1) + 'M';\n            if(price >= 1000) return '\u00a3' + (price\/1000).toFixed(0) + 'K';\n            return '\u00a3' + price;\n        };\n\n        const renderSidebarCard = (prop) => {\n            return `\n            <a href=\"${prop.url}\" class=\"ncy-mini-card\" target=\"_blank\" data-id=\"${prop.id}\">\n                <div class=\"ncy-mini-img\" style=\"background-image: url('${prop.image}');\"><\/div>\n                <div class=\"ncy-mini-content\">\n                    <div class=\"ncy-mini-price\">${formatPrice(prop.price)}<\/div>\n                    <h3 class=\"ncy-mini-title\">${prop.title}<\/h3>\n                    <div class=\"ncy-mini-meta\">\n                        <span>\ud83d\udecf\ufe0f ${prop.beds ? prop.beds : '-'}<\/span>\n                        <span>\ud83d\udebf ${prop.baths ? prop.baths : '-'}<\/span>\n                        <span>\ud83d\udcd0 ${prop.size ? prop.size + ' m\u00b2' : '-'}<\/span>\n                    <\/div>\n                <\/div>\n            <\/a>`;\n        };\n\n        const fetchProperties = () => {\n            const bounds = map.getBounds();\n            const sw = bounds.getSouthWest();\n            const ne = bounds.getNorthEast();\n\n            document.getElementById('ncy-map-loading').classList.add('active');\n\n            const formData = new FormData();\n            formData.append('action', 'ncyprus_map_fetch_bounds');\n            formData.append('sw_lat', sw.lat);\n            formData.append('sw_lng', sw.lng);\n            formData.append('ne_lat', ne.lat);\n            formData.append('ne_lng', ne.lng);\n\n            \/\/ Append Filters\n            formData.append('region', document.getElementById('ncy-filter-region').value);\n            formData.append('type', document.getElementById('ncy-filter-type').value);\n            formData.append('beds', document.getElementById('ncy-filter-beds').value);\n            formData.append('min_price', document.getElementById('ncy-filter-min-price').value);\n            formData.append('max_price', document.getElementById('ncy-filter-max-price').value);\n\n                        fetch('https:\/\/ncyprus.com.tr\/wp-admin\/admin-ajax.php?lang=nl_NL', {\n                method: 'POST',\n                body: formData\n            })\n            .then(res => res.json())\n            .then(res => {\n                document.getElementById('ncy-map-loading').classList.remove('active');\n                if (res.success) {\n                    markersLayer.clearLayers();\n                    const listEl = document.getElementById('ncy-properties-list');\n                    listEl.innerHTML = '';\n                    \n                    if (res.data.length === 0) {\n                        listEl.innerHTML = '<div style=\"padding: 40px 0; text-align:center; color:#667085;\">' + 'No properties found in this area. Try zooming out or moving the map.' + '<\/div>';\n                        return;\n                    }\n\n                    res.data.forEach(prop => {\n                        if (prop.lat && prop.lng) {\n                            \/\/ Create Custom Marker\n                            const icon = L.divIcon({\n                                className: 'ncy-custom-div-icon',\n                                html: `<div class=\"ncy-price-marker\" data-id=\"${prop.id}\">${formatPrice(prop.price)}<\/div>`,\n                                iconSize: null, \/\/ Let CSS determine size\n                                iconAnchor: [30, 15],\n                                popupAnchor: [0, -20]\n                            });\n\n                            const marker = L.marker([prop.lat, prop.lng], {icon: icon});\n                            \n                            \/\/ Create Popup\n                            const popupHtml = `\n                                <div class=\"ncy-popup-img\" style=\"background-image: url('${prop.image}');\"><\/div>\n                                <div class=\"ncy-popup-body\">\n                                    <div class=\"ncy-popup-price\">${formatPrice(prop.price)}<\/div>\n                                    <h4 class=\"ncy-popup-title\">${prop.title}<\/h4>\n                                    <a href=\"${prop.url}\" class=\"ncy-popup-btn\" target=\"_blank\">View Details<\/a>\n                                <\/div>\n                            `;\n                            marker.bindPopup(popupHtml);\n                            markersLayer.addLayer(marker);\n\n                            \/\/ Append to Sidebar\n                            listEl.insertAdjacentHTML('beforeend', renderSidebarCard(prop));\n                        }\n                    });\n\n                    \/\/ Add hover interactions between sidebar and map\n                    document.querySelectorAll('.ncy-mini-card').forEach(card => {\n                        card.addEventListener('mouseenter', function() {\n                            const id = this.dataset.id;\n                            document.querySelectorAll('.ncy-price-marker').forEach(m => {\n                                if(m.dataset.id == id) {\n                                    m.classList.add('active');\n                                } else {\n                                    m.classList.remove('active');\n                                }\n                            });\n                        });\n                        card.addEventListener('mouseleave', function() {\n                            document.querySelectorAll('.ncy-price-marker').forEach(m => m.classList.remove('active'));\n                        });\n                    });\n                }\n            })\n            .catch(err => {\n                document.getElementById('ncy-map-loading').classList.remove('active');\n                console.error(\"Map Fetch Error:\", err);\n            });\n        };\n\n        \/\/ Event Listeners for Map Movement\n        map.on('movestart', () => { mapIsMoving = true; });\n        map.on('moveend', () => {\n            mapIsMoving = false;\n            clearTimeout(fetchTimeout);\n            fetchTimeout = setTimeout(fetchProperties, 600); \/\/ debounce\n        });\n\n        \/\/ Event Listeners for Filters\n        document.querySelectorAll('.ncy-map-filters select').forEach(el => {\n            el.addEventListener('change', () => {\n                clearTimeout(fetchTimeout);\n                fetchTimeout = setTimeout(fetchProperties, 100);\n            });\n        });\n\n        \/\/ Initial fetch\n        setTimeout(fetchProperties, 500);\n    });\n    <\/script>","protected":false},"excerpt":{"rendered":"","protected":false},"author":0,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"inline_featured_image":false,"footnotes":""},"class_list":["post-17124","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/ncyprus.com.tr\/nl\/wp-json\/wp\/v2\/pages\/17124","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ncyprus.com.tr\/nl\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/ncyprus.com.tr\/nl\/wp-json\/wp\/v2\/types\/page"}],"replies":[{"embeddable":true,"href":"https:\/\/ncyprus.com.tr\/nl\/wp-json\/wp\/v2\/comments?post=17124"}],"version-history":[{"count":0,"href":"https:\/\/ncyprus.com.tr\/nl\/wp-json\/wp\/v2\/pages\/17124\/revisions"}],"wp:attachment":[{"href":"https:\/\/ncyprus.com.tr\/nl\/wp-json\/wp\/v2\/media?parent=17124"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}