(function () { window.MULTIPLEX_GOOGLE_MAPS_KEYS = [ "AIzaSyD9gM22MGQuNbkLqNTeaqlcQaEDMWgT3-o", "AIzaSyAg3ZEcZm5IF73ofj-6zA3VfaIPHgM5rUc", "AIzaSyCO8cSoOTNE2_B05QaS1RUhNqYQel_QdM4" ]; const STORAGE_KEY = "multiplexGoogleMapsKeyIndex"; let index = Number( sessionStorage.getItem( STORAGE_KEY ) ); if ( !Number.isInteger(index) || index < 0 || index >= window.MULTIPLEX_GOOGLE_MAPS_KEYS.length ) { index = 0; } window.MULTIPLEX_GOOGLE_MAPS_KEY_INDEX = index; window.getMultiplexGoogleMapsKey = function () { return ( window.MULTIPLEX_GOOGLE_MAPS_KEYS[ window.MULTIPLEX_GOOGLE_MAPS_KEY_INDEX ] || "" ); }; window.tryNextMultiplexGoogleMapsKey = function () { window.MULTIPLEX_GOOGLE_MAPS_KEY_INDEX++; if ( window.MULTIPLEX_GOOGLE_MAPS_KEY_INDEX >= window.MULTIPLEX_GOOGLE_MAPS_KEYS.length ) { return false; } sessionStorage.setItem( STORAGE_KEY, String( window.MULTIPLEX_GOOGLE_MAPS_KEY_INDEX ) ); window.location.reload(); return true; }; window.resetMultiplexGoogleMapsKey = function () { window.MULTIPLEX_GOOGLE_MAPS_KEY_INDEX = 0; sessionStorage.setItem( STORAGE_KEY, "0" ); }; })();
(function () { const MAP_ID = "mapdisplay"; const LOGS_ID = "logs"; const GOOGLE_MAPS_KEY = window.getMultiplexGoogleMapsKey ? window.getMultiplexGoogleMapsKey() : ""; const BACKEND_URL = "https://script.google.com/macros/s/AKfycbx3BIURyMF3Sjp2Pwm6VfH8B4BNCTXpyJLDEeyRhaOo6MzmDRYzlzacScGwG4yWlpEE/exec"; const LOT_SIZE_BACKEND_URL = "https://script.google.com/macros/s/AKfycby4cWNyGaoUHA0u36t0mn964uGYoa7Iet0g4qTWdp_jVAE0G80UjeKig7O_E1uHAqlW5Q/exec"; const ZEALTY_BACKEND_URL = "https://script.google.com/macros/s/AKfycby8qvz1F5kJMSaQ7xCvhmyiwHPne9ToFfT8Jy0W1C727BFNreA52bq-dq0rVKla5kJzqA/exec"; const MY_MAP_ID = "1_V5HQvsBZ2n8Josemgp4E98FtYECk_Y"; const MAP_LAT = 49.25210560117948; const MAP_LNG = -123.13682576466381; const MAP_ZOOM = 13; const MARKER_SIZE = 24; const MARKER_FONT_SIZE = 12; if (window.__multiplexMapCleanup) { window.__multiplexMapCleanup(); } let map = null; let mapHost = null; let target = null; let output = null; let resizeObserver = null; let currentRequest = null; let unitMarkers = []; function prepareLogs() { const logs = document.getElementById( LOGS_ID ); if (!logs) { return; } logs.style.setProperty( "position", "relative", "important" ); logs.style.setProperty( "overflow", "hidden", "important" ); let existing = document.getElementById( "openai-log-output" ); if (existing) { output = existing; return; } output = document.createElement( "div" ); output.id = "openai-log-output"; output.style.cssText = ` position:absolute; inset:0; box-sizing:border-box; padding:28px; color:#ffffff; font-family:Arial,Helvetica,sans-serif; font-size:16px; line-height:1.5; text-align:left; white-space:pre-wrap; word-break:break-word; overflow-y:auto; overflow-x:hidden; z-index:10; `; logs.appendChild( output ); } function setLogs( text ) { const current = document.getElementById( "openai-log-output" ); if (current) { output = current; } if (!output) { return; } output.style.color = "#ffffff"; output.textContent = text || ""; output.scrollTop = 0; } function setGreenStatus( text ) { const current = document.getElementById( "openai-log-output" ); if (current) { output = current; } if (!output) { return; } output.style.color = "#00ff66"; output.textContent = text || ""; output.scrollTop = 0; } function setCityWithGreenStatus( cityText, statusText ) { const current = document.getElementById( "openai-log-output" ); if (current) { output = current; } if (!output) { return; } output.style.color = "#ffffff"; output.textContent = ""; const city = document.createElement( "span" ); city.style.color = "#ffffff"; city.textContent = cityText || ""; output.appendChild( city ); const status = document.createElement( "span" ); status.style.color = "#00ff66"; status.textContent = "\n\n" + statusText; output.appendChild( status ); output.scrollTop = 0; } function prepareMapContainer() { target = document.getElementById( MAP_ID ); if (!target) { throw new Error( "#mapdisplay not found." ); } const old = document.getElementById( "multiplex-google-map" ); if (old) { old.remove(); } target.style.setProperty( "position", "relative", "important" ); target.style.setProperty( "overflow", "hidden", "important" ); mapHost = document.createElement( "div" ); mapHost.id = "multiplex-google-map"; mapHost.style.cssText = ` position:absolute !important; inset:0 !important; width:100% !important; height:100% !important; display:block !important; z-index:9999 !important; pointer-events:auto !important; `; target.appendChild( mapHost ); } function switchGoogleKey() { if ( window.tryNextMultiplexGoogleMapsKey && window.tryNextMultiplexGoogleMapsKey() ) { return true; } return false; } function loadGoogleMaps() { return new Promise( function ( resolve, reject ) { if (!GOOGLE_MAPS_KEY) { reject( new Error( "No Google Maps API key available." ) ); return; } if ( window.google && window.google.maps ) { resolve(); return; } const oldScript = document.getElementById( "multiplex-google-loader" ); if (oldScript) { oldScript.remove(); } const callback = "multiplexGoogleReady_" + Date.now(); let finished = false; function fail( message ) { if (finished) { return; } finished = true; if ( switchGoogleKey() ) { return; } reject( new Error( message ) ); } window[ callback ] = function () { if (finished) { return; } finished = true; delete window[ callback ]; resolve(); }; window.gm_authFailure = function () { console.error( "GOOGLE MAPS API KEY REJECTED" ); fail( "All Google Maps API keys failed." ); }; const script = document.createElement( "script" ); script.id = "multiplex-google-loader"; script.src = "https://maps.googleapis.com/maps/api/js?key=" + encodeURIComponent( GOOGLE_MAPS_KEY ) + "&callback=" + encodeURIComponent( callback ) + "&loading=async&v=weekly"; script.async = true; script.onerror = function () { console.error( "GOOGLE MAPS SCRIPT FAILED" ); fail( "All Google Maps API keys failed." ); }; document.head.appendChild( script ); } ); } async function loadMultiplexMarkers() { try { console.log( "LOADING MULTIPLEX MARKERS..." ); const response = await fetch( BACKEND_URL, { method: "POST", headers: { "Content-Type": "text/plain;charset=utf-8" }, body: JSON.stringify( { getMarkers: true, mapId: MY_MAP_ID } ) } ); const raw = await response.text(); let data; try { data = JSON.parse( raw ); } catch ( error ) { console.error( "BACKEND RESPONSE:", raw ); throw new Error( "Backend returned invalid JSON." ); } if ( data.success !== true ) { throw new Error( data.error || "Could not load marker data." ); } if ( !Array.isArray( data.markers ) ) { throw new Error( "Backend returned no marker list." ); } console.log( "MULTIPLEX MARKERS:", data.count, data.markers ); createUnitMarkers( data.markers ); setLogs( "READY" ); } catch ( error ) { console.error( "MARKER ERROR:", error ); setLogs( "MARKER ERROR\n\n" + error.message ); } } function createUnitMarkers( properties ) { unitMarkers.forEach( function ( marker ) { marker.setMap( null ); } ); unitMarkers = []; properties.forEach( function ( property ) { const lat = Number( property.lat ); const lng = Number( property.lng ); const units = Number( property.units ); if ( !Number.isFinite( lat ) || !Number.isFinite( lng ) || !Number.isFinite( units ) ) { return; } const marker = new google.maps.Marker( { map: map, position: { lat: lat, lng: lng }, title: ( property.name || "Property" ) + " — " + units + " units", optimized: false, zIndex: 1000000, icon: { path: google.maps.SymbolPath.CIRCLE, scale: MARKER_SIZE / 2, fillColor: getUnitColor( units ), fillOpacity: 1, strokeColor: "#000000", strokeOpacity: 1, strokeWeight: 2 }, label: { text: String( units ), color: "#ffffff", fontSize: MARKER_FONT_SIZE + "px", fontWeight: "700", fontFamily: "Arial, Helvetica, sans-serif" } } ); marker.addListener( "click", function () { if ( property.url ) { readMarkerPage( property.name || "Property", property.url ); } else { setLogs( "NO LINK FOUND\n\n" + ( property.name || "Property" ) ); } } ); unitMarkers.push( marker ); } ); console.log( unitMarkers.length + " CUSTOM MARKERS CREATED" ); } function getUnitColor( units ) { switch ( Number( units ) ) { case 3: return "#2ecc71"; case 4: return "#3498db"; case 5: return "#f39c12"; case 6: return "#e74c3c"; case 7: return "#9b59b6"; case 8: return "#e84393"; default: return "#666666"; } } function hasCompletionDate( text ) { if (!text) { return false; } const lines = String( text ) .replace( /\r/g, "" ) .split( "\n" ); const completionPattern = /\bcomplet(?:e|ed|es|ing|ion|ions)\b/i; for ( let i = 0; i < lines.length; i++ ) { const line = lines[ i ].trim(); if ( !completionPattern.test( line ) ) { continue; } const previousLine = i > 0 ? lines[ i - 1 ].trim() : ""; const nextLine = i + 1 < lines.length ? lines[ i + 1 ].trim() : ""; const nextTwoLines = i + 2 < lines.length ? lines[ i + 2 ].trim() : ""; const nearbyText = [ previousLine, line, nextLine, nextTwoLines ] .join( " " ); if ( /\bnot\s+provided\b/i.test( nearbyText ) ) { console.log( "IGNORING COMPLETION — NOT PROVIDED" ); continue; } console.log( "VALID COMPLETION FOUND:", line ); return true; } console.log( "NO VALID COMPLETION FOUND" ); return false; } async function readLotSize( address, signal ) { console.log( "READING LOT SIZE:", address ); const response = await fetch( LOT_SIZE_BACKEND_URL, { method: "POST", headers: { "Content-Type": "text/plain;charset=utf-8" }, body: JSON.stringify( { address: address } ), signal: signal } ); const raw = await response.text(); let data; try { data = JSON.parse( raw ); } catch ( error ) { console.error( "LOT SIZE RESPONSE:", raw ); throw new Error( "Lot size backend returned invalid JSON." ); } if ( data.success !== true ) { throw new Error( data.error || "Lot size lookup failed." ); } return data; } function formatLotSize( data ) { if ( !data || data.found !== true || !data.lotSizeSqFt ) { return "LOT SIZE: Not found"; } const size = Number( data.lotSizeSqFt ); if ( Number.isFinite( size ) ) { return ( "LOT SIZE: " + size.toLocaleString() + " sq ft" ); } return ( "LOT SIZE: " + data.lotSizeSqFt + " sq ft" ); } async function readMarkerPage( name, url ) { if (!url) { setLogs( "NO LINK FOUND\n\n" + name ); return; } if ( currentRequest ) { currentRequest.abort(); } currentRequest = new AbortController(); const signal = currentRequest.signal; setGreenStatus( "READING WEBPAGE...\n\n" + name ); try { const response = await fetch( BACKEND_URL, { method: "POST", headers: { "Content-Type": "text/plain;charset=utf-8" }, body: JSON.stringify( { readPage: true, url: url, propertyName: name } ), signal: signal } ); const raw = await response.text(); let data; try { data = JSON.parse( raw ); } catch ( error ) { throw new Error( "Backend returned invalid JSON." ); } if ( data.success !== true ) { throw new Error( data.error || "Could not read webpage." ); } const cityText = data.text || "No information returned."; setLogs( cityText ); let lotData = null; try { lotData = await readLotSize( name, signal ); } catch ( lotError ) { if ( lotError.name === "AbortError" ) { return; } console.error( "LOT SIZE ERROR:", lotError ); } if ( signal.aborted ) { return; } const lotText = formatLotSize( lotData ); const propertyText = cityText + "\n\n" + lotText; setLogs( propertyText ); const completed = hasCompletionDate( cityText ); console.log( "PROPERTY:", name ); console.log( "VALID COMPLETION FOUND:", completed ); if ( !completed ) { return; } setCityWithGreenStatus( propertyText, "SEARCHING CURRENT LISTINGS..." ); const zealtyData = await readZealtyListings( name, signal ); if ( signal.aborted ) { return; } let zealtyText = ""; if ( zealtyData.text ) { zealtyText = zealtyData.text; } else { zealtyText = formatZealtyListings( zealtyData, name ); } setLogs( propertyText + "\n\n" + "==============================\n\n" + zealtyText ); } catch ( error ) { if ( error.name === "AbortError" ) { return; } console.error( "PROPERTY LOOKUP ERROR:", error ); setLogs( "ERROR\n\n" + error.message ); } } async function readZealtyListings( address, signal ) { console.log( "SEARCHING ZEALTY:", address ); const response = await fetch( ZEALTY_BACKEND_URL, { method: "POST", headers: { "Content-Type": "text/plain;charset=utf-8" }, body: JSON.stringify( { address: address } ), signal: signal } ); const raw = await response.text(); let data; try { data = JSON.parse( raw ); } catch ( error ) { console.error( "ZEALTY RESPONSE:", raw ); throw new Error( "Zealty backend returned invalid JSON." ); } if ( data.success !== true ) { throw new Error( data.error || "Zealty lookup failed." ); } return data; } function formatZealtyListings( data, address ) { if ( !data || !Array.isArray( data.listings ) || !data.listings.length ) { return ( "CURRENT LISTINGS\n\n" + address + "\n\n" + "No active listings found." ); } let text = "CURRENTLY FOR SALE\n\n"; data.listings.forEach( function ( listing, index ) { if ( index > 0 ) { text += "\n\n"; } if ( listing.address ) { text += listing.address + "\n"; } if ( listing.price ) { text += "ASKING PRICE: " + listing.price + "\n"; } const details = []; if ( listing.beds !== undefined && listing.beds !== "" ) { details.push( listing.beds + " Bed" ); } if ( listing.baths !== undefined && listing.baths !== "" ) { details.push( listing.baths + " Bath" ); } if ( listing.sqft ) { const sqft = Number( listing.sqft ); details.push( ( Number.isFinite( sqft ) ? sqft.toLocaleString() : listing.sqft ) + " sq ft" ); } if ( details.length ) { text += details.join( " | " ) + "\n"; } if ( listing.mls ) { text += "MLS: " + listing.mls + "\n"; } if ( listing.url ) { text += listing.url; } } ); return text; } async function start() { prepareLogs(); setLogs( "LOADING MAP..." ); try { prepareMapContainer(); await loadGoogleMaps(); map = new google.maps.Map( mapHost, { center: { lat: MAP_LAT, lng: MAP_LNG }, zoom: MAP_ZOOM, mapTypeId: google.maps.MapTypeId.ROADMAP, mapTypeControl: false, streetViewControl: false, fullscreenControl: false, clickableIcons: false, gestureHandling: "greedy" } ); await loadMultiplexMarkers(); function resizeMap() { if (!map) { return; } google.maps.event.trigger( map, "resize" ); } setTimeout( resizeMap, 100 ); setTimeout( resizeMap, 500 ); setTimeout( resizeMap, 1500 ); if ( window.ResizeObserver ) { resizeObserver = new ResizeObserver( resizeMap ); resizeObserver.observe( target ); } window.MultiplexMap = { map: map, get unitMarkers() { return unitMarkers; }, reloadMarkers: loadMultiplexMarkers }; } catch ( error ) { console.error( error ); setLogs( "MAP ERROR\n\n" + error.message ); } } window.__multiplexMapCleanup = function () { if ( currentRequest ) { currentRequest.abort(); } unitMarkers.forEach( function ( marker ) { marker.setMap( null ); } ); unitMarkers = []; if ( resizeObserver ) { resizeObserver.disconnect(); } if ( mapHost ) { mapHost.remove(); } }; if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", start, { once: true } ); } else { start(); } })();
(function () { if (window.__googleMapsLoadingOverlayCleanup) { window.__googleMapsLoadingOverlayCleanup(); } const MAP_ID = "mapdisplay"; const OVERLAY_BACKGROUND = "#222021"; const TITLE_TEXT = "MULTIPLEX TRACKER"; const SUBTITLE_TEXT = "developed by Jay C"; const LOADED_HOLD_DURATION = 3000; const FADE_DURATION = 700; const CHECK_INTERVAL = 100; const ERROR_PATTERNS = [ "Oops! Something went wrong", "This page didn't load Google Maps correctly", "Google Maps JavaScript API error", "RefererNotAllowedMapError", "InvalidKeyMapError", "ApiNotActivatedMapError", "BillingNotEnabledMapError", "OverQuotaMapError" ]; let overlay = null; let textWrap = null; let checkTimer = null; let holdTimer = null; let observer = null; let hasFinished = false; let waitingToFade = false; let mapErrorDetected = false; function createOverlay() { const oldOverlay = document.getElementById( "google-maps-loading-overlay" ); if (oldOverlay) { try { if ( oldOverlay.tagName === "DIALOG" && oldOverlay.open ) { oldOverlay.close(); } } catch (error) {} oldOverlay.remove(); } overlay = document.createElement( "dialog" ); overlay.id = "google-maps-loading-overlay"; overlay.setAttribute( "aria-label", "Loading map" ); overlay.style.cssText = ` position:fixed !important; left:0 !important; top:0 !important; right:auto !important; bottom:auto !important; width:100vw !important; height:100vh !important; min-width:100vw !important; min-height:100vh !important; max-width:none !important; max-height:none !important; margin:0 !important; padding:0 !important; border:0 !important; outline:0 !important; background:${OVERLAY_BACKGROUND} !important; opacity:1 !important; visibility:visible !important; box-sizing:border-box !important; overflow:hidden !important; pointer-events:auto !important; transform:none !important; transition: opacity ${FADE_DURATION}ms ease !important; `; textWrap = document.createElement( "div" ); textWrap.style.cssText = ` position:absolute; left:50%; top:50%; transform:translate(-50%,-50%); display:flex; flex-direction:column; align-items:center; justify-content:center; text-align:center; color:#ffffff; font-family:"Jost",Arial,Helvetica,sans-serif; pointer-events:none; opacity:1; transition: opacity ${FADE_DURATION}ms ease; `; const title = document.createElement( "div" ); title.textContent = TITLE_TEXT; title.style.cssText = ` font-size:34px; font-weight:600; letter-spacing:0.12em; line-height:1.1; white-space:nowrap; `; const subtitle = document.createElement( "div" ); subtitle.textContent = SUBTITLE_TEXT; subtitle.style.cssText = ` margin-top:8px; font-size:14px; font-weight:400; letter-spacing:0.08em; line-height:1.2; white-space:nowrap; opacity:0.7; `; textWrap.appendChild( title ); textWrap.appendChild( subtitle ); overlay.appendChild( textWrap ); document.body.appendChild( overlay ); try { overlay.showModal(); } catch (error) { overlay.setAttribute( "open", "" ); overlay.style.zIndex = "2147483647"; } } function getMapDisplay() { return document.getElementById( MAP_ID ); } function containsMapErrorText() { const mapDisplay = getMapDisplay(); if (!mapDisplay) { return false; } const text = ( mapDisplay.innerText || mapDisplay.textContent || "" ) .trim() .toLowerCase(); if (!text) { return false; } for ( let i = 0; i < ERROR_PATTERNS.length; i++ ) { if ( text.includes( ERROR_PATTERNS[i].toLowerCase() ) ) { return true; } } return false; } function detectMapErrorElements() { const mapDisplay = getMapDisplay(); if (!mapDisplay) { return false; } const selectors = [ ".gm-err-container", ".gm-err-content", ".gm-err-message", ".gm-err-title" ]; for ( let i = 0; i < selectors.length; i++ ) { const elements = mapDisplay.querySelectorAll( selectors[i] ); for ( let j = 0; j < elements.length; j++ ) { const rect = elements[j].getBoundingClientRect(); if ( rect.width > 0 && rect.height > 0 ) { return true; } } } return false; } function hasMapError() { if ( containsMapErrorText() || detectMapErrorElements() ) { mapErrorDetected = true; return true; } return mapErrorDetected; } function hasVisibleGoogleControls() { const mapDisplay = getMapDisplay(); if (!mapDisplay) { return false; } const selectors = [ ".gm-style-mtc", ".gm-fullscreen-control", ".gm-svpc", ".gmnoprint" ]; for ( let i = 0; i < selectors.length; i++ ) { const elements = mapDisplay.querySelectorAll( selectors[i] ); for ( let j = 0; j < elements.length; j++ ) { const rect = elements[j].getBoundingClientRect(); if ( rect.width > 0 && rect.height > 0 ) { return true; } } } return false; } function hasRenderedMapSurface() { const mapDisplay = getMapDisplay(); if (!mapDisplay) { return false; } const gmStyle = mapDisplay.querySelector( ".gm-style" ); if (!gmStyle) { return false; } const gmRect = gmStyle.getBoundingClientRect(); if ( gmRect.width <= 0 || gmRect.height <= 0 ) { return false; } const images = gmStyle.querySelectorAll( "img" ); let loadedImageCount = 0; for ( let i = 0; i < images.length; i++ ) { const image = images[i]; const rect = image.getBoundingClientRect(); if ( image.complete && image.naturalWidth > 0 && rect.width > 0 && rect.height > 0 ) { loadedImageCount++; } } if ( loadedImageCount >= 2 ) { return true; } const canvases = gmStyle.querySelectorAll( "canvas" ); for ( let i = 0; i < canvases.length; i++ ) { const canvas = canvases[i]; const rect = canvas.getBoundingClientRect(); if ( rect.width > 50 && rect.height > 50 ) { return true; } } if ( hasVisibleGoogleControls() ) { return true; } return false; } function mapLoadedSuccessfully() { if ( hasMapError() ) { return false; } if ( !window.google || !window.google.maps ) { return false; } if ( !hasRenderedMapSurface() ) { return false; } return true; } function finishLoading() { if ( hasFinished || !overlay || mapErrorDetected ) { return; } hasFinished = true; if (checkTimer) { clearInterval( checkTimer ); checkTimer = null; } if (observer) { observer.disconnect(); observer = null; } if (textWrap) { textWrap.style.opacity = "0"; } overlay.style.setProperty( "opacity", "0", "important" ); setTimeout( function () { if (!overlay) { return; } try { if (overlay.open) { overlay.close(); } } catch (error) {} overlay.remove(); overlay = null; textWrap = null; }, FADE_DURATION + 50 ); } function beginHold() { if ( waitingToFade || hasFinished ) { return; } waitingToFade = true; if (checkTimer) { clearInterval( checkTimer ); checkTimer = null; } if (observer) { observer.disconnect(); observer = null; } holdTimer = setTimeout( function () { holdTimer = null; finishLoading(); }, LOADED_HOLD_DURATION ); } function checkMap() { if ( hasFinished || waitingToFade ) { return; } if ( hasMapError() ) { return; } if ( mapLoadedSuccessfully() ) { beginHold(); } } function startObserver() { const mapDisplay = getMapDisplay(); if (!mapDisplay) { return; } if ( typeof MutationObserver === "undefined" ) { return; } observer = new MutationObserver( function () { checkMap(); } ); observer.observe( mapDisplay, { childList:true, subtree:true, characterData:true, attributes:true } ); } function preventDialogCancel( event ) { event.preventDefault(); } function start() { createOverlay(); if (overlay) { overlay.addEventListener( "cancel", preventDialogCancel ); } startObserver(); checkTimer = setInterval( checkMap, CHECK_INTERVAL ); checkMap(); } window.__googleMapsLoadingOverlayCleanup = function () { if (checkTimer) { clearInterval( checkTimer ); checkTimer = null; } if (holdTimer) { clearTimeout( holdTimer ); holdTimer = null; } if (observer) { observer.disconnect(); observer = null; } if (overlay) { overlay.removeEventListener( "cancel", preventDialogCancel ); try { if (overlay.open) { overlay.close(); } } catch (error) {} overlay.remove(); overlay = null; textWrap = null; } hasFinished = true; }; if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", start, { once:true } ); } else { start(); } })();
(function () { const SHARED_CACHE_URL = "https://script.google.com/macros/s/AKfycbztx7Elr0IKArs7gI9HG9JZdAFBoiUvxx1OvhCUl-wk-cfBg2WhKV8mn6BN6dbEkVby/exec"; const LOGS_ID = "logs"; const LOG_OUTPUT_ID = "openai-log-output"; const SHARED_CACHE_COLOR = "#ff0000"; function getMarkerKey( marker ) { const title = marker.getTitle ? marker.getTitle() : ""; const position = marker.getPosition ? marker.getPosition() : null; if (position) { return ( title + "|" + position.lat().toFixed(7) + "," + position.lng().toFixed(7) ); } return title; } function getLogElement() { const output = document.getElementById( LOG_OUTPUT_ID ); if (output) { return output; } return document.getElementById( LOGS_ID ); } function getLogText() { const element = getLogElement(); if (!element) { return ""; } return ( element.innerText || element.textContent || "" ).trim(); } function cleanValue( value ) { if (!value) { return ""; } value = String( value ).trim(); if ( /^(?:not provided|not found|n\/a|none|null|unknown)$/i.test( value ) ) { return ""; } return value; } function findLineValue( text, patterns ) { const lines = text .split(/\r?\n/) .map(function (line) { return line.trim(); }) .filter(Boolean); for ( let i = 0; i < lines.length; i++ ) { for ( let j = 0; j < patterns.length; j++ ) { const match = lines[i].match( patterns[j] ); if ( match && match[1] ) { return cleanValue( match[1] ); } } } return ""; } function extractPropertyData( marker ) { const text = getLogText(); if (!text) { return null; } const data = { k: getMarkerKey(marker) }; const applicationDate = findLineValue( text, [ /^APPLICATION\s+DATE\s*:\s*(.+)$/i, /^APPLICATION\s+DATE\s*-\s*(.+)$/i ] ); const issueDate = findLineValue( text, [ /^ISSUE\s+DATE\s*:\s*(.+)$/i, /^ISSUED\s+DATE\s*:\s*(.+)$/i, /^ISSUE\s+DATE\s*-\s*(.+)$/i ] ); const completionDate = findLineValue( text, [ /^COMPLETION\s+DATE\s*:\s*(.+)$/i, /^COMPLETED\s+DATE\s*:\s*(.+)$/i, /^COMPLETION\s*:\s*(.+)$/i ] ); const lotSizeText = findLineValue( text, [ /^LOT\s+SIZE\s*:\s*(.+)$/i ] ); if (applicationDate) { data.a = applicationDate; } if (issueDate) { data.i = issueDate; } if (completionDate) { data.c = completionDate; } if (lotSizeText) { const lotMatch = lotSizeText.match( /([\d,.]+)/ ); if (lotMatch) { const lot = Number( lotMatch[1] .replace( /,/g, "" ) ); if ( Number.isFinite(lot) && lot > 0 ) { data.l = Math.round( lot ); } } } if ( !data.a && !data.i && !data.c && !data.l ) { return null; } return data; } async function get( marker ) { if ( !marker || !SHARED_CACHE_URL ) { return null; } const markerKey = getMarkerKey( marker ); try { const url = SHARED_CACHE_URL + "?action=get&k=" + encodeURIComponent( markerKey ); const response = await fetch( url, { method: "GET", cache: "no-store" } ); if (!response.ok) { return null; } const result = await response.json(); if ( !result || result.ok !== true || !result.data ) { return null; } if ( result.data.k !== markerKey ) { return null; } return result.data; } catch (error) { console.error( "Shared property cache read failed:", error ); return null; } } async function save( marker ) { if (!marker) { return false; } const data = extractPropertyData( marker ); if (!data) { return false; } try { const response = await fetch( SHARED_CACHE_URL, { method: "POST", headers: { "Content-Type": "text/plain;charset=utf-8" }, body: JSON.stringify({ action: "save", ...data }) } ); if (!response.ok) { return false; } const result = await response.json(); return !!( result && result.ok === true ); } catch (error) { console.error( "Shared property cache save failed:", error ); return false; } } function formatDate( timestamp ) { if (!timestamp) { return ""; } const date = new Date( timestamp ); if ( Number.isNaN( date.getTime() ) ) { return ""; } return date.toLocaleString( "en-CA", { year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "2-digit", hour12: true } ); } function render( data ) { if (!data) { return false; } const element = getLogElement(); if (!element) { return false; } const lines = []; if (data.a) { lines.push( "APPLICATION DATE: " + data.a ); } if (data.i) { lines.push( "ISSUE DATE: " + data.i ); } if (data.c) { lines.push( "COMPLETION DATE: " + data.c ); } if (data.l) { lines.push( "LOT SIZE: " + Number( data.l ).toLocaleString( "en-CA" ) + " sq ft" ); } if (data.t) { lines.push( "SAVED ON " + formatDate( data.t ) ); } element.textContent = lines.join( "\n" ); element.style.color = SHARED_CACHE_COLOR; return true; } window.SharedPropertyCache = { get: get, save: save, render: render, extract: extractPropertyData, getMarkerKey: getMarkerKey }; })();
(function () { const LOGS_ID = "logs"; const LOG_OUTPUT_ID = "openai-log-output"; const CHECK_INTERVAL = 250; const APPEND_DELAY = 300; const CACHE_COLOR = "#ff0000"; const CACHE_SEPARATOR = "=============================="; let mainTimer = null; let activeMarker = null; let cachedData = null; let lastObservedText = ""; let appendTimer = null; function getLogElement() { const output = document.getElementById( LOG_OUTPUT_ID ); if (output) { return output; } return document.getElementById( LOGS_ID ); } function getCurrentText() { const element = getLogElement(); if (!element) { return ""; } const clone = element.cloneNode( true ); const cachedBlocks = clone.querySelectorAll( "[data-shared-cache-block]" ); cachedBlocks.forEach( function ( block ) { block.remove(); } ); return ( clone.innerText || clone.textContent || "" ).trim(); } function formatSavedDate( timestamp ) { if (!timestamp) { return ""; } const date = new Date( timestamp ); if ( Number.isNaN( date.getTime() ) ) { return ""; } return date.toLocaleString( "en-CA", { year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "2-digit", hour12: true } ); } function buildCachedText( data ) { if (!data) { return ""; } const lines = []; lines.push( "SAVED PROPERTY DATA" ); if (data.a) { lines.push( "APPLICATION DATE: " + data.a ); } if (data.i) { lines.push( "ISSUE DATE: " + data.i ); } if (data.c) { lines.push( "COMPLETION DATE: " + data.c ); } if (data.l) { lines.push( "LOT SIZE: " + Number( data.l ).toLocaleString( "en-CA" ) + " sq ft" ); } if (data.t) { const date = formatSavedDate( data.t ); if (date) { lines.push( "SAVED ON " + date ); } } if ( lines.length === 1 ) { return ""; } return lines.join( "\n" ); } function removeCachedBlock() { const element = getLogElement(); if (!element) { return; } const blocks = element.querySelectorAll( "[data-shared-cache-block]" ); blocks.forEach( function ( block ) { block.remove(); } ); } function appendCachedBlock() { removeCachedBlock(); if (!cachedData) { return; } const element = getLogElement(); if (!element) { return; } const cachedText = buildCachedText( cachedData ); if (!cachedText) { return; } const wrapper = document.createElement( "div" ); wrapper.setAttribute( "data-shared-cache-block", "true" ); wrapper.style.cssText = ` display:block; margin:0; padding:0; color:${CACHE_COLOR}; font:inherit; font-size:inherit; line-height:inherit; white-space:pre-wrap; `; const separator = document.createElement( "div" ); separator.style.cssText = ` display:block; margin:24px 0; padding:0; color:#ffffff; font:inherit; font-size:inherit; line-height:inherit; white-space:pre-wrap; `; separator.textContent = CACHE_SEPARATOR; const content = document.createElement( "div" ); content.style.cssText = ` display:block; margin:0; padding:0; color:${CACHE_COLOR}; font:inherit; font-size:inherit; line-height:inherit; white-space:pre-wrap; `; content.textContent = cachedText; wrapper.appendChild( separator ); wrapper.appendChild( content ); element.appendChild( wrapper ); } async function loadCachedData( marker ) { cachedData = null; if ( !marker || !window.SharedPropertyCache || typeof window.SharedPropertyCache.get !== "function" ) { return; } try { cachedData = await window.SharedPropertyCache.get( marker ); } catch ( error ) { console.error( "Shared cache read failed:", error ); cachedData = null; } } async function saveFreshData() { if ( !activeMarker || !window.SharedPropertyCache || typeof window.SharedPropertyCache.save !== "function" ) { return; } try { await window.SharedPropertyCache.save( activeMarker ); } catch ( error ) { console.error( "Shared cache save failed:", error ); } } function scheduleAppend() { if ( appendTimer ) { clearTimeout( appendTimer ); } appendTimer = setTimeout( function () { saveFreshData(); appendCachedBlock(); }, APPEND_DELAY ); } function watchLogs() { const currentText = getCurrentText(); if ( !currentText || currentText === lastObservedText ) { return; } lastObservedText = currentText; if ( /READING\s+WEBPAGE/i.test( currentText ) || /READING\s+PAGE/i.test( currentText ) || /SEARCHING\s+CURRENT\s+LISTINGS/i.test( currentText ) || /FETCHING/i.test( currentText ) || /LOADING/i.test( currentText ) || /PROCESSING/i.test( currentText ) ) { return; } scheduleAppend(); } function attachMarker( marker ) { if ( !marker || marker.__sharedCacheAppendAttached ) { return; } marker.__sharedCacheAppendAttached = true; marker.addListener( "click", async function () { activeMarker = marker; cachedData = null; lastObservedText = ""; removeCachedBlock(); await loadCachedData( marker ); } ); } function scanMarkers() { if ( !window.MultiplexMap || !Array.isArray( window.MultiplexMap.unitMarkers ) ) { return; } window.MultiplexMap.unitMarkers.forEach( function ( marker ) { attachMarker( marker ); } ); watchLogs(); } if ( window.__sharedCacheAppendCleanup ) { window.__sharedCacheAppendCleanup(); } mainTimer = setInterval( scanMarkers, CHECK_INTERVAL ); scanMarkers(); window.__sharedCacheAppendCleanup = function () { if ( mainTimer ) { clearInterval( mainTimer ); mainTimer = null; } if ( appendTimer ) { clearTimeout( appendTimer ); appendTimer = null; } removeCachedBlock(); }; })();
(function () { const SHARED_CACHE_URL = "https://script.google.com/macros/s/AKfycbw_olJ2YwfvqrlFhNC41zS5_2Z8eApbLPV-nxJLVKphxyG1XjrZrVaHEC3Rqc88Wd1E/exec"; const CACHE_RING_COLOR = "#ff4fa3"; const CACHE_RING_SIZE = 17; const CACHE_RING_WEIGHT = 4; const CHECK_INTERVAL = 250; const MAX_WAIT_TIME = 30000; if ( window.__sharedCacheMarkerRingCleanup ) { window.__sharedCacheMarkerRingCleanup(); } let timer = null; let startedAt = Date.now(); let loading = false; let finished = false; let savedMarkerKeys = new Set(); let cacheRings = new Map(); function getMarkerKey( marker ) { if ( window.SharedPropertyCache && typeof window.SharedPropertyCache.getMarkerKey === "function" ) { return window.SharedPropertyCache.getMarkerKey( marker ); } const title = marker.getTitle ? marker.getTitle() : ""; const position = marker.getPosition ? marker.getPosition() : null; if (!position) { return title; } return ( title + "|" + position.lat().toFixed(7) + "," + position.lng().toFixed(7) ); } function getMarkers() { if ( !window.MultiplexMap || !Array.isArray( window.MultiplexMap.unitMarkers ) ) { return []; } return window.MultiplexMap.unitMarkers; } function getMap() { if ( window.MultiplexMap && window.MultiplexMap.map ) { return window.MultiplexMap.map; } return null; } function removeRing( marker ) { const ring = cacheRings.get( marker ); if (!ring) { return; } ring.setMap( null ); cacheRings.delete( marker ); } function createRing( marker ) { if ( cacheRings.has( marker ) ) { const existing = cacheRings.get( marker ); if ( marker.getPosition ) { existing.setPosition( marker.getPosition() ); } existing.setMap( getMap() ); return existing; } const map = getMap(); const position = marker.getPosition ? marker.getPosition() : null; if ( !map || !position || !window.google || !google.maps ) { return null; } const ring = new google.maps.Marker( { map: map, position: position, clickable: false, draggable: false, optimized: false, zIndex: 999999, icon: { path: google.maps.SymbolPath.CIRCLE, scale: CACHE_RING_SIZE, fillColor: "#000000", fillOpacity: 0, strokeColor: CACHE_RING_COLOR, strokeOpacity: 1, strokeWeight: CACHE_RING_WEIGHT } } ); cacheRings.set( marker, ring ); return ring; } function clearAllRings() { cacheRings.forEach( function ( ring ) { ring.setMap( null ); } ); cacheRings.clear(); } function applySavedRings() { if (!finished) { return; } const markers = getMarkers(); if (!markers.length) { return; } const currentMarkers = new Set( markers ); cacheRings.forEach( function ( ring, marker ) { if ( !currentMarkers.has( marker ) ) { ring.setMap( null ); cacheRings.delete( marker ); } } ); let matches = 0; markers.forEach( function ( marker ) { const key = getMarkerKey( marker ); const hasSavedData = savedMarkerKeys.has( key ); if ( hasSavedData ) { matches++; createRing( marker ); } else { removeRing( marker ); } } ); console.log( "CACHE RINGS:", matches + " / " + markers.length ); } async function loadSavedMarkerKeys() { if ( loading || finished ) { return; } if ( !SHARED_CACHE_URL || SHARED_CACHE_URL === "PASTE_SHARED_CACHE_EXEC_URL_HERE" ) { console.error( "Shared cache URL has not been configured." ); return; } loading = true; try { const url = SHARED_CACHE_URL + "?action=list&_=" + Date.now(); const response = await fetch( url, { method: "GET", cache: "no-store" } ); if (!response.ok) { throw new Error( "Backend returned HTTP " + response.status ); } const result = await response.json(); console.log( "SHARED CACHE LIST:", result ); if ( !result || result.ok !== true ) { throw new Error( result && result.error ? result.error : "Cache backend returned an error." ); } if ( !Array.isArray( result.data ) ) { throw new Error( "Cache backend did not return a data array." ); } savedMarkerKeys = new Set( result.data .map( function ( item ) { if ( item && typeof item.k === "string" ) { return item.k.trim(); } return ""; } ) .filter(Boolean) ); finished = true; console.log( "SAVED CACHE KEYS:", savedMarkerKeys.size ); applySavedRings(); } catch ( error ) { console.error( "SHARED CACHE RING ERROR:", error ); } finally { loading = false; } } function check() { const markers = getMarkers(); if ( markers.length && !finished ) { loadSavedMarkerKeys(); } if ( finished ) { applySavedRings(); if ( timer ) { clearInterval( timer ); timer = null; } return; } if ( Date.now() - startedAt >= MAX_WAIT_TIME ) { if ( timer ) { clearInterval( timer ); timer = null; } console.error( "Timed out waiting for shared cache/map." ); } } async function refresh() { finished = false; loading = false; savedMarkerKeys = new Set(); clearAllRings(); await loadSavedMarkerKeys(); } timer = setInterval( check, CHECK_INTERVAL ); check(); window.SharedCacheMarkerRings = { refresh: refresh, apply: applySavedRings, has: function ( marker ) { return savedMarkerKeys.has( getMarkerKey( marker ) ); }, getSavedKeys: function () { return Array.from( savedMarkerKeys ); } }; window.__sharedCacheMarkerRingCleanup = function () { if ( timer ) { clearInterval( timer ); timer = null; } clearAllRings(); }; })();
(function () { const COOKIE_NAME = "multiplex_favorite_markers"; /* Save for 1 year */ const COOKIE_DAYS = 365; const FAVORITE_STROKE_WEIGHT = 5; const NORMAL_STROKE_COLOR = "#212128"; const NORMAL_STROKE_WEIGHT = 2; /* Blink speed */ const BLINK_SPEED = 500; let favoriteKeys = loadFavorites(); let blinkState = false; /* ========================================= COOKIE FUNCTIONS ========================================= */ function setCookie( name, value, days ) { const expires = new Date( Date.now() + days * 24 * 60 * 60 * 1000 ); document.cookie = name + "=" + encodeURIComponent(value) + "; expires=" + expires.toUTCString() + "; path=/; SameSite=Lax"; } function getCookie( name ) { const prefix = name + "="; const cookies = document.cookie.split(";"); for ( let i = 0; i < cookies.length; i++ ) { let cookie = cookies[i].trim(); if ( cookie.indexOf(prefix) === 0 ) { return decodeURIComponent( cookie.substring( prefix.length ) ); } } return ""; } /* ========================================= LOAD FAVORITES ========================================= */ function loadFavorites() { try { const saved = getCookie( COOKIE_NAME ); if (!saved) { return []; } const parsed = JSON.parse( saved ); if ( Array.isArray( parsed ) ) { return parsed; } } catch ( error ) { console.error( "FAVORITE COOKIE LOAD ERROR:", error ); } return []; } /* ========================================= SAVE FAVORITES ========================================= */ function saveFavorites() { try { setCookie( COOKIE_NAME, JSON.stringify( favoriteKeys ), COOKIE_DAYS ); } catch ( error ) { console.error( "FAVORITE COOKIE SAVE ERROR:", error ); } } /* ========================================= MARKER IDENTIFIER ========================================= */ function getMarkerKey( marker ) { const title = marker.getTitle ? marker.getTitle() : ""; const position = marker.getPosition ? marker.getPosition() : null; if ( position ) { return ( title + "|" + position.lat().toFixed(7) + "," + position.lng().toFixed(7) ); } return title; } /* ========================================= CHECK FAVORITE ========================================= */ function isFavorite( marker ) { const key = getMarkerKey( marker ); return favoriteKeys.includes( key ); } /* ========================================= GET EXISTING MARKER COLOR ========================================= */ function getMarkerColor( marker ) { const icon = marker.getIcon ? marker.getIcon() : null; if ( icon && typeof icon === "object" && icon.fillColor ) { return icon.fillColor; } return NORMAL_STROKE_COLOR; } /* ========================================= UPDATE MARKER ========================================= */ function updateMarkerAppearance( marker ) { const icon = marker.getIcon(); if ( !icon || typeof icon !== "object" ) { return; } const newIcon = Object.assign( {}, icon ); if ( isFavorite( marker ) ) { newIcon.strokeColor = blinkState ? getMarkerColor( marker ) : NORMAL_STROKE_COLOR; newIcon.strokeWeight = FAVORITE_STROKE_WEIGHT; } else { newIcon.strokeColor = NORMAL_STROKE_COLOR; newIcon.strokeWeight = NORMAL_STROKE_WEIGHT; } marker.setIcon( newIcon ); } /* ========================================= UPDATE ALL MARKERS ========================================= */ function updateAllMarkers() { if ( !window.MultiplexMap || !Array.isArray( window.MultiplexMap.unitMarkers ) ) { return; } window.MultiplexMap.unitMarkers.forEach( function ( marker ) { updateMarkerAppearance( marker ); } ); } /* ========================================= TOGGLE FAVORITE ========================================= */ function toggleFavorite( marker ) { const key = getMarkerKey( marker ); const index = favoriteKeys.indexOf( key ); if ( index === -1 ) { favoriteKeys.push( key ); console.log( "FAVORITED:", marker.getTitle() ); } else { favoriteKeys.splice( index, 1 ); console.log( "UNFAVORITED:", marker.getTitle() ); } saveFavorites(); updateMarkerAppearance( marker ); } /* ========================================= ATTACH RIGHT CLICK ========================================= */ function attachMarker( marker ) { if ( !marker || marker.__favoriteAttached ) { return; } marker.__favoriteAttached = true; updateMarkerAppearance( marker ); marker.addListener( "rightclick", function ( event ) { if ( event && event.domEvent ) { event.domEvent.preventDefault(); event.domEvent.stopPropagation(); } toggleFavorite( marker ); } ); } /* ========================================= SCAN MARKERS ========================================= */ function scanMarkers() { if ( !window.MultiplexMap || !Array.isArray( window.MultiplexMap.unitMarkers ) ) { return; } window.MultiplexMap.unitMarkers.forEach( function ( marker ) { attachMarker( marker ); } ); } /* ========================================= BLINK FAVORITED MARKERS ========================================= */ const blinkInterval = setInterval( function () { blinkState = !blinkState; if ( !window.MultiplexMap || !Array.isArray( window.MultiplexMap.unitMarkers ) ) { return; } window.MultiplexMap.unitMarkers.forEach( function ( marker ) { if ( isFavorite( marker ) ) { updateMarkerAppearance( marker ); } } ); }, BLINK_SPEED ); /* ========================================= WATCH FOR NEW / RELOADED MARKERS ========================================= */ const markerObserver = setInterval( scanMarkers, 500 ); scanMarkers(); /* ========================================= PUBLIC CONTROLS ========================================= */ window.MultiplexFavorites = { getFavorites: function () { return favoriteKeys.slice(); }, isFavorite: function ( marker ) { return isFavorite( marker ); }, clearFavorites: function () { favoriteKeys = []; saveFavorites(); updateAllMarkers(); }, refresh: scanMarkers }; /* ========================================= CLEANUP ========================================= */ window.addEventListener( "beforeunload", function () { clearInterval( blinkInterval ); clearInterval( markerObserver ); } ); })();
(function () { if (window.__multiplexFilterAbort) { window.__multiplexFilterAbort.abort(); } const abort = new AbortController(); window.__multiplexFilterAbort = abort; const signal = abort.signal; const FAVORITES_BUTTON_ID = "showonlyfavourites"; const NON_FAVORITES_BUTTON_ID = "showonlynonfavourites"; const SHOW_ALL_BUTTON_ID = "showall"; const ACTIVE_BACKGROUND = "#222021"; const ACTIVE_TEXT_COLOR = "#ffffff"; const WHITE_BOX_SCALE = 0.72; /* X size relative to white box. 1.2 = X length equals white box size. 0.70 = X length is 70% of white box. */ const X_SIZE_PERCENT = 1.4; /* Thickness of X relative to its size. */ const X_THICKNESS_PERCENT = 0.17; const X_COLOR = "#212128"; let mode = "all"; let favoritesParts = null; let nonFavoritesParts = null; let showAllParts = null; let resizeFrame = null; const originalStyles = new Map(); function getButtonParts(buttonId) { const button = document.getElementById( buttonId ); if (!button) { return null; } const clickable = button.matches("a,button") ? button : button.querySelector("a,button") || button; let iconTarget = clickable.querySelector( "svg, img, i" ); if (!iconTarget) { iconTarget = clickable.querySelector("*"); } return { button: button, clickable: clickable, iconTarget: iconTarget, customBox: null, customX: null, currentStyle: null }; } function saveOriginalStyle(element) { if ( !element || originalStyles.has(element) ) { return; } originalStyles.set( element, element.getAttribute("style") ); } function restoreOriginalStyle(element) { if (!element) { return; } const original = originalStyles.get(element); if ( original === null || typeof original === "undefined" ) { element.removeAttribute( "style" ); } else { element.setAttribute( "style", original ); } } function rememberButton(parts) { if (!parts) { return; } saveOriginalStyle( parts.clickable ); parts.clickable .querySelectorAll("*") .forEach(function (element) { saveOriginalStyle( element ); }); } function removeCustomBox(parts) { if ( parts && parts.customBox ) { parts.customBox.remove(); parts.customBox = null; parts.customX = null; } } function restoreButton(parts) { if (!parts) { return; } removeCustomBox( parts ); restoreOriginalStyle( parts.clickable ); parts.clickable .querySelectorAll("*") .forEach(function (element) { restoreOriginalStyle( element ); }); } function captureCurrentStyle(parts) { if (!parts) { return null; } const clickable = parts.clickable; const computed = window.getComputedStyle( clickable ); const rect = clickable.getBoundingClientRect(); let textElement = clickable.querySelector( "span, strong, em, p" ); if (!textElement) { textElement = clickable; } const textComputed = window.getComputedStyle( textElement ); return { height: rect.height, fontSize: textComputed.fontSize, fontFamily: textComputed.fontFamily, fontWeight: textComputed.fontWeight, lineHeight: textComputed.lineHeight, letterSpacing: textComputed.letterSpacing, paddingTop: computed.paddingTop, paddingRight: computed.paddingRight, paddingBottom: computed.paddingBottom, paddingLeft: computed.paddingLeft, borderTop: computed.borderTop, borderRight: computed.borderRight, borderBottom: computed.borderBottom, borderLeft: computed.borderLeft, boxShadow: computed.boxShadow }; } function refreshResponsiveStyles() { restoreButton( favoritesParts ); restoreButton( nonFavoritesParts ); restoreButton( showAllParts ); void document.body.offsetHeight; favoritesParts.currentStyle = captureCurrentStyle( favoritesParts ); nonFavoritesParts.currentStyle = captureCurrentStyle( nonFavoritesParts ); showAllParts.currentStyle = captureCurrentStyle( showAllParts ); } function applyCurrentSize(parts) { if ( !parts || !parts.currentStyle ) { return; } const style = parts.currentStyle; const clickable = parts.clickable; clickable.style.setProperty( "height", style.height + "px", "important" ); clickable.style.setProperty( "min-height", style.height + "px", "important" ); clickable.style.setProperty( "max-height", style.height + "px", "important" ); clickable.style.setProperty( "box-sizing", "border-box", "important" ); clickable.style.setProperty( "padding-top", style.paddingTop, "important" ); clickable.style.setProperty( "padding-right", style.paddingRight, "important" ); clickable.style.setProperty( "padding-bottom", style.paddingBottom, "important" ); clickable.style.setProperty( "padding-left", style.paddingLeft, "important" ); clickable.style.setProperty( "border-top", style.borderTop, "important" ); clickable.style.setProperty( "border-right", style.borderRight, "important" ); clickable.style.setProperty( "border-bottom", style.borderBottom, "important" ); clickable.style.setProperty( "border-left", style.borderLeft, "important" ); clickable.style.setProperty( "box-shadow", style.boxShadow, "important" ); clickable.style.setProperty( "font-size", style.fontSize, "important" ); clickable.style.setProperty( "font-family", style.fontFamily, "important" ); clickable.style.setProperty( "font-weight", style.fontWeight, "important" ); clickable.style.setProperty( "line-height", style.lineHeight, "important" ); clickable.style.setProperty( "letter-spacing", style.letterSpacing, "important" ); clickable .querySelectorAll( "span, strong, em, p" ) .forEach(function (element) { if ( parts.iconTarget && ( element === parts.iconTarget || parts.iconTarget.contains(element) ) ) { return; } element.style.setProperty( "font-size", style.fontSize, "important" ); element.style.setProperty( "font-family", style.fontFamily, "important" ); element.style.setProperty( "font-weight", style.fontWeight, "important" ); element.style.setProperty( "line-height", style.lineHeight, "important" ); element.style.setProperty( "letter-spacing", style.letterSpacing, "important" ); }); } function getWhiteBoxRect(parts) { if ( !parts || !parts.iconTarget ) { return null; } const rect = parts.iconTarget.getBoundingClientRect(); const size = Math.min( rect.width, rect.height ) * WHITE_BOX_SCALE; return { left: rect.left + (rect.width - size) / 2, top: rect.top + (rect.height - size) / 2, size: size }; } function sizeCustomX(parts) { if ( !parts || !parts.customX || !parts.customBox ) { return; } const position = getWhiteBoxRect( parts ); if (!position) { return; } const xSize = position.size * X_SIZE_PERCENT; const thickness = Math.max( 1, xSize * X_THICKNESS_PERCENT ); parts.customX.style.width = xSize + "px"; parts.customX.style.height = xSize + "px"; const bars = parts.customX.querySelectorAll( ".multiplex-x-bar" ); bars.forEach(function (bar) { bar.style.width = xSize + "px"; bar.style.height = thickness + "px"; }); } function createCustomWhiteBox(parts) { if ( !parts || !parts.iconTarget ) { return; } removeCustomBox( parts ); const position = getWhiteBoxRect( parts ); if (!position) { return; } const box = document.createElement( "div" ); const x = document.createElement( "div" ); const bar1 = document.createElement( "div" ); const bar2 = document.createElement( "div" ); x.style.cssText = ` position:absolute; left:50%; top:50%; transform:translate(-50%,-50%); display:block; pointer-events:none; `; bar1.className = "multiplex-x-bar"; bar2.className = "multiplex-x-bar"; bar1.style.cssText = ` position:absolute; left:50%; top:50%; background:${X_COLOR}; transform:translate(-50%,-50%) rotate(45deg); transform-origin:center; `; bar2.style.cssText = ` position:absolute; left:50%; top:50%; background:${X_COLOR}; transform:translate(-50%,-50%) rotate(-45deg); transform-origin:center; `; x.appendChild( bar1 ); x.appendChild( bar2 ); box.appendChild( x ); box.style.cssText = ` position:fixed; left:${position.left}px; top:${position.top}px; width:${position.size}px; height:${position.size}px; background:#ffffff; border:0; outline:0; box-shadow:none; box-sizing:border-box; display:block; pointer-events:none; z-index:2147483647; `; document.body.appendChild( box ); parts.customBox = box; parts.customX = x; sizeCustomX( parts ); } function positionCustomBox(parts) { if ( !parts || !parts.customBox ) { return; } const position = getWhiteBoxRect( parts ); if (!position) { return; } parts.customBox.style.left = position.left + "px"; parts.customBox.style.top = position.top + "px"; parts.customBox.style.width = position.size + "px"; parts.customBox.style.height = position.size + "px"; sizeCustomX( parts ); } function markerIsFavorite(marker) { if ( window.MultiplexFavorites && typeof window.MultiplexFavorites.isFavorite === "function" ) { return window.MultiplexFavorites.isFavorite( marker ); } return false; } function activateButton(parts) { if (!parts) { return; } applyCurrentSize( parts ); parts.clickable.style.setProperty( "background-color", ACTIVE_BACKGROUND, "important" ); parts.clickable.style.setProperty( "color", ACTIVE_TEXT_COLOR, "important" ); parts.clickable .querySelectorAll( "span, strong, em, p" ) .forEach(function (element) { if ( parts.iconTarget && ( element === parts.iconTarget || parts.iconTarget.contains(element) ) ) { return; } element.style.setProperty( "color", ACTIVE_TEXT_COLOR, "important" ); }); if ( parts.iconTarget ) { parts.iconTarget.style.setProperty( "opacity", "0", "important" ); } createCustomWhiteBox( parts ); } function applyCurrentMode() { if ( mode === "favorites" ) { activateButton( favoritesParts ); return; } if ( mode === "nonfavorites" ) { activateButton( nonFavoritesParts ); return; } activateButton( showAllParts ); } function updateButtonStates() { refreshResponsiveStyles(); applyCurrentMode(); } function updateMarkerVisibility() { if ( !window.MultiplexMap || !Array.isArray( window.MultiplexMap.unitMarkers ) ) { return; } window.MultiplexMap.unitMarkers .forEach(function (marker) { if (!marker) { return; } const favorite = markerIsFavorite( marker ); if ( mode === "favorites" ) { marker.setVisible( favorite ); return; } if ( mode === "nonfavorites" ) { marker.setVisible( !favorite ); return; } marker.setVisible( true ); }); } function setMode(newMode) { mode = newMode; updateButtonStates(); updateMarkerVisibility(); } function handleResize() { if (resizeFrame) { cancelAnimationFrame( resizeFrame ); } resizeFrame = requestAnimationFrame(function () { resizeFrame = null; updateButtonStates(); setTimeout( updateButtonStates, 50 ); setTimeout( updateButtonStates, 150 ); }); } function updateActiveBoxPosition() { if ( mode === "favorites" ) { positionCustomBox( favoritesParts ); return; } if ( mode === "nonfavorites" ) { positionCustomBox( nonFavoritesParts ); return; } positionCustomBox( showAllParts ); } function attachButton( parts, newMode ) { parts.clickable.addEventListener( "click", function (event) { event.preventDefault(); event.stopPropagation(); setMode( newMode ); }, { capture:true, signal:signal } ); } function start() { favoritesParts = getButtonParts( FAVORITES_BUTTON_ID ); nonFavoritesParts = getButtonParts( NON_FAVORITES_BUTTON_ID ); showAllParts = getButtonParts( SHOW_ALL_BUTTON_ID ); if ( !favoritesParts || !nonFavoritesParts || !showAllParts ) { return; } rememberButton( favoritesParts ); rememberButton( nonFavoritesParts ); rememberButton( showAllParts ); attachButton( favoritesParts, "favorites" ); attachButton( nonFavoritesParts, "nonfavorites" ); attachButton( showAllParts, "all" ); window.addEventListener( "resize", handleResize, { signal:signal } ); window.addEventListener( "scroll", updateActiveBoxPosition, { capture:true, signal:signal } ); window.MultiplexMarkerFilter = { showAll: function () { setMode("all"); }, showFavorites: function () { setMode("favorites"); }, showNonFavorites: function () { setMode("nonfavorites"); }, refresh: function () { updateMarkerVisibility(); }, getMode: function () { return mode; } }; updateButtonStates(); updateMarkerVisibility(); } if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", start, { once:true, signal:signal } ); } else { start(); } })();
(function () { if (window.__leftSlideMenuCleanup) { window.__leftSlideMenuCleanup(); } const REFERENCE_BUTTON_ID = "showall"; const DISPLAY_ID = "display"; const TOGGLES_ID = "toggles"; const MENU_BACKGROUND = "#222021"; const MENU_TEXT_COLOR = "#ffffff"; const MENU_OUTLINE_COLOR = "#ffffff"; const MENU_OUTLINE_WIDTH = 2; const ARROW_BACKGROUND = "#222021"; const ARROW_COLOR = "#ffffff"; const ARROW_OUTLINE_COLOR = "#ffffff"; const ARROW_OUTLINE_WIDTH = 2; const MENU_WIDTH = 260; const ARROW_SCALE = 1; const ARROW_GAP = 8; const ARROW_THICKNESS = 3; const MENU_HEIGHT_MULTIPLIER = 30; const TRANSITION_SPEED = 280; const Z_INDEX_MENU = 2147483645; const Z_INDEX_ARROW = 2147483646; let menu = null; let arrowButton = null; let arrowIcon = null; let abort = null; let resizeObserver = null; let frame = null; let isOpen = false; function getReferenceButton() { const root = document.getElementById( REFERENCE_BUTTON_ID ); if (!root) { return null; } return root.matches( "a,button" ) ? root : ( root.querySelector( "a,button" ) || root ); } function getDisplay() { return document.getElementById( DISPLAY_ID ); } function getToggles() { return document.getElementById( TOGGLES_ID ); } function getReferenceDimensions() { const reference = getReferenceButton(); if (!reference) { return { height:48 }; } const rect = reference.getBoundingClientRect(); return { height: rect.height || 48 }; } function getCombinedCenterY() { const display = getDisplay(); const toggles = getToggles(); if ( !display || !toggles ) { return ( window.innerHeight / 2 ); } const displayRect = display.getBoundingClientRect(); const togglesRect = toggles.getBoundingClientRect(); const combinedTop = Math.min( togglesRect.top, displayRect.top ); const combinedBottom = Math.max( togglesRect.bottom, displayRect.bottom ); return ( combinedTop + combinedBottom ) / 2; } function createMenu() { menu = document.createElement( "div" ); menu.id = "carrd-left-slide-menu"; menu.style.cssText = ` position:fixed; left:0; top:0; width:${MENU_WIDTH}px; background:${MENU_BACKGROUND}; color:${MENU_TEXT_COLOR}; border-top:${MENU_OUTLINE_WIDTH}px solid ${MENU_OUTLINE_COLOR}; border-right:${MENU_OUTLINE_WIDTH}px solid ${MENU_OUTLINE_COLOR}; border-bottom:${MENU_OUTLINE_WIDTH}px solid ${MENU_OUTLINE_COLOR}; border-left:0; box-sizing:border-box; overflow:hidden; transform:translate(-100%,-50%); transition:transform ${TRANSITION_SPEED}ms ease; pointer-events:auto; z-index:${Z_INDEX_MENU}; `; const content = document.createElement( "div" ); content.id = "carrd-left-slide-menu-content"; content.style.cssText = ` position:absolute; inset:0; box-sizing:border-box; padding:20px; font-family:"Jost",sans-serif; color:${MENU_TEXT_COLOR}; overflow:auto; `; menu.appendChild( content ); document.body.appendChild( menu ); } function createArrow() { arrowButton = document.createElement( "button" ); arrowButton.id = "carrd-left-slide-menu-arrow"; arrowButton.type = "button"; arrowButton.setAttribute( "aria-label", "Open menu" ); arrowButton.style.cssText = ` position:fixed; left:0; top:0; padding:0; margin:0; border:${ARROW_OUTLINE_WIDTH}px solid ${ARROW_OUTLINE_COLOR}; outline:0; background:${ARROW_BACKGROUND}; color:${ARROW_COLOR}; display:flex; align-items:center; justify-content:center; box-sizing:border-box; cursor:pointer; transform:translateY(-50%); transition: left ${TRANSITION_SPEED}ms ease, background-color 140ms ease; z-index:${Z_INDEX_ARROW}; `; arrowIcon = document.createElement( "div" ); arrowIcon.style.cssText = ` position:relative; width:12px; height:18px; pointer-events:none; `; const line1 = document.createElement( "div" ); const line2 = document.createElement( "div" ); line1.className = "slide-menu-arrow-line"; line2.className = "slide-menu-arrow-line"; line1.style.cssText = ` position:absolute; left:50%; top:50%; width:12px; height:${ARROW_THICKNESS}px; background:${ARROW_COLOR}; transform-origin:right center; transform:translate(-55%,-50%) rotate(45deg); `; line2.style.cssText = ` position:absolute; left:50%; top:50%; width:12px; height:${ARROW_THICKNESS}px; background:${ARROW_COLOR}; transform-origin:right center; transform:translate(-55%,-50%) rotate(-45deg); `; arrowIcon.appendChild( line1 ); arrowIcon.appendChild( line2 ); arrowButton.appendChild( arrowIcon ); document.body.appendChild( arrowButton ); } function updateArrowDirection() { if (!arrowIcon) { return; } const lines = arrowIcon.querySelectorAll( ".slide-menu-arrow-line" ); if ( lines.length < 2 ) { return; } if (isOpen) { lines[0].style.transformOrigin = "left center"; lines[1].style.transformOrigin = "left center"; lines[0].style.transform = "translate(-45%,-50%) rotate(-45deg)"; lines[1].style.transform = "translate(-45%,-50%) rotate(45deg)"; arrowButton.setAttribute( "aria-label", "Close menu" ); } else { lines[0].style.transformOrigin = "right center"; lines[1].style.transformOrigin = "right center"; lines[0].style.transform = "translate(-55%,-50%) rotate(45deg)"; lines[1].style.transform = "translate(-55%,-50%) rotate(-45deg)"; arrowButton.setAttribute( "aria-label", "Open menu" ); } } function updateDimensions() { if ( !menu || !arrowButton ) { return; } const dimensions = getReferenceDimensions(); const buttonHeight = dimensions.height; const menuHeight = buttonHeight * MENU_HEIGHT_MULTIPLIER; const arrowSize = buttonHeight * ARROW_SCALE; const centerY = getCombinedCenterY(); menu.style.top = centerY + "px"; arrowButton.style.top = centerY + "px"; menu.style.height = menuHeight + "px"; arrowButton.style.width = arrowSize + "px"; arrowButton.style.height = arrowSize + "px"; if (isOpen) { arrowButton.style.left = ( MENU_WIDTH + ARROW_GAP ) + "px"; } else { arrowButton.style.left = "0px"; } } function openMenu() { if ( !menu || !arrowButton ) { return; } isOpen = true; updateDimensions(); menu.style.transform = "translate(0,-50%)"; arrowButton.style.left = ( MENU_WIDTH + ARROW_GAP ) + "px"; updateArrowDirection(); } function closeMenu() { if ( !menu || !arrowButton ) { return; } isOpen = false; menu.style.transform = "translate(-100%,-50%)"; arrowButton.style.left = "0px"; updateArrowDirection(); } function toggleMenu() { if (isOpen) { closeMenu(); } else { openMenu(); } } function handleOutsideClick(event) { if (!isOpen) { return; } if ( menu && menu.contains( event.target ) ) { return; } if ( arrowButton && arrowButton.contains( event.target ) ) { return; } closeMenu(); } function scheduleUpdate() { if (frame) { cancelAnimationFrame( frame ); } frame = requestAnimationFrame( function () { frame = null; updateDimensions(); } ); } function start() { abort = new AbortController(); const signal = abort.signal; createMenu(); createArrow(); updateDimensions(); updateArrowDirection(); arrowButton.addEventListener( "click", function (event) { event.preventDefault(); event.stopPropagation(); toggleMenu(); }, { signal:signal } ); document.addEventListener( "pointerdown", handleOutsideClick, { capture:true, signal:signal } ); window.addEventListener( "resize", scheduleUpdate, { signal:signal } ); window.addEventListener( "scroll", scheduleUpdate, { capture:true, signal:signal } ); if ( typeof ResizeObserver !== "undefined" ) { resizeObserver = new ResizeObserver( scheduleUpdate ); const reference = getReferenceButton(); const display = getDisplay(); const toggles = getToggles(); if (reference) { resizeObserver.observe( reference ); } if (display) { resizeObserver.observe( display ); } if (toggles) { resizeObserver.observe( toggles ); } } window.LeftSlideMenu = { open: function () { openMenu(); }, close: function () { closeMenu(); }, toggle: function () { toggleMenu(); }, isOpen: function () { return isOpen; }, getMenu: function () { return menu; }, getContent: function () { return document.getElementById( "carrd-left-slide-menu-content" ); } }; window.__leftSlideMenuCleanup = function () { if (abort) { abort.abort(); abort = null; } if (resizeObserver) { resizeObserver.disconnect(); resizeObserver = null; } if (frame) { cancelAnimationFrame( frame ); frame = null; } if (menu) { menu.remove(); menu = null; } if (arrowButton) { arrowButton.remove(); arrowButton = null; } arrowIcon = null; delete window.LeftSlideMenu; }; } if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", start, { once:true } ); } else { start(); } })();
(function () { if (window.__favoriteMenuListCleanup) { window.__favoriteMenuListCleanup(); } const COOKIE_NAME = "multiplex_favorite_markers"; const MENU_CONTENT_ID = "carrd-left-slide-menu-content"; const REFRESH_INTERVAL = 500; const BOX_BACKGROUND = "#ffffff"; const BOX_TEXT_COLOR = "#222021"; const BOX_GAP = 10; const BOX_PADDING = 14; const LEFT_ACCENT_WIDTH = 5; const REMOVE_WIDTH = 30; const REMOVE_BACKGROUND = "#e74c3c"; const REMOVE_TEXT_COLOR = "#ffffff"; const REMOVE_X_THICKNESS = 3; /* ========================================= HOVER SETTINGS ========================================= */ const HOVER_BACKGROUND = "#222021"; const HOVER_TEXT_COLOR = "#ffffff"; const HOVER_LINE_COLOR = "#ffffff"; const HOVER_LINE_HEIGHT = 2; const HOVER_TRANSITION_SPEED = 140; const UNIT_FONT_SIZE = 20; const ADDRESS_FONT_SIZE = 13; const SLIDE_DURATION = 260; const COLLAPSE_DURATION = 220; let refreshTimer = null; let lastSignature = ""; let removalInProgress = false; function getCookie( name ) { const prefix = name + "="; const cookies = document.cookie.split( ";" ); for ( let i = 0; i < cookies.length; i++ ) { const cookie = cookies[i].trim(); if ( cookie.indexOf( prefix ) === 0 ) { try { return decodeURIComponent( cookie.substring( prefix.length ) ); } catch (error) { return cookie.substring( prefix.length ); } } } return ""; } function getFavoriteKeys() { if ( window.MultiplexFavorites && typeof window.MultiplexFavorites.getFavorites === "function" ) { const favorites = window.MultiplexFavorites.getFavorites(); if ( Array.isArray( favorites ) ) { return favorites.slice(); } } const raw = getCookie( COOKIE_NAME ); if (!raw) { return []; } try { const parsed = JSON.parse( raw ); if ( Array.isArray( parsed ) ) { return parsed; } } catch (error) {} return raw .split("|~|") .map( function ( value ) { return value.trim(); } ) .filter( Boolean ); } function getMarkers() { if ( !window.MultiplexMap || !Array.isArray( window.MultiplexMap.unitMarkers ) ) { return []; } return window.MultiplexMap.unitMarkers; } function getMarkerKey( marker ) { const title = marker.getTitle ? marker.getTitle() : ""; const position = marker.getPosition ? marker.getPosition() : null; if (position) { return ( title + "|" + position.lat().toFixed(7) + "," + position.lng().toFixed(7) ); } return title; } function isFavorite( marker ) { if ( window.MultiplexFavorites && typeof window.MultiplexFavorites.isFavorite === "function" ) { return window.MultiplexFavorites.isFavorite( marker ); } const key = getMarkerKey( marker ); return getFavoriteKeys().includes( key ); } function getMarkerUnitCount( marker ) { const title = marker.getTitle ? marker.getTitle() : ""; const match = title.match( /—\s*(\d+)\s*units?/i ); if (match) { return match[1]; } if ( marker.getLabel ) { const label = marker.getLabel(); if ( typeof label === "string" ) { return label; } if ( label && label.text !== undefined ) { return String( label.text ); } } return "?"; } function getMarkerAddress( marker ) { const title = marker.getTitle ? marker.getTitle() : ""; if (!title) { return "Unknown address"; } return title .replace( /\s*—\s*\d+\s*units?.*$/i, "" ) .trim(); } function getUnitColor( units ) { switch ( Number( units ) ) { case 3: return "#2ecc71"; case 4: return "#3498db"; case 5: return "#f39c12"; case 6: return "#e74c3c"; case 7: return "#9b59b6"; case 8: return "#e84393"; default: return "#666666"; } } function triggerFavoriteToggle( marker ) { if ( !window.google || !window.google.maps || !window.google.maps.event ) { return false; } google.maps.event.trigger( marker, "rightclick" ); return true; } function setHoverState( box, units, address, hoverTopLine, hoverBottomLine, enabled ) { if ( !box || box.dataset.removing === "true" ) { return; } if (enabled) { box.style.background = HOVER_BACKGROUND; units.style.color = HOVER_TEXT_COLOR; address.style.color = HOVER_TEXT_COLOR; hoverTopLine.style.opacity = "1"; hoverBottomLine.style.opacity = "1"; } else { box.style.background = BOX_BACKGROUND; units.style.color = BOX_TEXT_COLOR; address.style.color = BOX_TEXT_COLOR; hoverTopLine.style.opacity = "0"; hoverBottomLine.style.opacity = "0"; } } function animateRemove( box, marker ) { if ( !box || box.dataset.removing === "true" || removalInProgress ) { return; } box.dataset.removing = "true"; removalInProgress = true; const wasFavorite = isFavorite( marker ); if (wasFavorite) { triggerFavoriteToggle( marker ); } box.style.pointerEvents = "none"; const startHeight = box.offsetHeight; box.style.height = startHeight + "px"; box.style.boxSizing = "border-box"; box.style.transition = "transform " + SLIDE_DURATION + "ms ease, opacity " + SLIDE_DURATION + "ms ease"; requestAnimationFrame( function () { requestAnimationFrame( function () { box.style.transform = "translateX(-110%)"; box.style.opacity = "0"; } ); } ); setTimeout( function () { box.style.transition = "height " + COLLAPSE_DURATION + "ms ease, margin-bottom " + COLLAPSE_DURATION + "ms ease, padding-top " + COLLAPSE_DURATION + "ms ease, padding-bottom " + COLLAPSE_DURATION + "ms ease"; box.style.height = "0px"; box.style.marginBottom = "0px"; box.style.paddingTop = "0px"; box.style.paddingBottom = "0px"; }, SLIDE_DURATION ); setTimeout( function () { if ( box && box.parentNode ) { box.parentNode.removeChild( box ); } removalInProgress = false; lastSignature = ""; renderFavorites(); }, SLIDE_DURATION + COLLAPSE_DURATION + 20 ); } function createFavoriteBox( marker ) { const unitCount = getMarkerUnitCount( marker ); const accentColor = getUnitColor( unitCount ); const box = document.createElement( "div" ); box.className = "multiplex-favorite-menu-item"; box.style.cssText = ` position:relative; width:100%; box-sizing:border-box; background:${BOX_BACKGROUND}; color:${BOX_TEXT_COLOR}; padding:${BOX_PADDING}px; padding-left:${BOX_PADDING + LEFT_ACCENT_WIDTH}px; padding-right:${BOX_PADDING + REMOVE_WIDTH}px; margin:0 0 ${BOX_GAP}px 0; font-family:"Jost",sans-serif; cursor:pointer; user-select:none; overflow:hidden; opacity:1; transform:translateX(0); transition: background-color ${HOVER_TRANSITION_SPEED}ms ease, color ${HOVER_TRANSITION_SPEED}ms ease; `; const leftAccent = document.createElement( "div" ); leftAccent.style.cssText = ` position:absolute; left:0; top:0; bottom:0; width:${LEFT_ACCENT_WIDTH}px; background:${accentColor}; pointer-events:none; z-index:2; `; const hoverTopLine = document.createElement( "div" ); hoverTopLine.style.cssText = ` position:absolute; left:${LEFT_ACCENT_WIDTH}px; right:${REMOVE_WIDTH}px; top:0; height:${HOVER_LINE_HEIGHT}px; background:${HOVER_LINE_COLOR}; opacity:0; pointer-events:none; transition:opacity ${HOVER_TRANSITION_SPEED}ms ease; z-index:3; `; const hoverBottomLine = document.createElement( "div" ); hoverBottomLine.style.cssText = ` position:absolute; left:${LEFT_ACCENT_WIDTH}px; right:${REMOVE_WIDTH}px; bottom:0; height:${HOVER_LINE_HEIGHT}px; background:${HOVER_LINE_COLOR}; opacity:0; pointer-events:none; transition:opacity ${HOVER_TRANSITION_SPEED}ms ease; z-index:3; `; const units = document.createElement( "div" ); units.textContent = unitCount + " UNITS"; units.style.cssText = ` font-size:${UNIT_FONT_SIZE}px; font-weight:600; line-height:1.1; color:${BOX_TEXT_COLOR}; transition:color ${HOVER_TRANSITION_SPEED}ms ease; `; const address = document.createElement( "div" ); address.textContent = getMarkerAddress( marker ); address.style.cssText = ` margin-top:5px; font-size:${ADDRESS_FONT_SIZE}px; font-weight:400; line-height:1.25; color:${BOX_TEXT_COLOR}; transition:color ${HOVER_TRANSITION_SPEED}ms ease; `; const removeButton = document.createElement( "button" ); removeButton.type = "button"; removeButton.setAttribute( "aria-label", "Remove favourite" ); removeButton.style.cssText = ` position:absolute; right:0; top:0; bottom:0; width:${REMOVE_WIDTH}px; border:0; margin:0; padding:0; background:${REMOVE_BACKGROUND}; display:flex; align-items:center; justify-content:center; cursor:pointer; outline:none; z-index:4; `; const x = document.createElement( "div" ); x.style.cssText = ` position:relative; width:14px; height:14px; pointer-events:none; `; const xLine1 = document.createElement( "span" ); const xLine2 = document.createElement( "span" ); xLine1.style.cssText = ` position:absolute; left:50%; top:50%; width:15px; height:${REMOVE_X_THICKNESS}px; background:${REMOVE_TEXT_COLOR}; transform:translate(-50%,-50%) rotate(45deg); transform-origin:center; `; xLine2.style.cssText = ` position:absolute; left:50%; top:50%; width:15px; height:${REMOVE_X_THICKNESS}px; background:${REMOVE_TEXT_COLOR}; transform:translate(-50%,-50%) rotate(-45deg); transform-origin:center; `; x.appendChild( xLine1 ); x.appendChild( xLine2 ); removeButton.appendChild( x ); box.appendChild( leftAccent ); box.appendChild( hoverTopLine ); box.appendChild( hoverBottomLine ); box.appendChild( units ); box.appendChild( address ); box.appendChild( removeButton ); box.addEventListener( "mousemove", function ( event ) { if ( box.dataset.removing === "true" ) { return; } const rect = box.getBoundingClientRect(); const relativeX = event.clientX - rect.left; const overRemoveArea = relativeX >= rect.width - REMOVE_WIDTH; setHoverState( box, units, address, hoverTopLine, hoverBottomLine, !overRemoveArea ); } ); box.addEventListener( "mouseleave", function () { setHoverState( box, units, address, hoverTopLine, hoverBottomLine, false ); } ); removeButton.addEventListener( "mouseenter", function () { setHoverState( box, units, address, hoverTopLine, hoverBottomLine, false ); } ); removeButton.addEventListener( "click", function ( event ) { event.preventDefault(); event.stopPropagation(); animateRemove( box, marker ); } ); box.addEventListener( "click", function ( event ) { if ( box.dataset.removing === "true" ) { return; } if ( removeButton.contains( event.target ) ) { return; } if ( window.MultiplexMap && window.MultiplexMap.map && marker.getPosition ) { window.MultiplexMap.map.panTo( marker.getPosition() ); } if ( window.google && window.google.maps ) { google.maps.event.trigger( marker, "click" ); } } ); return box; } function getSignature( favorites, markers ) { return ( favorites.join( "||" ) + "::" + markers.map( getMarkerKey ).join( "||" ) ); } function renderFavorites() { if ( removalInProgress ) { return; } const content = document.getElementById( MENU_CONTENT_ID ); if (!content) { return; } const favorites = getFavoriteKeys(); const markers = getMarkers(); const signature = getSignature( favorites, markers ); if ( signature === lastSignature ) { return; } lastSignature = signature; content.innerHTML = ""; if ( !favorites.length ) { const empty = document.createElement( "div" ); empty.textContent = "NO FAVOURITES"; empty.style.cssText = ` font-family:"Jost",sans-serif; font-size:13px; font-weight:500; color:#ffffff; opacity:0.6; `; content.appendChild( empty ); return; } const favoriteSet = new Set( favorites ); markers.forEach( function ( marker ) { const key = getMarkerKey( marker ); if ( !favoriteSet.has( key ) ) { return; } content.appendChild( createFavoriteBox( marker ) ); } ); } function start() { renderFavorites(); refreshTimer = setInterval( renderFavorites, REFRESH_INTERVAL ); } window.FavoriteMenuList = { refresh: function () { lastSignature = ""; renderFavorites(); } }; window.__favoriteMenuListCleanup = function () { if (refreshTimer) { clearInterval( refreshTimer ); refreshTimer = null; } const content = document.getElementById( MENU_CONTENT_ID ); if (content) { content.innerHTML = ""; } delete window.FavoriteMenuList; }; if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", start, { once:true } ); } else { start(); } })();
(function () { const FAVORITES_COOKIE = "multiplex_favorite_markers"; const CACHE_COOKIE_PREFIX = "multiplex_favorite_cache_"; const CACHE_STORAGE_PREFIX = "multiplex_favorite_logs_"; const MENU_CONTENT_ID = "carrd-left-slide-menu-content"; const LOGS_ID = "logs"; const LOG_OUTPUT_ID = "openai-log-output"; const CHECK_INTERVAL = 250; const CAPTURE_INTERVAL = 100; const LOG_STABLE_TIME = 2500; const CAPTURE_TIMEOUT = 60000; const COOKIE_DAYS = 365; const REMOVE_AREA_WIDTH = 30; const SAVED_DATE_PREFIX = "SAVED ON "; const SAVED_DATE_MARGIN_TOP = 12; const SAVED_DATE_OPACITY = 0.6; const TEMPORARY_TEXT_PATTERNS = [ /READING\s+WEBPAGE/i, /READING\s+PAGE/i, /FETCHING/i, /LOADING/i, /ANALYZING/i, /SCANNING/i, /SEARCHING/i, /PROCESSING/i, /PLEASE\s+WAIT/i, /CONNECTING/i ]; if ( window.__favoriteLogsCacheCleanup ) { window.__favoriteLogsCacheCleanup(); } let mainTimer = null; let captureTimer = null; let captureTimeout = null; let activeMarkerKey = null; let originalHTML = ""; let lastHTML = ""; let lastChangeTime = 0; let hasChanged = false; let finalStateSeen = false; let knownFavorites = []; function getCookie( name ) { const prefix = name + "="; const cookies = document.cookie.split( ";" ); for ( let i = 0; i < cookies.length; i++ ) { const cookie = cookies[i].trim(); if ( cookie.indexOf( prefix ) === 0 ) { try { return decodeURIComponent( cookie.substring( prefix.length ) ); } catch (error) { return cookie.substring( prefix.length ); } } } return ""; } function setCookie( name, value ) { const maxAge = COOKIE_DAYS * 24 * 60 * 60; document.cookie = name + "=" + encodeURIComponent( value ) + "; path=/; max-age=" + maxAge + "; SameSite=Lax"; } function deleteCookie( name ) { document.cookie = name + "=; path=/; max-age=0; SameSite=Lax"; } function hashString( text ) { let hash = 2166136261; for ( let i = 0; i < text.length; i++ ) { hash ^= text.charCodeAt( i ); hash = Math.imul( hash, 16777619 ); } return ( hash >>> 0 ).toString( 36 ); } function getCacheID( markerKey ) { return hashString( markerKey ); } function getCacheCookieName( markerKey ) { return ( CACHE_COOKIE_PREFIX + getCacheID( markerKey ) ); } function getStorageName( markerKey ) { return ( CACHE_STORAGE_PREFIX + getCacheID( markerKey ) ); } function getFavorites() { if ( window.MultiplexFavorites && typeof window.MultiplexFavorites.getFavorites === "function" ) { const favorites = window.MultiplexFavorites.getFavorites(); if ( Array.isArray( favorites ) ) { return favorites.slice(); } } const raw = getCookie( FAVORITES_COOKIE ); if (!raw) { return []; } try { const parsed = JSON.parse( raw ); if ( Array.isArray( parsed ) ) { return parsed; } } catch (error) {} return raw .split("|~|") .map( function ( value ) { return value.trim(); } ) .filter( Boolean ); } function getMarkers() { if ( !window.MultiplexMap || !Array.isArray( window.MultiplexMap.unitMarkers ) ) { return []; } return window.MultiplexMap.unitMarkers; } function getMarkerKey( marker ) { const title = marker.getTitle ? marker.getTitle() : ""; const position = marker.getPosition ? marker.getPosition() : null; if (position) { return ( title + "|" + position.lat().toFixed(7) + "," + position.lng().toFixed(7) ); } return title; } function findMarkerByKey( key ) { const markers = getMarkers(); for ( let i = 0; i < markers.length; i++ ) { if ( getMarkerKey( markers[i] ) === key ) { return markers[i]; } } return null; } function getLogElement() { const output = document.getElementById( LOG_OUTPUT_ID ); if (output) { return output; } return document.getElementById( LOGS_ID ); } function getLogHTML() { const element = getLogElement(); if (!element) { return ""; } return element.innerHTML; } function getLogText() { const element = getLogElement(); if (!element) { return ""; } return ( element.innerText || element.textContent || "" ).trim(); } function showLogHTML( html ) { const element = getLogElement(); if (!element) { return false; } element.innerHTML = html; return true; } function formatSavedDate( timestamp ) { if (!timestamp) { return ""; } const date = new Date( timestamp ); if ( isNaN( date.getTime() ) ) { return ""; } return date .toLocaleString( "en-CA", { month: "long", day: "numeric", year: "numeric", hour: "numeric", minute: "2-digit", hour12: true } ) .toUpperCase(); } function appendSavedDate( timestamp ) { const element = getLogElement(); if (!element) { return; } const oldDate = element.querySelector( "[data-favorite-saved-date]" ); if (oldDate) { oldDate.remove(); } const formattedDate = formatSavedDate( timestamp ); if (!formattedDate) { return; } const savedDate = document.createElement( "div" ); savedDate.setAttribute( "data-favorite-saved-date", "true" ); savedDate.textContent = SAVED_DATE_PREFIX + formattedDate; savedDate.style.cssText = ` display:block; margin-top:${SAVED_DATE_MARGIN_TOP}px; padding:0; color:inherit; font:inherit; font-size:inherit; font-weight:inherit; line-height:inherit; letter-spacing:inherit; text-align:left; opacity:${SAVED_DATE_OPACITY}; `; element.appendChild( savedDate ); } function hasTemporaryText() { const text = getLogText(); if (!text) { return true; } for ( let i = 0; i < TEMPORARY_TEXT_PATTERNS.length; i++ ) { if ( TEMPORARY_TEXT_PATTERNS[ i ].test( text ) ) { return true; } } return false; } function saveCachedLogs( markerKey, html ) { if ( !markerKey || !html ) { return false; } const favorites = getFavorites(); if ( !favorites.includes( markerKey ) ) { return false; } const data = { key: markerKey, html: html, saved: Date.now() }; try { localStorage.setItem( getStorageName( markerKey ), JSON.stringify( data ) ); setCookie( getCacheCookieName( markerKey ), "1" ); return true; } catch (error) { console.error( "Could not save favorite logs:", error ); return false; } } function getCachedData( markerKey ) { if (!markerKey) { return null; } const cacheCookie = getCookie( getCacheCookieName( markerKey ) ); if ( cacheCookie !== "1" ) { return null; } try { const raw = localStorage.getItem( getStorageName( markerKey ) ); if (!raw) { deleteCookie( getCacheCookieName( markerKey ) ); return null; } const data = JSON.parse( raw ); if ( !data || data.key !== markerKey || typeof data.html !== "string" || !data.html ) { return null; } return data; } catch (error) { return null; } } function getCachedLogs( markerKey ) { const data = getCachedData( markerKey ); if (!data) { return null; } return data.html; } function deleteCachedLogs( markerKey ) { if (!markerKey) { return; } deleteCookie( getCacheCookieName( markerKey ) ); try { localStorage.removeItem( getStorageName( markerKey ) ); } catch (error) {} } function stopCapture() { if (captureTimer) { clearInterval( captureTimer ); captureTimer = null; } if (captureTimeout) { clearTimeout( captureTimeout ); captureTimeout = null; } activeMarkerKey = null; originalHTML = ""; lastHTML = ""; lastChangeTime = 0; hasChanged = false; finalStateSeen = false; } function beginCapture( markerKey ) { stopCapture(); activeMarkerKey = markerKey; originalHTML = getLogHTML(); lastHTML = originalHTML; lastChangeTime = Date.now(); hasChanged = false; finalStateSeen = false; captureTimer = setInterval( function () { if (!activeMarkerKey) { stopCapture(); return; } const favorites = getFavorites(); if ( !favorites.includes( activeMarkerKey ) ) { deleteCachedLogs( activeMarkerKey ); stopCapture(); return; } const currentHTML = getLogHTML(); if (!currentHTML) { return; } if ( currentHTML !== lastHTML ) { lastHTML = currentHTML; lastChangeTime = Date.now(); hasChanged = true; if ( hasTemporaryText() ) { finalStateSeen = false; } else { finalStateSeen = true; } return; } if ( hasTemporaryText() ) { finalStateSeen = false; lastChangeTime = Date.now(); return; } if ( hasChanged ) { finalStateSeen = true; } if ( hasChanged && finalStateSeen && Date.now() - lastChangeTime >= LOG_STABLE_TIME ) { const keyToSave = activeMarkerKey; const htmlToSave = currentHTML; stopCapture(); saveCachedLogs( keyToSave, htmlToSave ); } }, CAPTURE_INTERVAL ); captureTimeout = setTimeout( function () { if (!activeMarkerKey) { return; } const keyToSave = activeMarkerKey; const currentHTML = getLogHTML(); const currentText = getLogText(); const stillTemporary = hasTemporaryText(); const shouldSave = currentHTML && currentHTML !== originalHTML && currentText && !stillTemporary; stopCapture(); if (shouldSave) { saveCachedLogs( keyToSave, currentHTML ); } }, CAPTURE_TIMEOUT ); } function scanMarker( marker ) { if ( !marker || !window.google || !window.google.maps || !window.google.maps.event ) { return; } const key = getMarkerKey( marker ); beginCapture( key ); google.maps.event.trigger( marker, "click" ); } function openFavorite( marker ) { if (!marker) { return; } const key = getMarkerKey( marker ); if ( window.MultiplexMap && window.MultiplexMap.map && marker.getPosition ) { window.MultiplexMap.map.panTo( marker.getPosition() ); } const cachedData = getCachedData( key ); if (cachedData) { stopCapture(); showLogHTML( cachedData.html ); appendSavedDate( cachedData.saved ); return; } scanMarker( marker ); } function updateBoxKeys() { const content = document.getElementById( MENU_CONTENT_ID ); if (!content) { return; } const boxes = Array.from( content.querySelectorAll( ".multiplex-favorite-menu-item" ) ); if (!boxes.length) { return; } const favorites = getFavorites(); const favoriteSet = new Set( favorites ); const favoriteMarkers = getMarkers().filter( function ( marker ) { return favoriteSet.has( getMarkerKey( marker ) ); } ); boxes.forEach( function ( box, index ) { const marker = favoriteMarkers[ index ]; if (!marker) { delete box.dataset.favoriteMarkerKey; return; } box.dataset.favoriteMarkerKey = getMarkerKey( marker ); } ); } function isRemoveClick( event, box ) { const rect = box.getBoundingClientRect(); const x = event.clientX - rect.left; return ( x >= rect.width - REMOVE_AREA_WIDTH ); } function handleMenuClick( event ) { const target = event.target; if ( !target || !target.closest ) { return; } const box = target.closest( ".multiplex-favorite-menu-item" ); if (!box) { return; } const menu = document.getElementById( MENU_CONTENT_ID ); if ( !menu || !menu.contains( box ) ) { return; } let markerKey = box.dataset.favoriteMarkerKey; if (!markerKey) { updateBoxKeys(); markerKey = box.dataset.favoriteMarkerKey; } if (!markerKey) { return; } const marker = findMarkerByKey( markerKey ); if (!marker) { return; } if ( isRemoveClick( event, box ) ) { deleteCachedLogs( markerKey ); if ( activeMarkerKey === markerKey ) { stopCapture(); } return; } event.preventDefault(); event.stopPropagation(); event.stopImmediatePropagation(); openFavorite( marker ); } function cleanupRemovedFavorites() { const current = getFavorites(); const currentSet = new Set( current ); knownFavorites.forEach( function ( oldKey ) { if ( !currentSet.has( oldKey ) ) { deleteCachedLogs( oldKey ); if ( activeMarkerKey === oldKey ) { stopCapture(); } } } ); knownFavorites = current.slice(); } function update() { updateBoxKeys(); cleanupRemovedFavorites(); } function start() { knownFavorites = getFavorites(); updateBoxKeys(); document.addEventListener( "click", handleMenuClick, true ); mainTimer = setInterval( update, CHECK_INTERVAL ); } window.FavoriteLogsCache = { get: function ( marker ) { if (!marker) { return null; } return getCachedLogs( getMarkerKey( marker ) ); }, remove: function ( marker ) { if (!marker) { return; } deleteCachedLogs( getMarkerKey( marker ) ); }, rescan: function ( marker ) { if (!marker) { return; } const key = getMarkerKey( marker ); deleteCachedLogs( key ); scanMarker( marker ); }, has: function ( marker ) { if (!marker) { return false; } return !!getCachedLogs( getMarkerKey( marker ) ); } }; window.__favoriteLogsCacheCleanup = function () { document.removeEventListener( "click", handleMenuClick, true ); if (mainTimer) { clearInterval( mainTimer ); mainTimer = null; } stopCapture(); delete window.FavoriteLogsCache; }; if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", start, { once:true } ); } else { start(); } })();
(function () { if (window.__logsCopyCleanup) { window.__logsCopyCleanup(); } const LOGS_ID = "logs"; const OVERLAY_COLOR = "rgba(0,0,0,0.62)"; const TEXT_COLOR = "#ffffff"; const TEXT = "COPY TO CLIPBOARD"; const COPIED_TEXT = "COPIED"; const TRANSITION_SPEED = 140; const MAX_FONT_SIZE = 30; const MIN_FONT_SIZE = 10; const TEXT_WIDTH_PERCENT = 0.82; let logs = null; let overlay = null; let label = null; let abort = null; let observer = null; let frame = null; let copiedTimer = null; function createOverlay() { overlay = document.createElement( "div" ); overlay.id = "logs-copy-overlay"; overlay.style.cssText = ` position:fixed; display:flex; align-items:center; justify-content:center; background:${OVERLAY_COLOR}; opacity:0; pointer-events:none; box-sizing:border-box; overflow:hidden; z-index:2147483646; transition:opacity ${TRANSITION_SPEED}ms ease; `; label = document.createElement( "div" ); label.textContent = TEXT; label.style.cssText = ` font-family:"Jost", sans-serif; font-size:${MAX_FONT_SIZE}px; font-weight:500; letter-spacing:0.08em; color:${TEXT_COLOR}; text-align:center; white-space:nowrap; pointer-events:none; user-select:none; line-height:1; `; overlay.appendChild( label ); document.body.appendChild( overlay ); } function resizeLabel() { if ( !logs || !label ) { return; } const rect = logs.getBoundingClientRect(); const availableWidth = rect.width * TEXT_WIDTH_PERCENT; label.style.fontSize = MAX_FONT_SIZE + "px"; const naturalWidth = label.scrollWidth; if (!naturalWidth) { return; } let size = MAX_FONT_SIZE * ( availableWidth / naturalWidth ); size = Math.min( MAX_FONT_SIZE, size ); size = Math.max( MIN_FONT_SIZE, size ); label.style.fontSize = size + "px"; } function updatePosition() { if ( !logs || !overlay ) { return; } const rect = logs.getBoundingClientRect(); overlay.style.left = rect.left + "px"; overlay.style.top = rect.top + "px"; overlay.style.width = rect.width + "px"; overlay.style.height = rect.height + "px"; const computed = window.getComputedStyle( logs ); overlay.style.borderRadius = computed.borderRadius; resizeLabel(); } function schedulePositionUpdate() { if (frame) { cancelAnimationFrame( frame ); } frame = requestAnimationFrame( function () { frame = null; updatePosition(); } ); } function showOverlay() { updatePosition(); overlay.style.opacity = "1"; logs.style.cursor = "pointer"; } function hideOverlay() { overlay.style.opacity = "0"; logs.style.cursor = ""; if (copiedTimer) { clearTimeout( copiedTimer ); copiedTimer = null; } label.textContent = TEXT; resizeLabel(); } function getLogsText() { const output = document.getElementById( "openai-log-output" ); if ( output && output.innerText.trim() ) { return output.innerText.trim(); } return logs.innerText.trim(); } async function copyLogs() { const text = getLogsText(); if (!text) { return; } let copied = false; try { if ( navigator.clipboard && window.isSecureContext ) { await navigator.clipboard.writeText( text ); copied = true; } } catch (error) { copied = false; } if (!copied) { const textarea = document.createElement( "textarea" ); textarea.value = text; textarea.style.cssText = ` position:fixed; left:-999999px; top:-999999px; opacity:0; `; document.body.appendChild( textarea ); textarea.focus(); textarea.select(); try { copied = document.execCommand( "copy" ); } catch (error) { copied = false; } textarea.remove(); } if (copied) { label.textContent = COPIED_TEXT; resizeLabel(); if (copiedTimer) { clearTimeout( copiedTimer ); } copiedTimer = setTimeout( function () { label.textContent = TEXT; resizeLabel(); copiedTimer = null; }, 900 ); } } function start() { logs = document.getElementById( LOGS_ID ); if (!logs) { return; } abort = new AbortController(); const signal = abort.signal; createOverlay(); updatePosition(); logs.addEventListener( "mouseenter", showOverlay, { signal:signal } ); logs.addEventListener( "mouseleave", hideOverlay, { signal:signal } ); logs.addEventListener( "click", function () { copyLogs(); }, { signal:signal } ); window.addEventListener( "resize", schedulePositionUpdate, { signal:signal } ); window.addEventListener( "scroll", schedulePositionUpdate, { capture:true, signal:signal } ); if ( typeof ResizeObserver !== "undefined" ) { observer = new ResizeObserver( schedulePositionUpdate ); observer.observe( logs ); } window.__logsCopyCleanup = function () { if (abort) { abort.abort(); abort = null; } if (observer) { observer.disconnect(); observer = null; } if (frame) { cancelAnimationFrame( frame ); frame = null; } if (copiedTimer) { clearTimeout( copiedTimer ); copiedTimer = null; } if (overlay) { overlay.remove(); overlay = null; } if (logs) { logs.style.cursor = ""; } }; } if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", start, { once:true } ); } else { start(); } })();
(function () { if (window.__displayOutlineCleanup) { window.__displayOutlineCleanup(); } const DISPLAY_ID = "display"; const TOGGLES_ID = "toggles"; const MAP_ID = "mapdisplay"; const LOGS_ID = "logs"; /* ADJUST THESE */ const OUTLINE_COLOR = "#ffffff"; const OUTLINE_WIDTH = 2; /* Color filling the cut corners. */ const CUT_FILL_COLOR = "#000000"; /* Diagonal cut size. */ const CUT_SIZE = 16; /* Responsive height offsets. */ const TOP_OFFSET_PERCENT = 0.09; const BOTTOM_OFFSET_PERCENT = 0; /* Side offsets. */ const LEFT_OFFSET = -1; const RIGHT_OFFSET = -1; /* ---------------- */ let outline = null; let svg = null; let polygon = null; let observer = null; let frame = null; function removeOutline() { if (outline) { outline.remove(); outline = null; svg = null; polygon = null; } } function createOutline() { removeOutline(); outline = document.createElement( "div" ); outline.id = "display-extended-outline"; outline.style.cssText = ` position:fixed; pointer-events:none; background:transparent; z-index:2147483000; overflow:visible; `; svg = document.createElementNS( "http://www.w3.org/2000/svg", "svg" ); svg.style.cssText = ` position:absolute; inset:0; width:100%; height:100%; overflow:visible; pointer-events:none; `; polygon = document.createElementNS( "http://www.w3.org/2000/svg", "polygon" ); polygon.setAttribute( "fill", "none" ); polygon.setAttribute( "stroke", OUTLINE_COLOR ); polygon.setAttribute( "stroke-width", OUTLINE_WIDTH ); polygon.setAttribute( "vector-effect", "non-scaling-stroke" ); polygon.setAttribute( "stroke-linejoin", "miter" ); svg.appendChild( polygon ); outline.appendChild( svg ); document.body.appendChild( outline ); } function createCutTriangle( points ) { const triangle = document.createElementNS( "http://www.w3.org/2000/svg", "polygon" ); triangle.setAttribute( "points", points ); triangle.setAttribute( "fill", CUT_FILL_COLOR ); triangle.setAttribute( "stroke", "none" ); svg.insertBefore( triangle, polygon ); } function updatePolygon( width, height ) { if ( !polygon || !svg ) { return; } /* Remove old black corner fills. */ svg .querySelectorAll( ".display-cut-fill" ) .forEach(function (element) { element.remove(); }); const halfStroke = OUTLINE_WIDTH / 2; const cut = Math.min( CUT_SIZE, width / 2, height / 2 ); const left = halfStroke; const top = halfStroke; const right = Math.max( halfStroke, width - halfStroke ); const bottom = Math.max( halfStroke, height - halfStroke ); /* Main chamfered outline. */ const points = [ [ left + cut, top ], [ right - cut, top ], [ right, top + cut ], [ right, bottom - cut ], [ right - cut, bottom ], [ left + cut, bottom ], [ left, bottom - cut ], [ left, top + cut ] ]; polygon.setAttribute( "points", points .map(function (point) { return ( point[0] + "," + point[1] ); }) .join(" ") ); /* BLACK CUT AREAS */ /* Top-left */ const topLeft = document.createElementNS( "http://www.w3.org/2000/svg", "polygon" ); topLeft.setAttribute( "class", "display-cut-fill" ); topLeft.setAttribute( "points", [ "0,0", cut + ",0", "0," + cut ].join(" ") ); topLeft.setAttribute( "fill", CUT_FILL_COLOR ); svg.insertBefore( topLeft, polygon ); /* Top-right */ const topRight = document.createElementNS( "http://www.w3.org/2000/svg", "polygon" ); topRight.setAttribute( "class", "display-cut-fill" ); topRight.setAttribute( "points", [ width + ",0", (width - cut) + ",0", width + "," + cut ].join(" ") ); topRight.setAttribute( "fill", CUT_FILL_COLOR ); svg.insertBefore( topRight, polygon ); /* Bottom-right */ const bottomRight = document.createElementNS( "http://www.w3.org/2000/svg", "polygon" ); bottomRight.setAttribute( "class", "display-cut-fill" ); bottomRight.setAttribute( "points", [ width + "," + height, (width - cut) + "," + height, width + "," + (height - cut) ].join(" ") ); bottomRight.setAttribute( "fill", CUT_FILL_COLOR ); svg.insertBefore( bottomRight, polygon ); /* Bottom-left */ const bottomLeft = document.createElementNS( "http://www.w3.org/2000/svg", "polygon" ); bottomLeft.setAttribute( "class", "display-cut-fill" ); bottomLeft.setAttribute( "points", [ "0," + height, cut + "," + height, "0," + (height - cut) ].join(" ") ); bottomLeft.setAttribute( "fill", CUT_FILL_COLOR ); svg.insertBefore( bottomLeft, polygon ); } function updateOutline() { if (!outline) { return; } const display = document.getElementById( DISPLAY_ID ); const toggles = document.getElementById( TOGGLES_ID ); const map = document.getElementById( MAP_ID ); const logs = document.getElementById( LOGS_ID ); if ( !display || !toggles || !map || !logs ) { return; } const displayRect = display.getBoundingClientRect(); const togglesRect = toggles.getBoundingClientRect(); const mapRect = map.getBoundingClientRect(); const logsRect = logs.getBoundingClientRect(); const topOffset = togglesRect.height * TOP_OFFSET_PERCENT; const bottomOffset = displayRect.height * BOTTOM_OFFSET_PERCENT; const top = togglesRect.top + topOffset; const bottom = displayRect.bottom - bottomOffset; const left = mapRect.left + LEFT_OFFSET; const right = logsRect.right - RIGHT_OFFSET; const width = Math.max( 0, right - left ); const height = Math.max( 0, bottom - top ); outline.style.left = left + "px"; outline.style.top = top + "px"; outline.style.width = width + "px"; outline.style.height = height + "px"; updatePolygon( width, height ); } function scheduleUpdate() { if (frame) { cancelAnimationFrame( frame ); } frame = requestAnimationFrame(function () { frame = null; updateOutline(); }); } function start() { const display = document.getElementById( DISPLAY_ID ); const toggles = document.getElementById( TOGGLES_ID ); const map = document.getElementById( MAP_ID ); const logs = document.getElementById( LOGS_ID ); if ( !display || !toggles || !map || !logs ) { return; } createOutline(); updateOutline(); observer = new ResizeObserver( scheduleUpdate ); observer.observe( display ); observer.observe( toggles ); observer.observe( map ); observer.observe( logs ); window.addEventListener( "resize", scheduleUpdate ); window.addEventListener( "scroll", scheduleUpdate, true ); setTimeout( scheduleUpdate, 100 ); setTimeout( scheduleUpdate, 500 ); setTimeout( scheduleUpdate, 1000 ); window.__displayOutlineCleanup = function () { removeOutline(); if (observer) { observer.disconnect(); observer = null; } if (frame) { cancelAnimationFrame( frame ); frame = null; } window.removeEventListener( "resize", scheduleUpdate ); window.removeEventListener( "scroll", scheduleUpdate, true ); }; } if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", start, { once:true } ); } else { start(); } })();
(function () { if (window.__toggleHoverPreviewCleanup) { window.__toggleHoverPreviewCleanup(); } const BUTTON_IDS = [ "showall", "showonlyfavourites", "showonlynonfavourites" ]; const ACTIVE_BACKGROUND = "#222021"; const ACTIVE_TEXT = "#ffffff"; const WHITE_BOX_SCALE = 0.67; const TRANSITION_SPEED = 140; let abort = null; const previews = new Map(); function getButtonParts(id) { const root = document.getElementById(id); if (!root) { return null; } const clickable = root.matches("a,button") ? root : ( root.querySelector("a,button") || root ); const iconTarget = clickable.querySelector("svg,img,i") || clickable.querySelector("*"); return { root:root, clickable:clickable, iconTarget:iconTarget }; } function getRealMode() { if ( window.MultiplexMarkerFilter && typeof window.MultiplexMarkerFilter.getMode === "function" ) { return window.MultiplexMarkerFilter.getMode(); } return "all"; } function isActuallySelected(id) { const mode = getRealMode(); if (id === "showall") { return mode === "all"; } if (id === "showonlyfavourites") { return mode === "favorites"; } if (id === "showonlynonfavourites") { return mode === "nonfavorites"; } return false; } function getPreviewBoxId(id) { return ( "toggle-hover-box-" + id ); } function removePreviewBox(id) { const box = document.getElementById( getPreviewBoxId(id) ); if (box) { box.remove(); } } function getIconPosition(parts) { if (!parts.iconTarget) { return null; } const rect = parts.iconTarget.getBoundingClientRect(); if ( !rect.width || !rect.height ) { return null; } const size = Math.min( rect.width, rect.height ) * WHITE_BOX_SCALE; return { left: rect.left + rect.width / 2 - size / 2, top: rect.top + rect.height / 2 - size / 2, size:size }; } function createPreviewBox(parts) { removePreviewBox( parts.root.id ); const position = getIconPosition(parts); if (!position) { return; } const box = document.createElement("div"); box.id = getPreviewBoxId( parts.root.id ); box.style.cssText = ` position:fixed; left:${position.left}px; top:${position.top}px; width:${position.size}px; height:${position.size}px; background:#ffffff; border:0; outline:0; box-shadow:none; box-sizing:border-box; display:block; pointer-events:none; z-index:2147483647; `; document.body.appendChild( box ); } function applyPreview(id) { if ( isActuallySelected(id) ) { return; } const parts = getButtonParts(id); if (!parts) { return; } if ( previews.has(id) ) { return; } const original = { boxShadow: parts.clickable.style.getPropertyValue( "box-shadow" ), boxShadowPriority: parts.clickable.style.getPropertyPriority( "box-shadow" ), color: parts.clickable.style.getPropertyValue( "color" ), colorPriority: parts.clickable.style.getPropertyPriority( "color" ), transition: parts.clickable.style.getPropertyValue( "transition" ), transitionPriority: parts.clickable.style.getPropertyPriority( "transition" ) }; previews.set( id, original ); /* Dark hover surface. Inset box-shadow paints over the button background without changing Carrd's actual background state. */ parts.clickable.style.setProperty( "box-shadow", `inset 0 0 0 9999px ${ACTIVE_BACKGROUND}`, "important" ); parts.clickable.style.setProperty( "color", ACTIVE_TEXT, "important" ); parts.clickable.style.setProperty( "transition", `box-shadow ${TRANSITION_SPEED}ms ease, color ${TRANSITION_SPEED}ms ease`, "important" ); createPreviewBox( parts ); } function restoreProperty( element, property, value, priority ) { if (value) { element.style.setProperty( property, value, priority || "" ); } else { element.style.removeProperty( property ); } } function removePreview(id) { const original = previews.get(id); const parts = getButtonParts(id); if ( original && parts ) { restoreProperty( parts.clickable, "box-shadow", original.boxShadow, original.boxShadowPriority ); restoreProperty( parts.clickable, "color", original.color, original.colorPriority ); restoreProperty( parts.clickable, "transition", original.transition, original.transitionPriority ); } previews.delete(id); removePreviewBox(id); } function removeAllPreviews() { BUTTON_IDS.forEach( function (id) { removePreview(id); } ); } function refreshPreviewPosition(id) { if ( !previews.has(id) ) { return; } const parts = getButtonParts(id); if (!parts) { return; } const box = document.getElementById( getPreviewBoxId(id) ); if (!box) { return; } const position = getIconPosition(parts); if (!position) { return; } box.style.left = position.left + "px"; box.style.top = position.top + "px"; box.style.width = position.size + "px"; box.style.height = position.size + "px"; } function start() { abort = new AbortController(); const signal = abort.signal; BUTTON_IDS.forEach( function (id) { const parts = getButtonParts(id); if (!parts) { return; } parts.clickable.addEventListener( "mouseenter", function () { applyPreview(id); }, { signal:signal } ); parts.clickable.addEventListener( "mouseleave", function () { removePreview(id); }, { signal:signal } ); parts.clickable.addEventListener( "focus", function () { applyPreview(id); }, { signal:signal } ); parts.clickable.addEventListener( "blur", function () { removePreview(id); }, { signal:signal } ); /* IMPORTANT: Remove temporary hover styling BEFORE the real filter button click happens. Do not restore anything after click. */ parts.clickable.addEventListener( "pointerdown", function () { removeAllPreviews(); }, { capture:true, signal:signal } ); } ); function repositionAll() { BUTTON_IDS.forEach( function (id) { refreshPreviewPosition(id); } ); } window.addEventListener( "resize", repositionAll, { signal:signal } ); window.addEventListener( "scroll", repositionAll, { capture:true, signal:signal } ); window.__toggleHoverPreviewCleanup = function () { removeAllPreviews(); if (abort) { abort.abort(); abort = null; } }; } if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", start, { once:true } ); } else { start(); } })();
(function () { if (window.__executerInvertCleanup) { window.__executerInvertCleanup(); } const FORM_ID = "executer"; const HOVER_BACKGROUND = "#1C1C1C"; const HOVER_TEXT = "#ffffff"; const TRANSITION_SPEED = 120; let form = null; let button = null; let abort = null; function findSendButton() { form = document.getElementById( FORM_ID ); if (!form) { return null; } return ( form.querySelector( 'button[type="submit"]' ) || form.querySelector( 'input[type="submit"]' ) || form.querySelector( "button" ) || form.querySelector( 'a[role="button"]' ) || form.querySelector( "a.button" ) ); } function start() { button = findSendButton(); if (!button) { return; } abort = new AbortController(); const signal = abort.signal; const originalBackground = button.style.backgroundColor; const originalColor = button.style.color; const originalTransition = button.style.transition; button.style.transition = ` background-color ${TRANSITION_SPEED}ms ease, color ${TRANSITION_SPEED}ms ease `; function activateButton() { button.style.setProperty( "background-color", HOVER_BACKGROUND, "important" ); button.style.setProperty( "color", HOVER_TEXT, "important" ); } function restoreButton() { if (originalBackground) { button.style.backgroundColor = originalBackground; } else { button.style.removeProperty( "background-color" ); } if (originalColor) { button.style.color = originalColor; } else { button.style.removeProperty( "color" ); } } button.addEventListener( "mouseenter", activateButton, { signal:signal } ); button.addEventListener( "mouseleave", restoreButton, { signal:signal } ); button.addEventListener( "focus", activateButton, { signal:signal } ); button.addEventListener( "blur", restoreButton, { signal:signal } ); window.__executerInvertCleanup = function () { if (abort) { abort.abort(); abort = null; } if (button) { restoreButton(); button.style.transition = originalTransition; } }; } if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", start, { once:true } ); } else { start(); } })();
(function () { const FORM_ID = "executer"; const LOGS_ID = "logs"; const BACKEND_URL = "https://script.google.com/macros/s/AKfycby3WhG3I1kDSBBTIvPAy_M1mEZKrL-P3U6Zq0WQ6oxEEPdigRBIJA7J0vD2SfnUn-b7/exec"; let output = null; let currentRequest = null; function prepareLogs() { const logs = document.getElementById( LOGS_ID ); if (!logs) { console.error( "#logs not found." ); return false; } logs.style.setProperty( "position", "relative", "important" ); logs.style.setProperty( "overflow", "hidden", "important" ); const oldOutput = document.getElementById( "openai-log-output" ); if ( oldOutput ) { oldOutput.remove(); } output = document.createElement( "div" ); output.id = "openai-log-output"; output.style.cssText = ` position:absolute; inset:0; box-sizing:border-box; padding: 28px 28px 28px 28px; color:#ffffff; font-family: Arial, Helvetica, sans-serif; font-size:16px; font-weight:400; line-height:1.5; text-align:left; white-space:pre-wrap; word-break:break-word; overflow-y:auto; overflow-x:hidden; z-index:10; `; logs.appendChild( output ); return true; } function setLogs( text ) { if (!output) { return; } output.textContent = text; output.scrollTop = output.scrollHeight; } function findInput( form ) { const textarea = form.querySelector( "textarea" ); if ( textarea ) { return textarea; } const textInput = form.querySelector( 'input[type="text"]' ); if ( textInput ) { return textInput; } const searchInput = form.querySelector( 'input[type="search"]' ); if ( searchInput ) { return searchInput; } const emailInput = form.querySelector( 'input:not([type="submit"]):not([type="button"]):not([type="hidden"])' ); return emailInput || null; } async function sendPrompt( prompt ) { prompt = String( prompt || "" ).trim(); if (!prompt) { setLogs( "TYPE A MESSAGE FIRST." ); return; } if ( currentRequest ) { currentRequest.abort(); } currentRequest = new AbortController(); setLogs( "THINKING..." ); try { const response = await fetch( BACKEND_URL, { method: "POST", headers: { "Content-Type": "text/plain;charset=utf-8" }, body: JSON.stringify( { prompt: prompt } ), signal: currentRequest.signal } ); const raw = await response.text(); console.log( "Backend response:", raw ); let data; try { data = JSON.parse( raw ); } catch ( error ) { throw new Error( "Backend returned invalid JSON." ); } if ( data.success !== true ) { throw new Error( data.error || "OpenAI request failed." ); } setLogs( data.text || "No response returned." ); } catch ( error ) { if ( error.name === "AbortError" ) { return; } console.error( "OpenAI request error:", error ); setLogs( "ERROR\n" + error.message ); } } function prepareForm() { const form = document.getElementById( FORM_ID ); if (!form) { console.error( "#executer not found." ); return; } const input = findInput( form ); if (!input) { console.error( "No text input found inside #executer." ); setLogs( "ERROR\nNo text input found inside #executer." ); return; } form.addEventListener( "submit", function ( event ) { event.preventDefault(); event.stopPropagation(); const prompt = input.value; if ( !String( prompt || "" ).trim() ) { return; } sendPrompt( prompt ); input.value = ""; input.focus(); }, true ); input.addEventListener( "keydown", function ( event ) { if ( event.key === "Enter" && !event.shiftKey && input.tagName !== "TEXTAREA" ) { event.preventDefault(); form.dispatchEvent( new Event( "submit", { bubbles: true, cancelable: true } ) ); } } ); console.log( "ChatGPT form ready." ); } function start() { if ( !prepareLogs() ) { return; } setLogs( "READY" ); prepareForm(); window.CarrdChatGPT = { send: sendPrompt }; } if ( document.readyState === "loading" ) { document.addEventListener( "DOMContentLoaded", start, { once: true } ); } else { start(); } })();
(function () { const style = document.createElement("style"); style.id = "logs-jost-font"; const oldStyle = document.getElementById( "logs-jost-font" ); if (oldStyle) { oldStyle.remove(); } style.textContent = ` #logs, #logs *, #openai-log-output, #openai-log-output * { font-family:"Jost", sans-serif !important; font-size:18px !important; } `; document.head.appendChild( style ); })();