1(function(){'use strict';const cfg=window.OBSL||{};const KEY='officebroker_shortlist_v1';const root=document.getElementById('obsl-root');if(!root||root.dataset.ready)return;root.dataset.ready='1';const launcher=document.getElementById('obsl-launcher');const countEl=document.getElementById('obsl-count');const modal=document.getElementById('obsl-modal');const itemsEl=document.getElementById('obsl-items');const emptyEl=document.getElementById('obsl-empty');const enquireBtn=document.getElementById('obsl-enquire');const toast=document.getElementById('obsl-toast');const form=document.getElementById('obsl-enquiry-form');const formSummary=document.getElementById('obsl-form-summary');const formStatus=document.getElementById('obsl-form-status');const successEl=document.getElementById('obsl-success');let ids=readIds();let items={};let lastFocus=null;function readIds(){try{const value=JSON.parse(localStorage.getItem(KEY)||'[]');return Array.isArray(value)?value.map(Number).filter(Boolean).slice(0,Number(cfg.maxItems||20)):[]}catch(e){return[]}} 2function saveIds(){try{localStorage.setItem(KEY,JSON.stringify(ids))}catch(e){}} 3function decodeHtml(value){const textarea=document.createElement('textarea');textarea.innerHTML=String(value||'');return textarea.value} 4function escapeHtml(value){return String(value||'').replace(/[&<>"']/g,function(c){return({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c]})} 5function getListingId(button){if(!button)return 0;const match=String(button.id||'').match(/^eltd-like-(\d+)(?:-|$)/);if(match)return parseInt(match[1],10);const dataId=parseInt(button.getAttribute('data-postid')||button.getAttribute('data-listing-id'),10);if(dataId)return dataId;const bodyMatch=document.body.className.match(/postid-(\d+)/);return bodyMatch?parseInt(bodyMatch[1],10):0} 6function getLikeButtons(){const selectors=new Set(['a.eltd-like']);String(cfg.buttonSelectors||'').split(',').map(s=>s.trim()).filter(Boolean).forEach(s=>selectors.add(s));const buttons=[];selectors.forEach(function(selector){try{document.querySelectorAll(selector).forEach(function(button){if(!buttons.includes(button))buttons.push(button);})}catch(e){}});return buttons} 7function syncHeartStates(){getLikeButtons().forEach(function(button){const id=getListingId(button);if(!id)return;const selected=ids.includes(id);button.classList.toggle('obsl-shortlisted',selected);button.classList.toggle('obsl-heart-selected',selected);button.setAttribute('aria-pressed',selected?'true':'false');button.dataset.obslShortlisted=selected?'1':'0'})} 8function showToast(message){toast.textContent=message;toast.hidden=!1;clearTimeout(showToast.timer);showToast.timer=setTimeout(()=>toast.hidden=!0,2200)} 9function addToShortlist(id){if(!id)return;if(ids.includes(id)){ids=ids.filter(x=>x!==id);saveIds();showToast('Removed from your shortlist')}else{if(ids.length>=Number(cfg.maxItems||20)){showToast('Your shortlist is full. Remove an office to add another.');return} 10ids.push(id);saveIds();showToast('Added to your shortlist')} 11syncHeartStates();render()} 12async function fetchItem(id){if(items[id])return items[id];const body=new URLSearchParams({action:'obsl_listing',nonce:cfg.nonce||'',listing_id:id});try{const r=await fetch(cfg.ajaxUrl,{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'},body});const json=await r.json();if(json.success&&json.data){items[id]=json.data;return json.data}}catch(e){} 13return{id,title:'Office listing #'+id,url:'#',image:'',location:''}} 14async function render(){countEl.textContent=ids.length;launcher.hidden=ids.length===0;itemsEl.innerHTML='';emptyEl.hidden=ids.length!==0;emptyEl.classList.toggle('obsl-is-hidden',ids.length!==0);enquireBtn.disabled=ids.length===0;syncHeartStates();const current=ids.slice();for(const id of current){const item=await fetchItem(id);if(!ids.includes(id))continue;const row=document.createElement('article');row.className='obsl-item';row.innerHTML=(item.image?'<img src="'+escapeHtml(item.image)+'" alt="" class="obsl-item-image">':'<div class="obsl-item-image obsl-item-placeholder">OFFICE</div>')+'<div class="obsl-item-main">'+'<a href="'+escapeHtml(item.url)+'" class="obsl-item-title">'+escapeHtml(decodeHtml(item.title))+'</a>'+(item.location?'<div class="obsl-item-meta">'+escapeHtml(decodeHtml(item.location))+'</div>
14':'')+'</div>'+'<button type="button" class="obsl-remove" data-obsl-remove="'+id+'" aria-label="Remove '+escapeHtml(decodeHtml(item.title))+'">Ã</button>';itemsEl.appendChild(row)}} 15function openModal(view){lastFocus=document.activeElement;modal.hidden=!1;root.querySelectorAll('[data-obsl-view]').forEach(function(v){v.hidden=v.dataset.obslView!==view});document.body.classList.add('obsl-no-scroll');render();const focusable=modal.querySelector('button:not([disabled]),a[href],input,textarea,select');if(focusable)setTimeout(()=>focusable.focus(),0);} 16function closeModal(){modal.hidden=!0;document.body.classList.remove('obsl-no-scroll');resetFormView();if(lastFocus&&typeof lastFocus.focus==='function')lastFocus.focus();} 17function resetFormView(){form.reset();form.hidden=!1;successEl.hidden=!0;formSummary.hidden=!1;formStatus.textContent='';formStatus.className='obsl-form-status';form.querySelector('.obsl-submit').disabled=!1} 18async function prepareForm(){if(!ids.length)return;resetFormView();formSummary.innerHTML='<strong>Shortlisted offices:</strong><span class="obsl-loading">Loadingâ¦</span>';const current=ids.slice();await Promise.all(current.map(fetchItem));if(!current.every(id=>ids.includes(id)))return;formSummary.innerHTML='<strong>Shortlisted offices:</strong><ul>'+current.map(function(id){const item=items[id];return'<li>'+escapeHtml(item?decodeHtml(item.title):('Office #'+id))+'</li>'}).join('')+'</ul>';root.querySelectorAll('[data-obsl-view]').forEach(function(v){v.hidden=v.dataset.obslView!=='form'});const first=form.querySelector('input[name="FullName"]');if(first)setTimeout(()=>first.focus(),0);} 19function setStatus(message,type){formStatus.textContent=message||'';formStatus.className='obsl-form-status'+(type?' is-'+type:'')} 20async function submitEnquiry(e){e.preventDefault();setStatus('');if(!ids.length){setStatus('Please add at least one office to your shortlist.','error');return} 21if(!form.checkValidity()){form.reportValidity();return} 22const submit=form.querySelector('.obsl-submit');submit.disabled=!0;setStatus('Sending enquiryâ¦','sending');const data=new FormData(form);data.append('action','obsl_enquiry');data.append('nonce',cfg.nonce||'');data.append('obsl_shortlist',ids.join(','));try{const response=await fetch(cfg.ajaxUrl,{method:'POST',body:data,credentials:'same-origin'});const json=await response.json();if(!json.success){throw new Error(json.data&&json.data.message?json.data.message:'The enquiry could not be sent.')} 23form.hidden=!0;successEl.hidden=!1;formSummary.hidden=!0}catch(error){setStatus(error.message||'The enquiry could not be sent. Please try again.','error');submit.disabled=!1}} 24document.addEventListener('click',function(e){const button=e.target.closest?e.target.closest('a.eltd-like'):null;if(button){const id=getListingId(button);if(id){setTimeout(function(){addToShortlist(id);setTimeout(function(){syncHeartStates()},220)},0)} 25return} 26const remove=e.target.closest?e.target.closest('[data-obsl-remove]'):null;if(remove){ids=ids.filter(x=>x!==parseInt(remove.dataset.obslRemove,10));saveIds();syncHeartStates();render();return} 27if(e.target.closest('#obsl-launcher')){openModal('shortlist');return} 28if(e.target.closest('[data-obsl-close]')){closeModal();return} 29if(e.target.closest('#obsl-clear')){ids=[];saveIds();render();showToast('Shortlist cleared');return} 30if(e.target.closest('#obsl-enquire')){if(!ids.length)return;openModal('form');prepareForm();return}},!1);form.addEventListener('submit',submitEnquiry);const heartObserver=new MutationObserver(function(){clearTimeout(heartObserver.timer);heartObserver.timer=setTimeout(syncHeartStates,80)});if(document.body){heartObserver.observe(document.body,{childList:!0,subtree:!0})} 31document.addEventListener('keydown',function(e){if(e.key==='Escape'&&!modal.hidden)closeModal();});render()})() 32;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.