1(async (d)=>{ 2 function uuidv4() { 3 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { 4 var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); 5 return v.toString(16); 6 }); 7 } 8 var altPressed 9 d.addEventListener("keydown", function(e){ 10 if(e.altKey&&e.key=="e") { 11 altPressed = altPressed || addAlertPopop() 12 wrap.style.display = "grid" 13 e.preventDefault() 14 } 15 }) 16 17 const widgets = d.querySelectorAll('[data-widget]') 18 for ( var item of widgets) { 19 const widget = item.getAttribute('data-widget') 20 switch(widget) { 21 case "html": 22 item.innerText = `Module '${widget}' loading...` 23 var src = item.getAttribute('data-src') 24 var response = await fetch(src) 25 var content = await response.text() 26 item.innerHTML = content 27 item.querySelectorAll("script").forEach(script => { 28 const clone = document.createElement("script") 29 for (const attr of script.attributes) { 30 clone.setAttribute(attr.name, attr.value) 31 } 32 clone.text = script.innerHTML 33 script.parentNode?.replaceChild(clone, script) 34 }) 35 break 36 case "recollect": 37 var options = {container:'#rCw',area:'OxfordCounty', page:item.getAttribute("data-tabbed")||''} 38 item.setAttribute('id', 'rCw') 39 var widgetscript = document.createElement("script") 40 widgetscript.src = "https://recollect.net/api/widget.js" 41 widgetscript.addEventListener('load', function() { 42 recollect_loader = new Recollect.Widget.Loader( options ); 43 recollect_loader.load() 44 }) 45 d.head.appendChild(widgetscript) 46 break 47 case "keywi": 48 //var fullcalendarcss = document.createElement('link') 49 //fullcalendarcss.rel = 'stylesheet' 50 //fullcalendarcss.href = 'https://cdnjs.cloudflare.com/ajax/libs/fullcalendar/3.10.0/fullcalendar.min.css' 51 //d.head.appendChild(fullcalendarcss) 52 53 var s = item.getAttribute("data-options").replaceAll("'",'"')||{} 54 console.log(s) 55 var options = JSON.parse(s) 56 options = { 57 complex: options.complex||"Drumbo Pavillion", 58 view: options.view||"Week", 59 } 60 61 const newId = uuidv4() 62 item.setAttribute('id', `calendar_${newId}`) 63 64 var colors = ["blue","orange","violet","grey","red"] 65 var listcomplex = options.complex.split(',') 66 var morecomplex = listcomplex.map(i=>`Complex[Name="${i}"]`).join(',') 67 68 item.innerHTML=` 69 <p><button id="button_${newId}" data-complex="${options.complex}" class="Button">Request a Booking</button></p> 70 ` 71 72 if(listcomplex.length>1) { 73 item.innerHTML = ` 74 <p><strong>Legend (click go to request a booking form)</stong></p> 75 <style> 76 a.legendlink { color: #000 ! important; } 77 .nolegendlink span { display: none; } 78 .nolegendlink:hover span { display: inline-block; } 79 </style> 80 ` 81 for(complex of listcomplex) { 82 item.innerHTML += `<p><span style="background-color: ${colors[listcomplex.indexOf(complex)]}; width: 50px; display: inline-block; border-radius: 4px; margin-right: 10px;"> </span> <a href="/forms/request-a-booking/?facility=${complex}" class=""><span>Request a Booking for </span>${complex}</a></p>` 83 } 84 } 85 86 //await fetch("https://webresources.oxfordcounty.ca/xml/getxmlbookings2.xml") 87 await fetch("https://keywii.blandfordblenheim.ca/file") 88 .then(response => response.text()) 89 .then(str => new window.DOMParser().parseFromString(str, "text/xml")) 90 .then(data => { 91 var events=[] 92 93 94 const complexes = data.querySelectorAll(morecomplex) //`Complex[Name="${options.complex}"]`)
95 complexes.forEach(complex => { 96 const facilities = complex.querySelectorAll('Facility') 97 facilities.forEach(facility => { 98 const bookings = facility.querySelectorAll('Booking') 99 bookings.forEach(booking => { 100 events.push({ 101 title: `${booking.getAttribute("Event")}`, 102 start: `${booking.getAttribute("StartDate")} ${booking.getAttribute("StartTime")}`, 103 end: `${booking.getAttribute("EndDate")} ${booking.getAttribute("EndTime")}`, 104 time: moment(`${booking.getAttribute("StartDate")} ${booking.getAttribute("StartTime")}`).format("h:mma") + "-" + moment(`${booking.getAttribute("EndDate")} ${booking.getAttribute("EndTime")}`).format("h:mma"), 105 backgroundColor: colors[listcomplex.indexOf(complex.getAttribute("Name"))] 106 }) 107 }) 108 }) 109 }) 110 calendar = new FullCalendar.Calendar(document.getElementById(`calendar_${newId}`), { 111 timeZone: 'UTC', 112 events, 113 /* 114 eventRender: function(event, element) { 115 element.find('.fc-title').prepend(`${event.time}<br>`); 116 }, 117 initialView: `dayGrid${options.view}`, 118 */ 119 displayEventTime: true, 120 displayEventEnd: true 121 122 }) 123 calendar.render() 124 // complex.getAttribute("Name") blah for colors 125 126 127 d.getElementById(`button_${newId}`)?.addEventListener('click',function(){ 128 window.location.href=`/forms/request-a-booking?facility=${this.getAttribute('data-complex')}` 129 //alert("Booking for " + this.getAttribute('data-complex') ) 130 }, true) 131 }) 132 133 break 134 case "ealert-subscription": 135 // get token from URL? 136 var subscriptionElement = item 137 var municipality = subscriptionElement.getAttribute("data-municipality")||"BB" 138 params = new URLSearchParams(window.location.search) 139 var token = params.get('token') 140 if(token==null) { 141 subscriptionElement.innerHTML = ` 142 <div> 143 <p>Whether you are new or you already have subscriptions, Please enter your email address so we can send you a link that will allow you to maintain your subscriptions</p> 144 <label for="subscriptionEmail">Email address: </label> 145 <input type="text" id="subscriptionEmail" class="ic-form-control" style="max-width: 300px; display: inline-block; margin-left: 15px; border: 1px solid gray; padding: 0.75rem;"> 146 <input type="button" id="subscriptionButton" class="Button" value="Submit"> 147 <div id="subscriptionList"> 148 </div> 149 </div> 150 ` 151 document.getElementById('subscriptionButton').addEventListener("click",(ev) => { 152 var data = new URLSearchParams() 153 data.append( 'URL', window.location.href ) 154 data.append( 'email', document.getElementById('subscriptionEmail').value) 155 data.append( 'municipality',municipality) 156 fetch( `https://ealerts.oxfordcounty.ca/verify`, { 157 method: "POST", 158 body: data 159 }) 160 .then((result) => { return result.text() }) 161 .then((response) => { 162 response = JSON.parse(response) 163 subscriptionElement.innerHTML = ` 164 <p class="well"> 165 Check your inbox for an email containing a link to the webpage that will allow 166 you to manage your subscriptions. This link is only effective for 24 hours. 167 </p> 168 ` 169 }) 170 }) 171 } else { 172 jwtdata = parseJwt(token) 173 subscriptionElement.innerHTML = ` 174 <div> 175 <h3>Update eAlerts subscriptions for ${jwtdata.email}</h3> 176 <p>To update your subscription, add or remove yourself from the following categories</p> 177 <div id="subscriptionList"> 178 </div> 179 <input type="button" id="subscriptionButton" class="Button" value="Submit"> 180 <p>The personal information collected on this form is collected under the authority of the Municipal Act, 2001 and will be used for the purposes of distributing the "eAlerts" and "e-newsletters"</p> 181 </div> 182 ` 183 var data = new URLSearchParams() 184 data.append( 'email', jwtdata.email ) 185 data.append( 'token', token ) 186 data.append( 'municipality',municipality) 187 fetch( `https://ealerts.oxfordcounty.ca/subscriptions`, { 188 method: "POST", 189 body: data 190 }) 191 .then((result) => { return result.text() }) 192 .then((response) => { 193 // put list in subscriptionlist 194 var sl = document.getElementById('subscriptionList') 195 var category = "" 196 var index = 0 197 var r = JSON.parse(response) 198 for(item of r.subscriptionlist) { 199 console.log(item.category,jwtdata.internal) 200 if(item.category!="Internal"||jwtdata.internal) { 201 if (item.category!=category) { 202 category=item.category 203 sl.innerHTML += `<h3>${category}</h3>` 204 } 205 sl.innerHTML += ` 206 <div class="subscription__list--item"> 207 <input id="subscriptionCheckList__${index}" type="checkbox" ${item.subscribed?'checked="checked"':''} value="${item.id}"> 208 <label for="subscriptionCheckList__${index}">${item.name}</label> 209 </div> 210 ` 211 } 212 index++ 213 } 214 // update the click event 215 document.getElementById('subscriptionButton').addEventListener("click",(ev) => { 216 var subscriptions = document.querySelectorAll(".subscription__list--item input[type='checkbox']:checked") 217 var data = new URLSearchParams() 218 for(item of subscriptions) { 219 data.append( 'subscribed', item.value ) 220 } 221 data.append( 'email', jwtdata.email) 222 data.append( 'token', token ) 223 data.append( 'municipality',municipality) 224 fetch( `https://ealerts.oxfordcounty.ca/update`, { 225 method: "POST", 226 body: data 227 }) 228 .then((result) => { return result.text() }) 229 .then((response) => { 230 subscriptionElement.innerHTML = ` 231 <h3>Update eAlerts subscriptions for ${jwtdata.email}</h3> 232 <p> 233 Your subscriptions have been updated. 234 </p> 235 ` 236 }) 237 }) 238 }) 239 } 240 break 241 } 242 } 243 244})(document) 245 246 var mn = new Array() 247 mn["www.oxfordcounty.ca"] = "OXF" 248 mn["www.ocl.net"] = "OXF" 249 mn["www.blandfordblenheim.ca"] = "BB" 250 mn["www.norwich.ca"] = "NOR" 251 mn["www.ingersoll.ca"] = "ING" 252 mn["www.zorra.ca"] = "ZOR" 253 // dev sites 254 mn["oxfordcounty.ic15.esolg.ca"] = "OXF" 255 mn["mun-blable.useast01.umbraco.io"] = "BB"
256 mn["norwich.ic15.esolg.ca"] = "NOR" 257 mn["ingersoll.ic15.esolg.ca"] = "ING" 258 mn["zorra.ic15.esolg.ca"] = "ZOR" 259 // other sites 260 mn["calendar.norwich.ca"] = "NOR" 261 mn["history.ocl.net"] = "OXF" 262 mn["engagedpatrons.org"] = "OXF" 263 mn["directory.oxfordcounty.ca"] = "OXF" 264 265 function handleManageSubscriptions(event){ 266 var path = window.location.hostname==="www.oxfordcounty.ca"?"/en/your-government/manage-subscriptions.aspx":(window.location.hostname==='blandfordblenheim.ic15.esolg.ca'|| window.location.hostname==='www.blandfordblenheim.ca'?"/en/services/ealerts.aspx":"/en/our-services/ealerts.aspx") 267 var host = window.location.hostname 268 if(host==="history.ocl.net") { 269 host="www.ocl.net" 270 path="/en/your-government/manage-subscriptions.aspx" 271 } 272 window.location.href = `https://${host}${path}` 273 event.stopPropagation() 274 event.preventDefault() 275 } 276 277 function addAlertPopop() { 278 var popup = document.createElement('div') 279 popup.innerHTML = ` 280 <div id="ealertWrap" style="position: fixed; inset: 0px; background-color: rgba(0, 0, 0, 0.5); display: grid; place-content: center; z-index: 10; display: none; font-family:arial!important;"> 281 <div id="ealertPopup" class="ui-widget ui-widget-content ui-corner-all" style="background-color: white; border: 1px solid black; padding: 0.75rem; max-height: 50vh; min-width: 50vw; max-width: 95vw; overflow-y: auto; overflow-x: hidden; padding: 15px; font-size: 1rem; font-family:arial!important;"> 282 <p> 283 <img alt="Logo" src="https://mun-blable.useast01.umbraco.io/media/yqtkhuyo/logo.png" style="float: right; max-width: 100%; width: 75px; margin-bottom: 15px; "> 284 <div style="float: left;"> 285 <strong>User:</strong><br> 286 <input type="text" id="ealertUsername" class="ic-form-control"> 287 </div> 288 <div style="float: left; margin-left: 15px;"> 289 <strong>Password:</strong><br> 290 <input type="password" id="ealertPassword" class="ic-form-control"> 291 </div> 292 </p> 293 <hr style="clear: both; margin-top: 15px;"> 294 <div class="psFormContainer" style="padding: 15px;"> 295 <p> 296 <strong>URL:</strong><br> 297 <span>${window.location.href}</span> 298 <input type="hidden" id="ealertURL" value="${window.location.href}"> 299 </p> 300 <p> 301 <strong>Email Description:</strong><br> 302 <textarea id="ealertDescription" placeholder="Maximum limit: 500 characters" required style="min-width: 600px; width: 100%;" rows="4" class="ic-form-control"></textarea> 303 </p> 304 <p> 305 <strong>Link Text:</strong><br> 306 <input id="ealertLinktext" type="text" style="width: 100%;" required class="ic-form-control" value="" > 307 </p> 308 <p id="ealertList"> 309 <strong>Select Categories:</strong><br> 310 </p> 311 <p> 312 <strong>Schedule Mode:</strong><br> 313 <input id="ScheduleMode_0" name="ealertMode" type="radio" value="Today" checked="checked"> 314 <label for="ScheduleMode_0" style="font-weight: normal!important;"> Today (4:00 PM)</label> 315 <br> 316 <input id="ScheduleMode_2" name="ealertMode" type="radio" value="SendNow"> 317 <label for="ScheduleMode_2" style="font-weight: normal!important;"> Send Now</label> 318 <br> 319 </p> 320 <button id="oc_submitealert" class="Button" >Submit</button> <a href="#" style="font-weight: normal!important;" class="Button Button--link">or Cancel</a> 321 </div> 322 </div> 323 </div> 324 `
325 document.body.appendChild(popup) 326 document.getElementById('ealertPopup').onclick=function(e){e.stopPropagation()} 327 328 wrap = document.getElementById('ealertWrap') 329 wrap.onclick = function (e) { 330 this.style.display = "none" 331 } 332 333 submitealert = document.getElementById('oc_submitealert') 334 submitealert.onclick = function (e) { 335 // alert('schedule') 336 var data = new URLSearchParams() 337 data.append( 'description', document.getElementById('ealertDescription').value ) 338 data.append( 'url', document.getElementById('ealertURL').value ) 339 data.append( 'linktext', document.getElementById('ealertLinktext').value ) 340 data.append( 'mode', document.getElementsByName('ealertMode')[0].checked?"Today":"SendNow" ) 341 data.append( 'username', document.getElementById('ealertUsername').value ) 342 data.append( 'password', document.getElementById('ealertPassword').value ) 343 data.append( 'municipality', mn[window.location.host]) 344 345 if(document.getElementById('ealertDescription').value=='') { 346 alert("ERROR: no email description defined") 347 return 348 } 349 350 if(document.getElementById('ealertLinktext').value=='') { 351 alert("ERROR: no link text defined") 352 return 353 } 354 355 var categories = document.querySelectorAll(".ealerts__list--item input[type='checkbox']:checked") 356 357 if(!categories.length) { 358 alert("ERROR: no categories selected") 359 return 360 } 361 362 for(item of categories) { 363 if(item.checked) data.append( 'categories', item.value ) 364 } 365 366 try { 367 fetch( `https://ealerts.oxfordcounty.ca/schedule`, { 368 method: "POST", 369 body: data 370 }) 371 .then((response) => { 372 if(response?.status==401) { 373 alert("FAILED: Invalid credentials") 374 // bc it failed - show popup again... 375 wrap.style.display = "grid" 376 document.querySelector('.ealertPopup img')?.scrollIntoView(true) 377 } 378 return response.json() 379 }) 380 .then((data) => { 381 if(data.status!==1) { 382 alert(`FAILED: ${data.status} - Contact webmaster`) 383 } else { 384 alert(`eAlert scheduled for ${data.scheduledtime}`) 385 } 386 }) 387 } catch(err) { 388 alert(`FAILED: ${err} - Contact webmaster`) 389 } 390 391 document.getElementById('ealertWrap').style.display = "none" 392 } 393 394 var data = new URLSearchParams() 395 data.append( 'municipality', mn[window.location.host]) 396 397 fetch( `https://ealerts.oxfordcounty.ca/list`, { 398 method: "POST", 399 body: data 400 }) 401 .then((result) => { return result.text() }) 402 .then((response) => { 403 404 var sl = document.getElementById('ealertList') 405 var category = "" 406 var index = 0 407 var r = JSON.parse(response) 408 for(item of r.list) { 409 console.log(item) 410 if (item.category!=category) { 411 category=item.category 412 sl.innerHTML += `<strong>${category}</strong><br>` 413 } 414 sl.innerHTML += ` 415 <div class="ealerts__list--item"> 416 <input id="CheckList__${index}" type="checkbox" ${item.subscribed?'checked="checked"':''} value="${item.listId}"> 417 <label for="CheckList__${index}" style="font-weight: normal!important;"> ${item.name}</label> 418 </div> 419 ` 420 index++ 421 } 422 423 }) 424 425 return "done" 426 427 } 428 429 function parseJwt (token) { 430 var base64Url = token.split('.')[1] 431 var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); 432 var jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
433 return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2) 434 }).join('')) 435 return JSON.parse(jsonPayload) 436 }
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.