1/** 2 * Utils section. 3 * Contain helper functions to build ccl queries and other 4 * cross platform support functions 5 */ 6$.fn.serializeObject = function() { 7 var o = {}; 8 var a = this.serializeArray(); 9 $.each(a, function() { 10 if (o[this.name] !== undefined) { 11 if (!o[this.name].push) { 12 o[this.name] = [o[this.name]]; 13 } 14 o[this.name].push(this.value || ''); 15 } else { 16 o[this.name] = this.value || ''; 17 } 18 }); 19 return o; 20}; 21 22String.prototype.cclTermSafe = function() { 23 return ['"', this.replace(/"/g, ""), '"'].join(''); 24}; 25 26String.prototype.wrapWithBrackets = function() { 27 return ['(', this, ')'].join(''); 28}; 29 30Array.prototype.cclTermSafe = function() { 31 var newArray = []; 32 $.each(this, function(index, value) { 33 newArray.push(['"', value.replace(/"/g, ""), '"'].join('')); 34 }); 35 36 return newArray; 37}; 38 39// Returns a JSON object with all URL parameters 40function getURLParameters(url) { 41 var resultJson = {}; 42 if (url && url.length > 0) { 43 var splitParams = url.substring(1).split("&"); 44 for (var i = 0; i < splitParams.length; i++) { 45 var splitParam = splitParams[i].split("="); 46 if (splitParam.length === 2) { 47 var paramName = decodeURIComponent(splitParam[0]); 48 var paramVal = decodeURIComponent(splitParam[1].replace(/\+/g, " ")); 49 var currentVal = resultJson[paramName]; 50 if (currentVal) { 51 if ($.isArray(currentVal)) { 52 currentVal.push(paramVal); 53 resultJson[paramName] = currentVal; 54 } else { 55 resultJson[paramName] = [currentVal, paramVal]; 56 } 57 } else { 58 resultJson[paramName] = paramVal; 59 } 60 } 61 } 62 } 63 return resultJson; 64} 65 66function getURLParameter(name) { 67 68 var uri = decodeURIComponent((RegExp(name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1]); 69 if(uri) 70 uri = uri.replace(/[+]/g, " "); 71 72 return uri; 73} 74 75function isValidDate(dateString) { 76 if(dateString == null || dateString == "") { 77 return false; 78 } 79 return dateString.search(/1500-01-01/) == -1; 80} 81 82function secondsToMidnight() { 83 var now = new Date(); 84 var then = new Date(now) 85 then.setHours(24,0,0,0); 86 // 1 minute = 6e4 milliseconds 87 return (then - now) / 60 88} 89 90String.prototype.hashCode = function() { 91 var hash = 0; 92 if (this.length == 0) return hash; 93 for (i=0; i < this.length; i++) { 94 c = this.charCodeAt(i); 95 hash = ((hash<<5) - hash) + c; 96 hash = hash & hash; // Convert to 32bit integer 97 } 98 return hash; 99} 100 101function getSizeString(sizeInBytes) { 102 var size = sizeInBytes / 1024; 103 if(size < 1024){ 104 return size.toFixed() + " KB"; 105 } else { 106 size = size / 1024.00; 107 return size.toFixed(2) + " MB"; 108 } 109} 110 111function getDisplayQueryHtml(urlParameters) { 112 var display = 'Document Types="'; 113 114 // Build the collection ccl 115 var collections = []; 116 var collectionDisplay = []; 117 if (urlParameters["q-collection[]"] && urlParameters["q-collection[]"] instanceof Array) { 118 collections = urlParameters["q-collection[]"]; 119 } else if (urlParameters["q-collection[]"]) { 120 collections.push(urlParameters["q-collection[]"].toString()); 121 } 122 123 $.each(collections, function(index, value) { 124 // Build sub ccl for collection 125 if (value == "inforceActs") { 126 collectionDisplay.push("<span class='dq-highlight'>Acts</span>"); 127 } else if (value == "inforceSLs") { 128 collectionDisplay.push("<span class='dq-highlight'>SL</span>"); 129 } else if (value == "actsAsPassed") { 130 collectionDisplay.push("<span class='dq-highlight'>Acts as passed</span>"); 131 } else if (value == "slAsMade") { 132 collectionDisplay.push("<span class='dq-highlight'>SL as made</span>"); 133 } else if (value == "repealedActs") {
134 collectionDisplay.push("<span class='dq-highlight'>Repealed Acts</span>"); 135 } else if (value == "repealedSLs") { 136 collectionDisplay.push("<span class='dq-highlight'>Repealed SL</span>"); 137 } else if (value == "bills") { 138 collectionDisplay.push("<span class='dq-highlight'>Bills</span>"); 139 } else if (value == "otherasscdocs") { 140 collectionDisplay.push("<span class='dq-highlight'>Other docs</span>"); 141 } else if (value == "expnotes") { 142 collectionDisplay.push("<span class='dq-highlight'>Exp Notes</span>"); 143 } else if (value == "currentLH") { 144 collectionDisplay.push("<span class='dq-highlight'>Legislative histories</span>"); 145 } else if (value == "repealedLH") { 146 collectionDisplay.push("<span class='dq-highlight'>Repealed legislative histories</span>"); 147 } else if (value == "website") { 148 collectionDisplay.push("<span class='dq-highlight'>Website info and help</span>"); 149 } 150 }); 151 152 display += collectionDisplay.join(", ") + "\""; 153 154 switch(urlParameters["q-searchform"]) { 155 case "basic": 156 if (urlParameters["q-searchfor"] == "") 157 { 158 if(urlParameters["q-year"]) 159 { 160 display += ', Year="<span class=\'dq-highlight\'>' + htmlEncode(urlParameters["q-year"]) + '</span>"'; 161 } 162 163 if(urlParameters["q-no"]) 164 { 165 display += ', No="<span class=\'dq-highlight\'>' + htmlEncode(urlParameters["q-no"]) + '</span>"'; 166 } 167 break; 168 } 169 170 if (urlParameters["q-searchin"] == "Content") { 171 display += ', Search In="<span class=\'dq-highlight\'>All Content</span>", '; 172 } else if (urlParameters["q-searchin"] == "Heading") { 173 display += ', Search In="<span class=\'dq-highlight\'>All Headings</span>", '; 174 } else if (urlParameters["q-searchin"] == "Title") { 175 display += ', Search In="<span class=\'dq-highlight\'>Title</span>", '; 176 } else if (urlParameters["q-searchin"] == "Part,Division") { 177 display += ', Search In="<span class=\'dq-highlight\'>Part/Division Headings</span>", '; 178 } else if (urlParameters["q-searchin"] == "Schedule") { 179 display += ', Search In="<span class=\'dq-highlight\'>Schedule Headings</span>", '; 180 } else if (urlParameters["q-searchin"] == "DefinedTerm") { 181 display += ', Search In="<span class=\'dq-highlight\'>Defined Terms</span>", '; 182 } else if (urlParameters["q-searchin"] == "Titles") { 183 display += ', Search In="<span class=\'dq-highlight\'>Historical Title</span>", '; 184 } 185 186 // Build the search term ccl 187 if (urlParameters["q-searchusing"] == "allwords") {
188 display += 'All Words="<span class=\'dq-highlight\'>'; 189 display += htmlEncode(urlParameters["q-searchfor"]); 190 display += '</span>"'; 191 } else if (urlParameters["q-searchusing"] == "anywords") { 192 display += 'Any Words="<span class=\'dq-highlight\'>'; 193 display += htmlEncode(urlParameters["q-searchfor"]); 194 display += '</span>"'; 195 } else if (urlParameters["q-searchusing"] == "exactwords") { 196 display += 'Exact Phrase="<span class=\'dq-highlight\'>'; 197 display += htmlEncode(urlParameters["q-searchfor"]); 198 display += '</span>"'; 199 } else if (urlParameters["q-searchusing"] == "woutwords") { 200 display += 'Without Words="<span class=\'dq-highlight\'>'; 201 display += htmlEncode(urlParameters["q-searchfor"]); 202 display += '</span>"'; 203 } 204 205 if(urlParameters["q-year"]) 206 { 207 display += ', Year="<span class=\'dq-highlight\'>' + htmlEncode(urlParameters["q-year"]) + '</span>"'; 208 } 209 210 if(urlParameters["q-no"]) 211 { 212 display += ', No="<span class=\'dq-highlight\'>' + htmlEncode(urlParameters["q-no"]) + '</span>"'; 213 } 214 215 if(urlParameters["q-point-in-time"]) 216 { 217 display += ', Point In Time="<span class=\'dq-highlight\'>' + htmlEncode(urlParameters["q-point-in-time"]) + '</span>"'; 218 } 219 220 break; 221 case "advanced": 222 var getDisplayField = function(val) { 223 if (val == "Content") { 224 return "Search in=\"<span class='dq-highlight'>All Content</span>\""; 225 } else if (val == "Heading") { 226 return "Search in=\"<span class='dq-highlight'>All Headings</span>\""; 227 } else if (val == "Title") { 228 return "Search in=\"<span class='dq-highlight'>Title</span>\""; 229 } else if (val == "Part,Division") { 230 return "Search in=\"<span class='dq-highlight'>Part/Division Headings</span>\""; 231 } else if (val == "Schedule") { 232 return "Search in=\"<span class='dq-highlight'>Schedule Headings</span>\""; 233 } else if (val == "DefinedTerm") { 234 return "Search in=\"<span class='dq-highlight'>Defined Terms</span>\""; 235 } 236 else 237 { 238 return "Unknown Field"; 239 } 240 } 241 var rowDisplays = []; 242 var joinOperators = []; 243 244 $.each(urlParameters["q-searchfor[]"], function(idx, val){ 245 // Skip empty ones 246 if(val === "") 247 return; 248 249 var rowDisplay = " "; 250 251 if (urlParameters["q-searchusing[]"][idx] == "allwords") { 252 var allWordsExp = val.split(/\s+/).cclTermSafe().join(" AND "); 253 254 rowDisplay += getDisplayField(urlParameters["q-searchin[]"][idx]); 255 rowDisplay += ", Where"; 256 rowDisplay += " All Words=\"<span class='dq-highlight'>" + htmlEncode(urlParameters["q-searchfor[]"][idx]); 257 rowDisplay += "</span>\""; 258 259 } else if (urlParameters["q-searchusing[]"][idx] == "anywords") { 260 var anyWordsExp = val.split(/\s+/).cclTermSafe().join(" OR "); 261 262 rowDisplay += getDisplayField(urlParameters["q-searchin[]"][idx]); 263 rowDisplay += ", Where"; 264 rowDisplay += " Any Words=\"<span class='dq-highlight'>" + htmlEncode(urlParameters["q-searchfor[]"][idx]); 265 rowDisplay += "</span>\""; 266 267 } else if (urlParameters["q-searchusing[]"][idx] == "exactwords") { 268 269 rowDisplay += getDisplayField(urlParameters["q-searchin[]"][idx]); 270 rowDisplay += ", Where"; 271 rowDisplay += " Exact Phrase=\"<span class='dq
271-highlight'>" + htmlEncode(urlParameters["q-searchfor[]"][idx]); 272 rowDisplay += "</span>\""; 273 274 } else if (urlParameters["q-searchusing[]"][idx] == "woutwords") { 275 276 rowDisplay += getDisplayField(urlParameters["q-searchin[]"][idx]); 277 rowDisplay += ", Where"; 278 rowDisplay += " Without Words=\"<span class='dq-highlight'>" + htmlEncode(urlParameters["q-searchfor[]"][idx]); 279 rowDisplay += "</span>\""; 280 } 281 282 // Collect the operator if not on the first 283 if(idx !== 0) 284 { 285 joinOperators.push(urlParameters["q-operator[]"][idx]); 286 } 287 288 rowDisplays.push(rowDisplay); 289 }); 290 291 292 293 // Now join each query row with the operator 294 var rowsDisplayQuery = ""; 295 $.each(rowDisplays, function(idx, val){ 296 rowsDisplayQuery += val; 297 298 if(joinOperators[idx]) 299 rowsDisplayQuery += " <b>" + joinOperators[idx] + "</b> "; 300 }); 301 302 display += rowsDisplayQuery; 303 304 if(urlParameters["q-years"]) 305 { 306 display += ', Year="<span class=\'dq-highlight\'>' + htmlEncode(urlParameters["q-years"]) + '</span>"'; 307 } 308 309 if(urlParameters["q-no"]) 310 { 311 display += ', No="<span class=\'dq-highlight\'>' + htmlEncode(urlParameters["q-no"]) + '</span>"'; 312 } 313 314 if(urlParameters["q-point-in-time"]) 315 { 316 display += ', Point In Time="<span class=\'dq-highlight\'>' + htmlEncode(urlParameters["q-point-in-time"]) + '</span>"'; 317 } 318 break; 319 case "menuAssisted": 320 display += ', '; 321 322 display += "Query=\"<span class='dq-highlight'>" 323 + htmlEncode(urlParameters["q-queryBuilderOutput"].replace(/([ ](AND|OR|NOT|WITH|SAME|!10|%10))$/, '')); 324 display += "</span>\""; 325 326 if(urlParameters["q-years"]) 327 { 328 display += ', Year="<span class=\'dq-highlight\'>' + htmlEncode(urlParameters["q-years"]) + '</span>"'; 329 } 330 331 if(urlParameters["q-no"]) 332 { 333 display += ', No="<span class=\'dq-highlight\'>' + htmlEncode(urlParameters["q-no"]) + '</span>"'; 334 } 335 336 if(urlParameters["q-point-in-time"]) 337 { 338 display += ', Point In Time="<span class=\'dq-highlight\'>' + htmlEncode(urlParameters["q-point-in-time"]) + '</span>"'; 339 } 340 break; 341 } 342 return display; 343} 344 345// Ideally we would overwrite the fnStateSave and fnStateLoad functions of datatable, but 346// this would require us to replicate various settings when the cookie is missing, so 347// it is simpler to use the function below when rendering a table instead, disabling the 348// state saving functionality of datatables altogether. 349 350function renderTable(table) { 351 table.pageLength = $.jStorage.get("results-per-page"); 352 if (table.pageLength == null){ 353 table.pageLength = 10; 354 } 355 356 // Show the page that the user was on when previously viewing this table. 357 if (window.sessionStorage.getItem("table-history")) { 358 var pageDetails = JSON.parse(window.sessionStorage.getItem("table-history"))[window.location.pathname + $.address.value()]; 359 if (pageDetails) { 360 table.displayStart = pageDetails.displayStart; 361 362 if (pageDetails.sortFields && pageDetails.sortDirections) { 363 // Ensure that the sort order that the user previously used for this table is remembered for this session. 364 var foundIndexes = []; 365 for (var j = 0; j < pageDetails.sortFields.length; j++) { 366 for (var i = 0; i < table.columns.length; i++) { 367 if (table.columns[i].key === pageDetails.sortFields[j] || 368 table.columns[i].sortKey === pageDetails.sortFields[j]) { 369 370 foundIndexes.push(i); 371 } else if ((j === 0) && (table.columns[i].sortable === "defaultAsc" || table.columns[i].sortable === "defaultDesc")) { 372 table.columns[i].sortable = true; 373 } 374 } 375 } 376 for (var k = 0; k < foundIndexes.length; k++) { 377 var append = true; 378 if (foundIndexes.length > k + 1) { 379 append = foundIndexes[k + 1] > foundIndexes[k]; 380 } 381 if (pageDetails.sortDirections[k] === "asc") { 382 if (append) { 383 table.columns[foundIndexes[k]].sortable = "defaultAsc"; 384 } else { 385 table.columns[foundIndexes[k]].sortable = "defaultAscPrepend"; 386 } 387 } else { 388 if (append) { 389 table.columns[foundIndexes[k]].sortable = "defaultDesc"; 390 } else { 391 table.columns[foundIndexes[k]].sortable = "defaultDescPrepend"; 392 } 393 } 394 } 395 } 396 } else { 397 table.displayStart = 0; 398 } 399 } 400 table.loadSettings({ 401 "pageSize": table.pageLength, 402 "displayStart": table.displayStart 403 }); 404 table.render(); 405 406 // Update the table history session variable to ensure that we remember what page the user was viewing when 407 // they last looked at the same table (search and browse results). 408 table.oTable.on('draw.dt', function() { 409 if ($.address.value() !== "/") { 410 var jsonObj; 411 if (window.sessionStorage.getItem("table-history")) { 412 jsonObj = JSON.parse(window.sessionStorage.getItem("table-history")); 413 } else { 414 jsonObj = {}; 415 } 416 jsonObj[window.location.pathname + $.address.value()] = { 417 displayStart: table.oTable.fnPagingInfo().iStart, 418 sortFields: table.sortFields, 419 sortDirections: table.sortDirections 420 }; 421 window.sessionStorage.setItem("table-history", JSON.stringify(jsonObj)); 422 } 423 }); 424 $("select[name=table_1_length]").change(function() { 425 $.jStorage.set("results-per-page", table.oTable.fnPagingInfo().iLength); 426 }); 427} 428 429//Other rendition functions for DALTables
430function purchaseLegislation(recordObj) { 431 var j = new Array(); 432 var list = new Array(); 433 var count = 0; 434 var expression = 'VersionSeriesId="' + recordObj['version.series.id'].__value__ + '"'; 435 $.ajax({ 436 type : "GET", 437 url : "/projectdata", 438 dataType : "json", 439 data : { 440 ds : "OQPC-LegHistoryAssociatedDataSource", 441 expression : expression 442 } 443 }).done(function(data) 444 { 445 if(data.data) 446 { 447 count = data.data.length; 448 for (var i = 0; i < count; i++) 449 { 450 j.push(data.data[i].__value__.__children__); 451 j.push(window.location.origin + createUrl(data.data[i].__value__, null, false, null, "pdf")); 452 list.push(j); 453 j = []; 454 } 455 } 456 var origUrl = window.location.origin + createUrl(recordObj, null, false, null, "pdf"); 457 var origName = recordObj['title'].__value__; 458 var titleExists = 0; 459 //Check each entry of the list to see if it's the original URL of the title 460 for (var i = 0; i < count; i++) 461 { 462 //If it does match, replace it with the original name rather than the //associateddoc name and move it to the front of the array 463 if(list[i][1] == origUrl) 464 { 465 list[i][0] = origName; 466 j = list[i]; 467 list.splice(i, 1); 468 list.unshift(j); 469 titleExists = 1; 470 } 471 } 472 //If it doesn't match, add the original title and URL to the front of the array 473 if(titleExists === 0) 474 { 475 j.push(origName); 476 j.push(origUrl); 477 list.unshift(j); 478 } 479 if(window.lit) 480 { 481 window.lit.purchasePrintedCopy(list); 482 } 483 return; 484 }); 485} 486 487function downloadOtherRendition(type, recordObj) { 488 var regExp = new RegExp("^.*" + type + "$"); 489 if(recordObj.otherRenditions) { 490 if (!$.isArray(recordObj.otherRenditions)) { 491 recordObj.otherRenditions = [recordObj.otherRenditions]; 492 } 493 for (var i = 0; i < recordObj.otherRenditions.length; i++) { 494 if(recordObj.otherRenditions[i]['mimetype'].match(regExp) !== null) { 495 window.open((createUrl(recordObj, null, false, null, type.toLowerCase())), '_blank'); 496 return; 497 } 498 } 499 } 500 var html = '<div class="alert alert-danger alert-dismissible" role="alert">' 501 + '<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' 502 + ' No ' + type + ' available for the selected title.' 503 + '</div>'; 504 $('#facet-btn-group').before(html); 505 $('#browse-results').before(html); 506} 507 508function downloadXML(recordObj) { 509 var regExp = new RegExp("^(act|sl)$"); 510 if(recordObj.type) { 511 if(recordObj.type['__value__'].match(regExp) !== null) { 512 window.open((createUrl(recordObj, null, false, null, "xml")), '_blank'); 513 return; 514 } 515 } 516 var html = '<div class="alert alert-danger alert-dismissible" role="alert">' 517 + '<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' 518 + ' No XML available for the selected title.' 519 + '</div>'; 520 $('#facet-btn-group').before(html); 521 $('#browse-results').before(html); 522} 523 524/** 525 * window.location.origin does not exist in IE8 526 */ 527if(!window.location.origin) 528{ 529 window.location.origin = window.location.protocol + "//" + 530 window.location.hostname + 531 (window.location.port ? ':' + window.location.port: ''); 532} 533 534function htmlEncode(value){ 535 //create a in-memory div, set it's inner text(which jQuery automatically encodes) 536 //then grab the encoded contents back out. The div never exists on the page. 537 return $('<div/>').text(value).html(); 538} 539 540function htmlDecode(value){ 541 return $('<div/>').html(value).text(); 542} 543 544function logout() { 545 $.ajax({ 546 type: "POST", 547 url: '/admin/doAjaxLogout', 548 success: function() 549 { 550 $.removeCookie('logged-on', { path: '/' }) 551 window.location.reload(); 552 } 553 }); 554} 555 556/*** END UTILS ********************************************/ 557 558/*** EVENT LISTENERS **************************************/ 559$(document).on('keydown', function(e) { 560 if (e.key === 'Escape') { 561 const $tocContainer = $('#toc-col'); 562 if ($tocContainer[0].contains(document.activeElement)) { 563 e.preventDefault(); 564 $('#legBtnGroup a').eq(0).trigger("focus"); 565 } 566 } 567}); 568/*** END EVENT LISTENERS **************************************/ 569 570/** 571 * This file contains a random language scroller. It updates 572 * the text of the other languages link every 5 seconds with a 573 * new random language supported by the www.qld.gov.au/languages 574 * 575 * (based on ideas from http://www.communityservices.qld.gov.au/scripts/languages.js) 576 * 577 * @requires jquery 578 */ 579if (typeof jQuery != 'undefined') { /* Start if jQuery exists */ 580(function($) { /* start closure */ 581 582 var languages = [ 583 '<span lang=\"ar\">Ø§ÙØ¹Ø±Ø¨ÙØ©</span>', 584 '<span lang=\"el\">Îλληνικά</span>', 585 '<span lang=\"pl\">Polski</span>', 586 '<span lang=\"bs\">Bosanksi</span>', 587 '<span lang=\"id\">Bahasa Indonesia</span>', 588 '<span lang=\"ru\">Ð ÑÑÑкий</span>', 589 '<span lang=\"zh\">䏿</span>', 590 '<span lang=\"it\">Italiano</span>', 591 '<span lang=\"sr\">ÑÑпÑки</span>' , 592 '<span lang=\"hr\">Hrvatski</span>', 593 '<span lang=\"ja\">æ¥æ¬èª</span>', 594 '<span lang=\"es\">Español</span>', 595 '<span lang=\"fr\">Français</span>', 596 '<span lang=\"ko\">íêµì´</span>', 597 '<span lang=\"tl\">Tagalog</span>', 598 '<span lang=\"de\">
598Deutsch</span>', 599 '<span lang=\"fa\">ÙØ§Ø±Ø³Û</span>', 600 '<span lang=\"vi\">Tiếng Viá»t</span>' 601 ]; 602 603 var doctype = document.doctype ? document.doctype.publicId : document.firstChild.data; 604 var XHTML; 605 if(doctype) 606 { 607 XHTML = doctype.indexOf('XHTML') > 0; 608 } 609 610 var updateLanguage = function () { 611 $('#languages a').empty().append('Other languages (' + languages[Math.floor(Math.random()*languages.length)]+')'); 612 //$('#languages a').empty().append(languages[Math.floor(Math.random()*languages.length)]+' (Other languages)'); 613 // copy @lang to @xml:lang for XHTML 614 if (XHTML) { 615 $('#languages span').attr('xml:lang', $('#languages span').attr('lang')); 616 } 617 }; 618 619 updateLanguage(); 620 window.setInterval(updateLanguage, 5000); 621 622 623})(jQuery); /* end closure */ 624} /* end if jQuery exists */ 625 626/** END LANGUAGE ********************************/ 627 628/** 629 * Website resize functions and variables 630 */ 631 632var g_minF = 100; 633var g_maxF = 200; 634 635$(function() { 636 $("#resizeUp").click(function() 637 { 638 $("#resizeDown").prop("disabled", false); 639 //var fs = $("html").css("font-size"); 640 //fs = parseInt(fs.replace("px","")); 641 var fs = $.jStorage.get("currFontSize") + 10; 642 $.jStorage.set("currFontSize", fs); 643 if(fs >= g_maxF) { 644 $("#resizeUp").blur(); 645 $("#resizeUp").prop("disabled", true); 646 } 647 fs = fs + "%"; 648 $("#main").css("font-size", fs); 649 }); 650 651 function resizeZero() { 652 $.jStorage.set("currFontSize", g_minF); 653 $("html").css("font-size", g_minF + "%"); 654 } 655 656 $("#resizeDown").click(function() 657 { 658 $("#resizeUp").prop("disabled", false); 659 //var fs = $("html").css("font-size"); 660 //fs = parseInt(fs.replace("px","")); 661 var fs = $.jStorage.get("currFontSize") - 10; 662 $.jStorage.set("currFontSize", fs); 663 if(fs <= g_minF) { 664 $("#resizeDown").blur(); 665 $("#resizeDown").prop("disabled", true); 666 } 667 fs = fs + "%"; 668 $("#main").css("font-size", fs); 669 670 }); 671}); 672 673/** END RESIZE ************************************************/ 674 675/** 676 * Function for the 'Skip to main content' button 677 */ 678 679$(function(){ 680 $("#skipStart").click(function(){ 681 $('html, body').animate({ 682 scrollTop: $("#main").offset().top 683 }, 200); 684 $("#skipEnd").focus(); 685 }); 686}); 687 688/** END SKIP **************************************************/ 689 690/*! sprintf.js | Copyright (c) 2007-2013 Alexandru Marasteanu <hello at alexei dot ro> | 3 clause BSD license */ 691 692(function(ctx) { 693 var sprintf = function() { 694 if (!sprintf.cache.hasOwnProperty(arguments[0])) { 695 sprintf.cache[arguments[0]] = sprintf.parse(arguments[0]); 696 } 697 return sprintf.format.call(null, sprintf.cache[arguments[0]], arguments); 698 }; 699 700 sprintf.format = function(parse_tree, argv) { 701 var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length; 702 for (i = 0; i < tree_length; i++) { 703 node_type = get_type(parse_tree[i]); 704 if (node_type === 'string') { 705 output.push(parse_tree[i]); 706 } 707 else if (node_type === 'array') { 708 match = parse_tree[i]; // convenience purposes only 709 if (match[2]) { // keyword argument 710 arg = argv[cursor]; 711 for (k = 0; k < match[2].length; k++) { 712 if (!arg.hasOwnProperty(match[2][k])) { 713 throw(sprintf('[sprintf] property "%s" does not exist', match[2][k])); 714 } 715 arg = arg[match[2][k]]; 716 } 717 } 718 else if (match[1]) { // positional argument (explicit) 719 arg = argv[match[1]]; 720 } 721 else { // positional argument (implicit) 722 arg = argv[cursor++]; 723 } 724 725 if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) { 726 throw(sprintf('[sprintf] expecting number but found %s', get_type(arg))); 727 } 728 switch (match[8]) { 729 case 'b': arg = arg.toString(2); break; 730 case 'c': arg = String.fromCharCode(arg); break; 731 case 'd': arg = parseInt(arg, 10); break; 732 case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; 733 case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; 734 case 'o': arg = arg.toString(8); break; 735 case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; 736 case 'u': arg = arg >>> 0; break; 737 case 'x': arg = arg.toString(16); break; 738 case 'X': arg = arg.toString(16).toUpperCase(); break; 739 } 740 arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); 741 pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' '; 742 pad_length = match[6] - String(arg).length; 743 pad = match[6] ? str_repeat(pad_character, pad_length) : ''; 744 output.push(match[5] ? arg + pad : pad + arg); 745 } 746 } 747 return output.join(''); 748 }; 749 750 sprintf.cache = {}; 751 752 sprintf.parse = function(fmt) { 753 var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; 754 while (_fmt) { 755 if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { 756 parse_tree.push(match[0]); 757 } 758 else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { 759 parse_tree.push('%'); 760 } 761 else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) { 762 if (match[2]) { 763 arg_names |= 1; 764 var field_list = [], replacement_field = match[2], field_match = []; 765 if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { 766 field_list.push(field_match[1]); 767 while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { 768 if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { 769 field_list.push(field_match[1]); 770 } 771 else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { 772 field_list.push(field_match[1]); 773 } 774 else { 775 throw('[sprintf] huh?'); 776 } 777 } 778 } 779 else { 780 throw('[sprintf] huh?'); 781 } 782 match[2] = field_list; 783 } 784 else { 785 arg_names |= 2; 786 } 787 if (arg_names === 3) { 788 throw('[sprintf] mixing positional and named placeholders is not (yet) supported'); 789 } 790 parse_tree.push(match); 791 } 792 else { 793 throw('[sprintf] huh?'); 794 } 795 _fmt = _fmt.substring(match[0].length); 796 } 797 return parse_tree; 798 }; 799 800 var vsprintf = function(fmt, argv, _argv) { 801 _argv = argv.slice(0); 802 _argv.splice(0, 0, fmt); 803 return sprintf.apply(null, _argv); 804 }; 805 806 /** 807 * helpers 808 */ 809 function get_type(variable) { 810 return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); 811 } 812 813 function str_repeat(input, multiplier) { 814 for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */} 815 return output.join(''); 816 } 817 818 /** 819 * export to either browser or node.js 820 */ 821 ctx.sprintf = sprintf; 822 ctx.vsprintf = vsprintf; 823})(typeof exports != "undefined" ? exports : window); 824 825/**** sprintf ********************************************************************************************/ 826 827 828/**** jquery cookie library ***/ 829/*! 830 * jQuery Cookie Plugin v1.4.1 831 * https://github.com/carhartl/jquery-cookie 832 * 833 * Copyright 2013 Klaus Hartl 834 * Released under the MIT license 835 */ 836(function (factory) { 837 if (typeof define === 'function' && define.amd) { 838 // AMD 839 define(['jquery'], factory); 840 } else if (typeof exports === 'object') { 841 // CommonJS 842 factory(require('jquery')); 843 } else { 844 // Browser globals 845 factory(jQuery); 846 } 847}(function ($) { 848 849 var pluses = /\+/g; 850 851 function encode(s) { 852 return config.raw ? s : encodeURIComponent(s); 853 } 854 855 function decode(s) { 856 return config.raw ? s : decodeURIComponent(s); 857 } 858 859 function stringifyCookieValue(value) { 860 return encode(config.json ? JSON.stringify(value) : String(value)); 861 } 862 863 function parseCookieValue(s) { 864 if (s.indexOf('"') === 0) { 865 // This is a quoted cookie as according to RFC2068, unescape... 866 s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); 867 } 868 869 try { 870 // Replace server-side written pluses with spaces. 871 // If we can't decode the cookie, ignore it, it's unusable. 872 // If we can't parse the cookie, ignore it, it's unusable. 873 s = decodeURIComponent(s.replace(pluses, ' ')); 874 return config.json ? JSON.parse(s) : s; 875 } catch(e) {} 876 } 877 878 function read(s, converter) { 879 var value = config.raw ? s : parseCookieValue(s); 880 return $.isFunction(converter) ? converter(value) : value; 881 } 882 883 var config = $.cookie = function (key, value, options) { 884 885 // Write 886 887 if (value !== undefined && !$.isFunction(value)) { 888 options = $.extend({}, config.defaults, options); 889 890 if (typeof options.expires === 'number') { 891 var days = options.expires, t = options.expires = new Date(); 892 t.setTime(+t + days * 864e+5); 893 } 894 895 return (document.cookie = [ 896 encode(key), '=', stringifyCookieValue(value), 897 options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE 898 options.path ? '; path=' + options.path : '', 899 options.domain ? '; domain=' + options.domain : '', 900 options.secure ? '; secure' : '' 901 ].join('')); 902 } 903 904 // Read 905 906 var result = key ? undefined : {}; 907 908 // To prevent the for loop in the first place assign an empty array 909 // in case there are no cookies at all. Also prevents odd result when 910 // calling $.cookie(). 911 var cookies = document.cookie ? document.cookie.split('; ') : []; 912 913 for (var i = 0, l = cookies.length; i < l; i++) { 914 var parts = cookies[i].split('='); 915 var name = decode(parts.shift()); 916 var cookie = parts.join('='); 917 918 if (key && key === name) { 919 // If second argument (value) is a function it's a converter... 920 result = read(cookie, value); 921 break; 922 } 923 924 // Prevent storing a cookie that we couldn't decode. 925 if (!key && (cookie = read(cookie)) !== undefined) { 926 result[name] = cookie; 927 } 928 } 929 930 return result; 931 }; 932 933 config.defaults = {}; 934 935 $.removeCookie = function (key, options) { 936 if ($.cookie(key) === undefined) { 937 return false;
938 } 939 940 // Must not alter options, thus extending a fresh object... 941 $.cookie(key, '', $.extend({}, options, { expires: -1 })); 942 return !$.cookie(key); 943 }; 944 945})); 946 947/*************************************************************************************/ 948 949/*! 950 * jQuery BBQ: Back Button & Query Library - v1.2.1 - 2/17/2010 951 * http://benalman.com/projects/jquery-bbq-plugin/ 952 * 953 * Copyright (c) 2010 "Cowboy" Ben Alman 954 * Dual licensed under the MIT and GPL licenses. 955 * http://benalman.com/about/license/ 956 */ 957 958// Script: jQuery BBQ: Back Button & Query Library 959// 960// *Version: 1.2.1, Last updated: 2/17/2010* 961// 962// Project Home - http://benalman.com/projects/jquery-bbq-plugin/ 963// GitHub - http://github.com/cowboy/jquery-bbq/ 964// Source - http://github.com/cowboy/jquery-bbq/raw/master/jquery.ba-bbq.js 965// (Minified) - http://github.com/cowboy/jquery-bbq/raw/master/jquery.ba-bbq.min.js (4.0kb) 966// 967// About: License 968// 969// Copyright (c) 2010 "Cowboy" Ben Alman, 970// Dual licensed under the MIT and GPL licenses. 971// http://benalman.com/about/license/ 972// 973// About: Examples 974// 975// These working examples, complete with fully commented code, illustrate a few 976// ways in which this plugin can be used. 977// 978// Basic AJAX - http://benalman.com/code/projects/jquery-bbq/examples/fragment-basic/ 979// Advanced AJAX - http://benalman.com/code/projects/jquery-bbq/examples/fragment-advanced/ 980// jQuery UI Tabs - http://benalman.com/code/projects/jquery-bbq/examples/fragment-jquery-ui-tabs/ 981// Deparam - http://benalman.com/code/projects/jquery-bbq/examples/deparam/ 982// 983// About: Support and Testing 984// 985// Information about what version or versions of jQuery this plugin has been 986// tested with, what browsers it has been tested in, and where the unit tests 987// reside (so you can test it yourself). 988// 989// jQuery Versions - 1.3.2, 1.4.1, 1.4.2 990// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.7, Safari 3-4, 991// Chrome 4-5, Opera 9.6-10.1. 992// Unit Tests - http://benalman.com/code/projects/jquery-bbq/unit/ 993// 994// About: Release History 995// 996// 1.2.1 - (2/17/2010) Actually fixed the stale window.location Safari bug from 997// <jQuery hashchange event> in BBQ, which was the main reason for the 998// previous release! 999// 1.2 - (2/16/2010) Integrated <jQuery hashchange event> v1.2, which fixes a 1000// Safari bug, the event can now be bound before DOM ready, and IE6/7 1001// page should no longer scroll when the event is first bound. Also 1002// added the <jQuery.param.fragment.noEscape> method, and reworked the 1003// <hashchange event (BBQ)> internal "add" method to be compatible with 1004// changes made to the jQuery 1.4.2 special events API. 1005// 1.1.1 - (1/22/2010) Integrated <jQuery hashchange event> v1.1, which fixes an 1006// obscure IE8 EmulateIE7 meta tag compatibility mode bug. 1007// 1.1 - (1/9/2010) Broke out the jQuery BBQ event.special <hashchange event> 1008// functionality into a separate plugin for users who want just the 1009// basic event & back button support, without all the extra awesomeness 1010// that BBQ provides. This plugin will be included as part of jQuery BBQ, 1011// but also be available separately. See <jQuery hashchange event> 1012// plugin for more information. Also added the <jQuery.bbq.removeState> 1013// method and added additional <jQuery.deparam> examples. 1014// 1.0.3 - (12/2/2009) Fixed an issue in IE 6 where location.search and 1015// location.hash would report incorrectly if the hash contained the ? 1016// character. Also <jQuery.param.querystring> and <jQuery.param.fragment> 1017// will no longer parse params out of a URL that doesn't contain ? or #, 1018// respectively. 1019// 1.0.2 - (10/10/2009) Fixed an issue in IE 6/7 where the hidden IFRAME caused 1020// a "This page contains both secure and nonsecure items." warning when 1021// used on an https:// page. 1022// 1.0.1 - (10/7/2009) Fixed an issue in IE 8. Since both "IE7" and "IE8 1023// Compatibility View" modes erroneously report that the browser 1024// supports the native window.onhashchange event, a slightly more 1025// robust test needed to be added. 1026// 1.0 - (10/2/2009) Initial release 1027 1028jQuery.browser = {}; 1029(function () { 1030 jQuery.browser.msie = false;
1031 jQuery.browser.version = 0; 1032 if (navigator.userAgent.match(/MSIE ([0-9]+)\./)) { 1033 jQuery.browser.msie = true; 1034 jQuery.browser.version = RegExp.$1; 1035 } 1036})(); 1037 1038(function($,window){ 1039 '$:nomunge'; // Used by YUI compressor. 1040 1041 // Some convenient shortcuts. 1042 var undefined, 1043 aps = Array.prototype.slice, 1044 decode = decodeURIComponent, 1045 1046 // Method / object references. 1047 jq_param = $.param, 1048 jq_param_fragment, 1049 jq_deparam, 1050 jq_deparam_fragment, 1051 jq_bbq = $.bbq = $.bbq || {}, 1052 jq_bbq_pushState, 1053 jq_bbq_getState, 1054 jq_elemUrlAttr, 1055 jq_event_special = $.event.special, 1056 1057 // Reused strings. 1058 str_hashchange = 'hashchange', 1059 str_querystring = 'querystring', 1060 str_fragment = 'fragment', 1061 str_elemUrlAttr = 'elemUrlAttr', 1062 str_location = 'location', 1063 str_href = 'href', 1064 str_src = 'src', 1065 1066 // Reused RegExp. 1067 re_trim_querystring = /^.*\?|#.*$/g, 1068 re_trim_fragment = /^.*\#/, 1069 re_no_escape, 1070 1071 // Used by jQuery.elemUrlAttr. 1072 elemUrlAttr_cache = {}; 1073 1074 // A few commonly used bits, broken out to help reduce minified file size. 1075 1076 function is_string( arg ) { 1077 return typeof arg === 'string'; 1078 }; 1079 1080 // Why write the same function twice? Let's curry! Mmmm, curry.. 1081 1082 function curry( func ) { 1083 var args = aps.call( arguments, 1 ); 1084 1085 return function() { 1086 return func.apply( this, args.concat( aps.call( arguments ) ) ); 1087 }; 1088 }; 1089 1090 // Get location.hash (or what you'd expect location.hash to be) sans any 1091 // leading #. Thanks for making this necessary, Firefox! 1092 function get_fragment( url ) { 1093 return url.replace( /^[^#]*#?(.*)$/, '$1' ); 1094 }; 1095 1096 // Get location.search (or what you'd expect location.search to be) sans any 1097 // leading #. Thanks for making this necessary, IE6! 1098 function get_querystring( url ) { 1099 return url.replace( /(?:^[^?#]*\?([^#]*).*$)?.*/, '$1' ); 1100 }; 1101 1102 // Section: Param (to string) 1103 // 1104 // Method: jQuery.param.querystring 1105 // 1106 // Retrieve the query string from a URL or if no arguments are passed, the 1107 // current window.location. 1108 // 1109 // Usage: 1110 // 1111 // > jQuery.param.querystring( [ url ] ); 1112 // 1113 // Arguments: 1114 // 1115 // url - (String) A URL containing query string params to be parsed. If url 1116 // is not passed, the current window.location is used. 1117 // 1118 // Returns: 1119 // 1120 // (String) The parsed query string, with any leading "?" removed. 1121 // 1122 1123 // Method: jQuery.param.querystring (build url) 1124 // 1125 // Merge a URL, with or without pre-existing query string params, plus any 1126 // object, params string or URL containing query string params into a new URL. 1127 // 1128 // Usage: 1129 // 1130 // > jQuery.param.querystring( url, params [, merge_mode ] ); 1131 // 1132 // Arguments: 1133 // 1134 // url - (String) A valid URL for params to be merged into. This URL may 1135 // contain a query string and/or fragment (hash). 1136 // params - (String) A params string or URL containing query string params to 1137 // be merged into url. 1138 // params - (Object) A params object to be merged into url. 1139 // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not 1140 // specified, and is as-follows: 1141 // 1142 // * 0: params in the params argument will override any query string 1143 // params in url. 1144 // * 1: any query string params in url will override params in the params 1145 // argument. 1146 // * 2: params argument will completely replace any query string in url. 1147 // 1148 // Returns: 1149 // 1150 // (String) Either a params string with urlencoded data or a URL with a 1151 // urlencoded query string in the format 'a=b&c=d&e=f'. 1152 1153 // Method: jQuery.param.fragment 1154 // 1155 // Retrieve the fragment (hash) from a URL or if no arguments are passed, the 1156 // current window.location. 1157 // 1158 // Usage: 1159 // 1160 // > jQuery.param.fragment( [ url ] ); 1161 // 1162 // Arguments: 1163 // 1164 // url - (String) A URL containing fragment (hash) params to be parsed. If 1165 // url is not passed, the current window.location is used. 1166 // 1167 // Returns: 1168 // 1169 // (String) The parsed fragment (hash) string, with any leading "#" removed. 1170 1171 // Method: jQuery.param.fragment (build url) 1172 // 1173 // Merge a URL, with or without pre-existing fragment (hash) params, plus any 1174 // object, params string or URL containing fragment (hash) params into a new 1175 // URL. 1176 // 1177 // Usage: 1178 // 1179 // > jQuery.param.fragment( url, params [, merge_mode ] ); 1180 // 1181 // Arguments: 1182 // 1183 // url - (String) A valid URL for params to be merged into. This URL may 1184 // contain a query string and/or fragment (hash). 1185 // params - (String) A params string or URL containing fragment (hash) params 1186 // to be merged into url. 1187 // params - (Object) A params object to be merged into url. 1188 // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not 1189 // specified, and is as-follows: 1190 // 1191 // * 0: params in the params argument will override any fragment (hash) 1192 // params in url. 1193 // * 1: any fragment (hash) params in url will override params in the 1194 // params argument. 1195 // * 2: params argument will completely replace any query string in url. 1196 // 1197 // Returns: 1198 // 1199 // (String) Either a params string with urlencoded data or a URL with a 1200 // urlencoded fragment (hash) in the format 'a=b&c=d&e=f'. 1201 1202 function jq_param_sub( is_fragment, get_func, url, params, merge_mode ) { 1203 var result, 1204 qs, 1205 matches, 1206 url_params, 1207 hash; 1208 1209 if ( params !== undefined ) { 1210 // Build URL by merging params into url string. 1211 1212 // matches[1] = url part that precedes params, not including trailing ?/# 1213 // matches[2] = params, not including leading ?/# 1214 // matches[3] = if in 'querystring' mode, hash including leading #, otherwise '' 1215 matches = url.match( is_fragment ? /^([^#]*)\#?(.*)$/ : /^([^#?]*)\??([^#]*)(#?.*)/ ); 1216 1217 // Get the hash if in 'querystring' mode, and it exists. 1218 hash = matches[3] || ''; 1219 1220 if ( merge_mode === 2 && is_string( params ) ) { 1221 // If merge_mode is 2 and params is a string, merge the fragment / query 1222 // string into the URL wholesale, without converting it into an object. 1223 qs = params.replace( is_fragment ? re_trim_fragment : re_trim_querystring, '' ); 1224 1225 } else { 1226 // Convert relevant params in url to object. 1227 url_params = jq_deparam( matches[2] ); 1228 1229 params = is_string( params ) 1230 1231 // Convert passed params string into object. 1232 ? jq_deparam[ is_fragment ? str_fragment : str_querystring ]( params ) 1233 1234 // Passed params object. 1235 : params; 1236 1237 qs = merge_mode === 2 ? params // passed params replace url params 1238 : merge_mode === 1 ? $.extend( {}, params, url_params ) // url params override passed params 1239 : $.extend( {}, url_params, params ); // passed params override url params 1240 1241 // Convert params object to a string. 1242 qs = jq_param( qs ); 1243
1244 // Unescape characters specified via $.param.noEscape. Since only hash- 1245 // history users have requested this feature, it's only enabled for 1246 // fragment-related params strings. 1247 if ( is_fragment ) { 1248 qs = qs.replace( re_no_escape, decode ); 1249 } 1250 } 1251 1252 // Build URL from the base url, querystring and hash. In 'querystring' 1253 // mode, ? is only added if a query string exists. In 'fragment' mode, # 1254 // is always added. 1255 result = matches[1] + ( is_fragment ? '#' : qs || !matches[1] ? '?' : '' ) + qs + hash; 1256 1257 } else { 1258 // If URL was passed in, parse params from URL string, otherwise parse 1259 // params from window.location. 1260 result = get_func( url !== undefined ? url : window[ str_location ][ str_href ] ); 1261 } 1262 1263 return result; 1264 }; 1265 1266 jq_param[ str_querystring ] = curry( jq_param_sub, 0, get_querystring ); 1267 jq_param[ str_fragment ] = jq_param_fragment = curry( jq_param_sub, 1, get_fragment ); 1268 1269 // Method: jQuery.param.fragment.noEscape 1270 // 1271 // Specify characters that will be left unescaped when fragments are created 1272 // or merged using <jQuery.param.fragment>, or when the fragment is modified 1273 // using <jQuery.bbq.pushState>. This option only applies to serialized data 1274 // object fragments, and not set-as-string fragments. Does not affect the 1275 // query string. Defaults to ",/" (comma, forward slash). 1276 // 1277 // Note that this is considered a purely aesthetic option, and will help to 1278 // create URLs that "look pretty" in the address bar or bookmarks, without 1279 // affecting functionality in any way. That being said, be careful to not 1280 // unescape characters that are used as delimiters or serve a special 1281 // purpose, such as the "#?&=+" (octothorpe, question mark, ampersand, 1282 // equals, plus) characters. 1283 // 1284 // Usage: 1285 // 1286 // > jQuery.param.fragment.noEscape( [ chars ] ); 1287 // 1288 // Arguments: 1289 // 1290 // chars - (String) The characters to not escape in the fragment. If 1291 // unspecified, defaults to empty string (escape all characters). 1292 // 1293 // Returns: 1294 // 1295 // Nothing. 1296 1297 jq_param_fragment.noEscape = function( chars ) { 1298 chars = chars || ''; 1299 var arr = $.map( chars.split(''), encodeURIComponent ); 1300 re_no_escape = new RegExp( arr.join('|'), 'g' ); 1301 }; 1302 1303 // A sensible default. These are the characters people seem to complain about 1304 // "uglifying up the URL" the most. 1305 jq_param_fragment.noEscape( ',/' ); 1306 1307 // Section: Deparam (from string) 1308 // 1309 // Method: jQuery.deparam 1310 // 1311 // Deserialize a params string into an object, optionally coercing numbers, 1312 // booleans, null and undefined values; this method is the counterpart to the 1313 // internal jQuery.param method. 1314 // 1315 // Usage: 1316 // 1317 // > jQuery.deparam( params [, coerce ] ); 1318 // 1319 // Arguments: 1320 // 1321 // params - (String) A params string to be parsed. 1322 // coerce - (Boolean) If true, coerces any numbers or true, false, null, and 1323 // undefined to their actual value. Defaults to false if omitted. 1324 // 1325 // Returns: 1326 // 1327 // (Object) An object representing the deserialized params string. 1328 1329 $.deparam = jq_deparam = function( params, coerce ) { 1330 var obj = {}, 1331 coerce_types = { 'true': !0, 'false': !1, 'null': null }; 1332 1333 // Iterate over all name=value pairs. 1334 $.each( params.replace( /\+/g, ' ' ).split( '&' ), function(j,v){ 1335 var param = v.split( '=' ), 1336 key = decode( param[0] ), 1337 val, 1338 cur = obj, 1339 i = 0, 1340 1341 // If key is more complex than 'foo', like 'a[]' or 'a[b][c]', split it 1342 // into its component parts. 1343 keys = key.split( '][' ), 1344 keys_last = keys.length - 1; 1345 1346 // If the first keys part contains [ and the last ends with ], then [] 1347 // are correctly balanced. 1348 if ( /\[/.test( keys[0] ) && /\]$/.test( keys[ keys_last ] ) ) { 1349 // Remove the trailing ] from the last keys part. 1350 keys[ keys_last ] = keys[ keys_last ].replace( /\]$/, '' ); 1351 1352 // Split first keys part into two parts on the [ and add them back onto 1353 // the beginning of the keys array.
1354 keys = keys.shift().split('[').concat( keys ); 1355 1356 keys_last = keys.length - 1; 1357 } else { 1358 // Basic 'foo' style key. 1359 keys_last = 0; 1360 } 1361 1362 // Are we dealing with a name=value pair, or just a name? 1363 if ( param.length === 2 ) { 1364 val = decode( param[1] ); 1365 1366 // Coerce values. 1367 if ( coerce ) { 1368 val = val && !isNaN(val) ? +val // number 1369 : val === 'undefined' ? undefined // undefined 1370 : coerce_types[val] !== undefined ? coerce_types[val] // true, false, null 1371 : val; // string 1372 } 1373 1374 if ( keys_last ) { 1375 // Complex key, build deep object structure based on a few rules: 1376 // * The 'cur' pointer starts at the object top-level. 1377 // * [] = array push (n is set to array length), [n] = array if n is 1378 // numeric, otherwise object. 1379 // * If at the last keys part, set the value. 1380 // * For each keys part, if the current level is undefined create an 1381 // object or array based on the type of the next keys part. 1382 // * Move the 'cur' pointer to the next level. 1383 // * Rinse & repeat. 1384 for ( ; i <= keys_last; i++ ) { 1385 key = keys[i] === '' ? cur.length : keys[i]; 1386 cur = cur[key] = i < keys_last 1387 ? cur[key] || ( keys[i+1] && isNaN( keys[i+1] ) ? {} : [] ) 1388 : val; 1389 } 1390 1391 } else { 1392 // Simple key, even simpler rules, since only scalars and shallow 1393 // arrays are allowed. 1394 1395 if ( $.isArray( obj[key] ) ) { 1396 // val is already an array, so push on the next value. 1397 obj[key].push( val ); 1398 1399 } else if ( obj[key] !== undefined ) { 1400 // val isn't an array, but since a second value has been specified, 1401 // convert val into an array. 1402 obj[key] = [ obj[key], val ]; 1403 1404 } else { 1405 // val is a scalar. 1406 obj[key] = val; 1407 } 1408 } 1409 1410 } else if ( key ) { 1411 // No value was defined, so set something meaningful. 1412 obj[key] = coerce 1413 ? undefined 1414 : ''; 1415 } 1416 }); 1417 1418 return obj; 1419 }; 1420 1421 // Method: jQuery.deparam.querystring 1422 // 1423 // Parse the query string from a URL or the current window.location, 1424 // deserializing it into an object, optionally coercing numbers, booleans, 1425 // null and undefined values. 1426 // 1427 // Usage: 1428 // 1429 // > jQuery.deparam.querystring( [ url ] [, coerce ] ); 1430 // 1431 // Arguments: 1432 // 1433 // url - (String) An optional params string or URL containing query string 1434 // params to be parsed. If url is omitted, the current window.location 1435 // is used. 1436 // coerce - (Boolean) If true, coerces any numbers or true, false, null, and 1437 // undefined to their actual value. Defaults to false if omitted. 1438 // 1439 // Returns: 1440 // 1441 // (Object) An object representing the deserialized params string. 1442 1443 // Method: jQuery.deparam.fragment 1444 // 1445 // Parse the fragment (hash) from a URL or the current window.location, 1446 // deserializing it into an object, optionally coercing numbers, booleans, 1447 // null and undefined values. 1448 // 1449 // Usage: 1450 // 1451 // > jQuery.deparam.fragment( [ url ] [, coerce ] ); 1452 // 1453 // Arguments: 1454 // 1455 // url - (String) An optional params string or URL containing fragment (hash) 1456 // params to be parsed. If url is omitted, the current window.location 1457 // is used. 1458 // coerce - (Boolean) If true, coerces any numbers or true, false, null, and 1459 // undefined to their actual value. Defaults to false if omitted. 1460 // 1461 // Returns: 1462 // 1463 // (Object) An object representing the deserialized params string. 1464 1465 function jq_deparam_sub( is_fragment, url_or_params, coerce ) { 1466 if ( url_or_params === undefined || typeof url_or_params === 'boolean' ) { 1467 // url_or_params not specified. 1468 coerce = url_or_params; 1469 url_or_params = jq_param[ is_fragment ? str_fragment : str_querystring ](); 1470 } else { 1471 url_or_params = is_string( url_or_params ) 1472 ? url_or_params.replace( is_fragment ? re_trim_fragment : re_trim_querystring, '' ) 1473 : url_or_params; 1474 } 1475 1476 return jq_deparam( url_or_params, coerce ); 1477 }; 1478 1479 jq_deparam[ str_querystring ] = curry( jq_deparam_sub, 0 ); 1480 jq_deparam[ str_fragment ] = jq_deparam_fragment = curry( jq_deparam_sub, 1 ); 1481 1482 // Section: Element manipulation 1483 // 1484 // Method: jQuery.elemUrlAttr 1485 // 1486 // Get the internal "Default URL attribute per tag" list, or augment the list 1487 // with additional tag-attribute pairs, in case the defaults are insufficient. 1488 // 1489 // In the <jQuery.fn.querystring> and <jQuery.fn.fragment> methods, this list 1490 // is used to determine which attribute contains the URL to be modified, if 1491 // an "attr" param is not specified. 1492 // 1493 // Default Tag-Attribute List: 1494 // 1495 // a - href 1496 // base - href 1497 // iframe - src 1498 // img - src 1499 // input - src 1500 // form - action 1501 // link - href 1502 // script - src 1503 // 1504 // Usage: 1505 // 1506 // > jQuery.elemUrlAttr( [ tag_attr ] ); 1507 // 1508 // Arguments: 1509 //
1510 // tag_attr - (Object) An object containing a list of tag names and their 1511 // associated default attribute names in the format { tag: 'attr', ... } to 1512 // be merged into the internal tag-attribute list. 1513 // 1514 // Returns: 1515 // 1516 // (Object) An object containing all stored tag-attribute values. 1517 1518 // Only define function and set defaults if function doesn't already exist, as 1519 // the urlInternal plugin will provide this method as well. 1520 $[ str_elemUrlAttr ] || ($[ str_elemUrlAttr ] = function( obj ) { 1521 return $.extend( elemUrlAttr_cache, obj ); 1522 })({ 1523 a: str_href, 1524 base: str_href, 1525 iframe: str_src, 1526 img: str_src, 1527 input: str_src, 1528 form: 'action', 1529 link: str_href, 1530 script: str_src 1531 }); 1532 1533 jq_elemUrlAttr = $[ str_elemUrlAttr ]; 1534 1535 // Method: jQuery.fn.querystring 1536 // 1537 // Update URL attribute in one or more elements, merging the current URL (with 1538 // or without pre-existing query string params) plus any params object or 1539 // string into a new URL, which is then set into that attribute. Like 1540 // <jQuery.param.querystring (build url)>, but for all elements in a jQuery 1541 // collection. 1542 // 1543 // Usage: 1544 // 1545 // > jQuery('selector').querystring( [ attr, ] params [, merge_mode ] ); 1546 // 1547 // Arguments: 1548 // 1549 // attr - (String) Optional name of an attribute that will contain a URL to 1550 // merge params or url into. See <jQuery.elemUrlAttr> for a list of default 1551 // attributes. 1552 // params - (Object) A params object to be merged into the URL attribute. 1553 // params - (String) A URL containing query string params, or params string 1554 // to be merged into the URL attribute. 1555 // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not 1556 // specified, and is as-follows: 1557 // 1558 // * 0: params in the params argument will override any params in attr URL. 1559 // * 1: any params in attr URL will override params in the params argument. 1560 // * 2: params argument will completely replace any query string in attr 1561 // URL. 1562 // 1563 // Returns: 1564 // 1565 // (jQuery) The initial jQuery collection of elements, but with modified URL 1566 // attribute values. 1567 1568 // Method: jQuery.fn.fragment 1569 // 1570 // Update URL attribute in one or more elements, merging the current URL (with 1571 // or without pre-existing fragment/hash params) plus any params object or 1572 // string into a new URL, which is then set into that attribute. Like 1573 // <jQuery.param.fragment (build url)>, but for all elements in a jQuery 1574 // collection. 1575 // 1576 // Usage: 1577 // 1578 // > jQuery('selector').fragment( [ attr, ] params [, merge_mode ] ); 1579 // 1580 // Arguments: 1581 // 1582 // attr - (String) Optional name of an attribute that will contain a URL to 1583 // merge params into. See <jQuery.elemUrlAttr> for a list of default 1584 // attributes. 1585 // params - (Object) A params object to be merged into the URL attribute. 1586 // params - (String) A URL containing fragment (hash) params, or params 1587 // string to be merged into the URL attribute. 1588 // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not 1589 // specified, and is as-follows: 1590 // 1591 // * 0: params in the params argument will override any params in attr URL. 1592 // * 1: any params in attr URL will override params in the params argument. 1593 // * 2: params argument will completely replace any fragment (hash) in attr 1594 // URL. 1595 // 1596 // Returns: 1597 // 1598 // (jQuery) The initial jQuery collection of elements, but with modified URL 1599 // attribute values. 1600 1601 function jq_fn_sub( mode, force_attr, params, merge_mode ) { 1602 if ( !is_string( params ) && typeof params !== 'object' ) { 1603 // force_attr not specified. 1604 merge_mode = params; 1605 params = force_attr; 1606 force_attr = undefined; 1607 } 1608 1609 return this.each(function(){ 1610 var that = $(this), 1611 1612 // Get attribute specified, or default specified via $.elemUrlAttr. 1613 attr = force_attr || jq_elemUrlAttr()[ ( this.nodeName || '' ).toLowerCase() ] || '', 1614 1615 // Get URL value. 1616 url = attr && that.attr( attr ) || ''; 1617 1618 // Update attribute with new URL. 1619 that.attr( attr, jq_param[ mode ]( url, params, merge_mode ) ); 1620 }); 1621 1622 }; 1623 1624 $.fn[ str_querystring ] = curry( jq_fn_sub, str_querystring ); 1625 $.fn[ str_fragment ] = curry( jq_fn_sub, str_fragment ); 1626 1627 // Section: History, hashchange event 1628 // 1629 // Method: jQuery.bbq.pushState 1630 // 1631 // Adds a 'state' into the browser history at the current position, setting
1632 // location.hash and triggering any bound <hashchange event> callbacks 1633 // (provided the new state is different than the previous state). 1634 // 1635 // If no arguments are passed, an empty state is created, which is just a 1636 // shortcut for jQuery.bbq.pushState( {}, 2 ). 1637 // 1638 // Usage: 1639 // 1640 // > jQuery.bbq.pushState( [ params [, merge_mode ] ] ); 1641 // 1642 // Arguments: 1643 // 1644 // params - (String) A serialized params string or a hash string beginning 1645 // with # to merge into location.hash. 1646 // params - (Object) A params object to merge into location.hash. 1647 // merge_mode - (Number) Merge behavior defaults to 0 if merge_mode is not 1648 // specified (unless a hash string beginning with # is specified, in which 1649 // case merge behavior defaults to 2), and is as-follows: 1650 // 1651 // * 0: params in the params argument will override any params in the 1652 // current state. 1653 // * 1: any params in the current state will override params in the params 1654 // argument. 1655 // * 2: params argument will completely replace current state. 1656 // 1657 // Returns: 1658 // 1659 // Nothing. 1660 // 1661 // Additional Notes: 1662 // 1663 // * Setting an empty state may cause the browser to scroll. 1664 // * Unlike the fragment and querystring methods, if a hash string beginning 1665 // with # is specified as the params agrument, merge_mode defaults to 2. 1666 1667 jq_bbq.pushState = jq_bbq_pushState = function( params, merge_mode ) { 1668 if ( is_string( params ) && /^#/.test( params ) && merge_mode === undefined ) { 1669 // Params string begins with # and merge_mode not specified, so completely 1670 // overwrite window.location.hash. 1671 merge_mode = 2; 1672 } 1673 1674 var has_args = params !== undefined, 1675 // Merge params into window.location using $.param.fragment. 1676 url = jq_param_fragment( window[ str_location ][ str_href ], 1677 has_args ? params : {}, has_args ? merge_mode : 2 ); 1678 1679 // Set new window.location.href. If hash is empty, use just # to prevent 1680 // browser from reloading the page. Note that Safari 3 & Chrome barf on 1681 // location.hash = '#'. 1682 window[ str_location ][ str_href ] = url + ( /#/.test( url ) ? '' : '#' ); 1683 }; 1684 1685 // Method: jQuery.bbq.getState 1686 // 1687 // Retrieves the current 'state' from the browser history, parsing 1688 // location.hash for a specific key or returning an object containing the 1689 // entire state, optionally coercing numbers, booleans, null and undefined 1690 // values. 1691 // 1692 // Usage: 1693 // 1694 // > jQuery.bbq.getState( [ key ] [, coerce ] ); 1695 // 1696 // Arguments: 1697 // 1698 // key - (String) An optional state key for which to return a value. 1699 // coerce - (Boolean) If true, coerces any numbers or true, false, null, and 1700 // undefined to their actual value. Defaults to false. 1701 // 1702 // Returns: 1703 // 1704 // (Anything) If key is passed, returns the value corresponding with that key 1705 // in the location.hash 'state', or undefined. If not, an object 1706 // representing the entire 'state' is returned. 1707 1708 jq_bbq.getState = jq_bbq_getState = function( key, coerce ) { 1709 return key === undefined || typeof key === 'boolean' 1710 ? jq_deparam_fragment( key ) // 'key' really means 'coerce' here 1711 : jq_deparam_fragment( coerce )[ key ]; 1712 }; 1713 1714 // Method: jQuery.bbq.removeState 1715 // 1716 // Remove one or more keys from the current browser history 'state', creating 1717 // a new state, setting location.hash and triggering any bound 1718 // <hashchange event> callbacks (provided the new state is different than 1719 // the previous state). 1720 // 1721 // If no arguments are passed, an empty state is created, which is just a 1722 // shortcut for jQuery.bbq.pushState( {}, 2 ). 1723 // 1724 // Usage: 1725 // 1726 // > jQuery.bbq.removeState( [ key [, key ... ] ] ); 1727 // 1728 // Arguments: 1729 // 1730 // key - (String) One or more key values to remove from the current state, 1731 // passed as individual arguments. 1732 // key - (Array) A single array argument that contains a list of key values 1733 // to remove from the current state. 1734 // 1735 // Returns: 1736 // 1737 // Nothing. 1738 // 1739 // Additional Notes: 1740 // 1741 // * Setting an empty state may cause the browser to scroll. 1742 1743 jq_bbq.removeState = function( arr ) { 1744 var state = {}; 1745 1746 // If one or more arguments is passed.. 1747 if ( arr !== undefined ) { 1748 1749 // Get the current state. 1750 state = jq_bbq_getState(); 1751 1752 // For each passed key, delete the corresponding property from the current 1753 // state. 1754 $.each( $.isArray( arr ) ? arr : arguments, function(i,v){ 1755 delete state[ v ]; 1756 }); 1757 } 1758 1759 // Set the state, completely overriding any existing state. 1760 jq_bbq_pushState( state, 2 ); 1761 }; 1762 1763 // Event: hashchange event (BBQ) 1764 // 1765 // Usage in jQuery 1.4 and newer: 1766 // 1767 // In jQuery 1.4 and newer, the event object passed into any hashchange event 1768 // callback is augmented with a copy of the location.hash fragment at the time 1769 // the event was triggered as its event.fragment property. In addition, the 1770 // event.getState method operates on this property (instead of location.hash) 1771 // which allows this fragment-as-a-state to be referenced later, even after 1772 // window.location may have changed. 1773 // 1774 // Note that event.fragment and event.getState are not defined according to 1775 // W3C (or any other) specification, but will still be available whether or 1776 // not the hashchange event exists natively in the browser, because of the 1777 // utility they provide. 1778 //
1779 // The event.fragment property contains the output of <jQuery.param.fragment> 1780 // and the event.getState method is equivalent to the <jQuery.bbq.getState> 1781 // method. 1782 // 1783 // > $(window).bind( 'hashchange', function( event ) { 1784 // > var hash_str = event.fragment, 1785 // > param_obj = event.getState(), 1786 // > param_val = event.getState( 'param_name' ), 1787 // > param_val_coerced = event.getState( 'param_name', true ); 1788 // > ... 1789 // > }); 1790 // 1791 // Usage in jQuery 1.3.2: 1792 // 1793 // In jQuery 1.3.2, the event object cannot to be augmented as in jQuery 1.4+, 1794 // so the fragment state isn't bound to the event object and must instead be 1795 // parsed using the <jQuery.param.fragment> and <jQuery.bbq.getState> methods. 1796 // 1797 // > $(window).bind( 'hashchange', function( event ) { 1798 // > var hash_str = $.param.fragment(), 1799 // > param_obj = $.bbq.getState(), 1800 // > param_val = $.bbq.getState( 'param_name' ), 1801 // > param_val_coerced = $.bbq.getState( 'param_name', true ); 1802 // > ... 1803 // > }); 1804 // 1805 // Additional Notes: 1806 // 1807 // * Due to changes in the special events API, jQuery BBQ v1.2 or newer is 1808 // required to enable the augmented event object in jQuery 1.4.2 and newer. 1809 // * See <jQuery hashchange event> for more detailed information. 1810 1811 jq_event_special[ str_hashchange ] = $.extend( jq_event_special[ str_hashchange ], { 1812 1813 // Augmenting the event object with the .fragment property and .getState 1814 // method requires jQuery 1.4 or newer. Note: with 1.3.2, everything will 1815 // work, but the event won't be augmented) 1816 add: function( handleObj ) { 1817 var old_handler; 1818 1819 function new_handler(e) { 1820 // e.fragment is set to the value of location.hash (with any leading # 1821 // removed) at the time the event is triggered. 1822 var hash = e[ str_fragment ] = jq_param_fragment(); 1823 1824 // e.getState() works just like $.bbq.getState(), but uses the 1825 // e.fragment property stored on the event object. 1826 e.getState = function( key, coerce ) { 1827 return key === undefined || typeof key === 'boolean' 1828 ? jq_deparam( hash, key ) // 'key' really means 'coerce' here 1829 : jq_deparam( hash, coerce )[ key ]; 1830 }; 1831 1832 old_handler.apply( this, arguments ); 1833 }; 1834 1835 // This may seem a little complicated, but it normalizes the special event 1836 // .add method between jQuery 1.4/1.4.1 and 1.4.2+ 1837 if ( $.isFunction( handleObj ) ) { 1838 // 1.4, 1.4.1 1839 old_handler = handleObj; 1840 return new_handler; 1841 } else { 1842 // 1.4.2+ 1843 old_handler = handleObj.handler; 1844 handleObj.handler = new_handler; 1845 } 1846 } 1847 1848 }); 1849 1850})(jQuery,this); 1851 1852/*! 1853 * jQuery hashchange event - v1.2 - 2/11/2010 1854 * http://benalman.com/projects/jquery-hashchange-plugin/ 1855 * 1856 * Copyright (c) 2010 "Cowboy" Ben Alman 1857 * Dual licensed under the MIT and GPL licenses. 1858 * http://benalman.com/about/license/ 1859 */ 1860 1861// Script: jQuery hashchange event 1862// 1863// *Version: 1.2, Last updated: 2/11/2010* 1864// 1865// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/ 1866// GitHub - http://github.com/cowboy/jquery-hashchange/ 1867// Source - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js 1868// (Minified) - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (1.1kb) 1869// 1870// About: License 1871// 1872// Copyright (c) 2010 "Cowboy" Ben Alman, 1873// Dual licensed under the MIT and GPL licenses. 1874// http://benalman.com/about/license/ 1875// 1876// About: Examples 1877// 1878// This working example, complete with fully commented code, illustrate one way 1879// in which this plugin can be used. 1880// 1881// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/ 1882// 1883// About: Support and Testing 1884// 1885// Information about what version or versions of jQuery this plugin has been 1886// tested with, what browsers it has been tested in, and where the unit tests 1887// reside (so you can test it yourself). 1888// 1889// jQuery Versions - 1.3.2, 1.4.1, 1.4.2 1890// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.7, Safari 3-4, Chrome, Opera 9.6-10.1. 1891// Unit Tests - http://benalman.com/code/projects/jquery-hashchange/unit/ 1892// 1893// About: Known issues 1894// 1895// While this jQuery hashchange event implementation is quite stable and robust, 1896// there are a few unfortunate browser bugs surrounding expected hashc
1896hange 1897// event-based behaviors, independent of any JavaScript window.onhashchange 1898// abstraction. See the following examples for more information: 1899// 1900// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/ 1901// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/ 1902// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/ 1903// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/ 1904// 1905// About: Release History 1906// 1907// 1.2 - (2/11/2010) Fixed a bug where coming back to a page using this plugin 1908// from a page on another domain would cause an error in Safari 4. Also, 1909// IE6/7 Iframe is now inserted after the body (this actually works), 1910// which prevents the page from scrolling when the event is first bound. 1911// Event can also now be bound before DOM ready, but it won't be usable 1912// before then in IE6/7. 1913// 1.1 - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug 1914// where browser version is incorrectly reported as 8.0, despite 1915// inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag. 1916// 1.0 - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special 1917// window.onhashchange functionality into a separate plugin for users 1918// who want just the basic event & back button support, without all the 1919// extra awesomeness that BBQ provides. This plugin will be included as 1920// part of jQuery BBQ, but also be available separately. 1921 1922(function($,window,undefined){ 1923 '$:nomunge'; // Used by YUI compressor. 1924 1925 // Method / object references. 1926 var fake_onhashchange, 1927 jq_event_special = $.event.special, 1928 1929 // Reused strings. 1930 str_location = 'location', 1931 str_hashchange = 'hashchange', 1932 str_href = 'href', 1933 1934 // IE6/7 specifically need some special love when it comes to back-button 1935 // support, so let's do a little browser sniffing.. 1936 browser = $.browser, 1937 mode = document.documentMode, 1938 is_old_ie = browser.msie && ( mode === undefined || mode < 8 ), 1939 1940 // Does the browser support window.onhashchange? Test for IE version, since 1941 // IE8 incorrectly reports this when in "IE7" or "IE8 Compatibility View"! 1942 supports_onhashchange = 'on' + str_hashchange in window && !is_old_ie; 1943 1944 // Get location.hash (or what you'd expect location.hash to be) sans any 1945 // leading #. Thanks for making this necessary, Firefox! 1946 function get_fragment( url ) { 1947 url = url || window[ str_location ][ str_href ]; 1948 return url.replace( /^[^#]*#?(.*)$/, '$1' ); 1949 }; 1950 1951 // Property: jQuery.hashchangeDelay 1952 // 1953 // The numeric interval (in milliseconds) at which the <hashchange event> 1954 // polling loop executes. Defaults to 100. 1955 1956 $[ str_hashchange + 'Delay' ] = 100; 1957 1958 // Event: hashchange event 1959 // 1960 // Fired when location.hash changes. In browsers that support it, the native 1961 // window.onhashchange event is used (IE8, FF3.6), otherwise a polling loop is 1962 // initialized, running every <jQuery.hashchangeDelay> milliseconds to see if 1963 // the hash has changed. In IE 6 and 7, a hidden Iframe is created to allow 1964 // the back button and hash-based history to work. 1965 // 1966 // Usage: 1967 // 1968 // > $(window).bind( 'hashchange', function(e) { 1969 // > var hash = location.hash; 1970 // > ... 1971 // > }); 1972 // 1973 // Additional Notes: 1974 // 1975 // * The polling loop and Iframe are not created until at least one callback 1976 // is actually bound to 'hashchange'. 1977 // * If you need the bound callback(s) to execute immediately, in cases where 1978 // the page 'state' exists on page load (via bookmark or page refresh, for 1979 // example) use $(window).trigger( 'hashchange' ); 1980 // * The event can be bound before DOM ready, but since it won't be usable 1981 // before then in IE6/7 (due to the necessary Iframe), recommended usage is 1982 // to bind it inside a $(document).ready() callback. 1983
1984 jq_event_special[ str_hashchange ] = $.extend( jq_event_special[ str_hashchange ], { 1985 1986 // Called only when the first 'hashchange' event is bound to window. 1987 setup: function() { 1988 // If window.onhashchange is supported natively, there's nothing to do.. 1989 if ( supports_onhashchange ) { return false; } 1990 1991 // Otherwise, we need to create our own. And we don't want to call this 1992 // until the user binds to the event, just in case they never do, since it 1993 // will create a polling loop and possibly even a hidden Iframe. 1994 $( fake_onhashchange.start ); 1995 }, 1996 1997 // Called only when the last 'hashchange' event is unbound from window. 1998 teardown: function() { 1999 // If window.onhashchange is supported natively, there's nothing to do.. 2000 if ( supports_onhashchange ) { return false; } 2001 2002 // Otherwise, we need to stop ours (if possible). 2003 $( fake_onhashchange.stop ); 2004 } 2005 2006 }); 2007 2008 // fake_onhashchange does all the work of triggering the window.onhashchange 2009 // event for browsers that don't natively support it, including creating a
2010 // polling loop to watch for hash changes and in IE 6/7 creating a hidden 2011 // Iframe to enable back and forward. 2012 fake_onhashchange = (function(){ 2013 var self = {}, 2014 timeout_id, 2015 iframe, 2016 set_history, 2017 get_history; 2018 2019 // Initialize. In IE 6/7, creates a hidden Iframe for history handling. 2020 function init(){ 2021 // Most browsers don't need special methods here.. 2022 set_history = get_history = function(val){ return val; }; 2023 2024 // But IE6/7 do! 2025 if ( is_old_ie ) { 2026 2027 // Create hidden Iframe after the end of the body to prevent initial 2028 // page load from scrolling unnecessarily. 2029 iframe = $('<iframe src="javascript:0"/>').hide().insertAfter( 'body' )[0].contentWindow; 2030 2031 // Get history by looking at the hidden Iframe's location.hash. 2032 get_history = function() { 2033 return get_fragment( iframe.document[ str_location ][ str_href ] ); 2034 }; 2035 2036 // Set a new history item by opening and then closing the Iframe 2037 // document, *then* setting its location.hash. 2038 set_history = function( hash, history_hash ) { 2039 if ( hash !== history_hash ) { 2040 var doc = iframe.document; 2041 doc.open().close(); 2042 doc[ str_location ].hash = '#' + hash; 2043 } 2044 }; 2045 2046 // Set initial history. 2047 set_history( get_fragment() ); 2048 } 2049 }; 2050 2051 // Start the polling loop. 2052 self.start = function() { 2053 // Polling loop is already running! 2054 if ( timeout_id ) { return; } 2055 2056 // Remember the initial hash so it doesn't get triggered immediately. 2057 var last_hash = get_fragment(); 2058 2059 // Initialize if not yet initialized. 2060 set_history || init(); 2061 2062 // This polling loop checks every $.hashchangeDelay milliseconds to see if 2063 // location.hash has changed, and triggers the 'hashchange' event on 2064 // window when necessary. 2065 (function loopy(){ 2066 var hash = get_fragment(), 2067 history_hash = get_history( last_hash ); 2068 2069 if ( hash !== last_hash ) { 2070 set_history( last_hash = hash, history_hash ); 2071 2072 $(window).trigger( str_hashchange ); 2073 2074 } else if ( history_hash !== last_hash ) { 2075 window[ str_location ][ str_href ] = window[ str_location ][ str_href ].replace( /#.*/, '' ) + '#' + history_hash; 2076 } 2077 2078 timeout_id = setTimeout( loopy, $[ str_hashchange + 'Delay' ] ); 2079 })(); 2080 }; 2081 2082 // Stop the polling loop, but only if an IE6/7 Iframe wasn't created. In 2083 // that case, even if there are no longer any bound event handlers, the 2084 // polling loop is still necessary for back/next to work at all! 2085 self.stop = function() { 2086 if ( !iframe ) { 2087 timeout_id && clearTimeout( timeout_id ); 2088 timeout_id = 0; 2089 } 2090 }; 2091 2092 return self; 2093 })(); 2094 2095})(jQuery,this); 2096/*************************************************************************************/ 2097 2098/************************** <jStorage-jquery-plugin> *********************************/ 2099/* 2100 * ----------------------------- JSTORAGE ------------------------------------- 2101 * Simple local storage wrapper to save data on the browser side, supporting 2102 * all major browsers - IE6+, Firefox2+, Safari4+, Chrome4+ and Opera 10.5+ 2103 * 2104 * Author: Andris Reinman, [email protected] 2105 * Project homepage: www.jstorage.info 2106 * 2107 * Licensed under Unlicense: 2108 * 2109 * This is free and unencumbered software released into the public domain. 2110 * 2111 * Anyone is free to copy, modify, publish, use, compile, sell, or 2112 * distribute this software, either in source code form or as a compiled 2113 * binary, for any purpose, commercial or non-commercial, and by any 2114 * means. 2115 * 2116 * In jurisdictions that recognize copyright laws, the author or authors 2117 * of this software dedicate any and all copyright interest in the 2118 * software to the public domain. We make this dedication for the benefit 2119 * of the public at large and to the detriment of our heirs and 2120 * successors. We intend this dedication to be an overt act of 2121 * relinquishment in perpetuity of all present and future rights to this 2122 * software under copyright law. 2123 * 2124 * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 2125 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2126 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 2127 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 2128 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2129 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2130 * OTHER DEALINGS IN THE SOFTWARE. 2131 * 2132 * For more information, please refer to <http://unlicense.org/> 2133 */ 2134 2135(function() { 2136 'use strict'; 2137 2138 var 2139 /* jStorage version */ 2140 JSTORAGE_VERSION = '0.4.11', 2141 2142 /* detect a dollar object or create one if not found */ 2143 $ = window.jQuery || window.$ || (window.$ = {}), 2144 2145 /* check for a JSON handling support */ 2146 JSON = { 2147 parse: window.JSON && (window.JSON.parse || window.JSON.decode) || 2148 String.prototype.evalJSON && function(str) { 2149 return String(str).evalJSON(); 2150 } || 2151 $.parseJSON || 2152 $.evalJSON,
vendor: 19,510 bytes, lines 2153-2755
2153 stringify: Object.toJSON || 2154 window.JSON && (window.JSON.stringify || window.JSON.encode) || 2155 $.toJSON 2156 }; 2157 2158 // Break if no JSON support was found 2159 if (typeof JSON.parse !== 'function' || typeof JSON.stringify !== 'function') { 2160 throw new Error('No JSON support found, include //cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js to page'); 2161 } 2162 2163 var 2164 /* This is the object, that holds the cached values */ 2165 _storage = { 2166 __jstorage_meta: { 2167 CRC32: {} 2168 } 2169 }, 2170 2171 /* Actual browser storage (localStorage or globalStorage['domain']) */ 2172 _storage_service = { 2173 jStorage: '{}' 2174 }, 2175 2176 /* DOM element for older IE versions, holds userData behavior */ 2177 _storage_elm = null, 2178 2179 /* How much space does the storage take */ 2180 _storage_size = 0, 2181 2182 /* which backend is currently used */ 2183 _backend = false, 2184 2185 /* onchange observers */ 2186 _observers = {}, 2187 2188 /* timeout to wait after onchange event */ 2189 _observer_timeout = false, 2190 2191 /* last update time */ 2192 _observer_update = 0, 2193 2194 /* pubsub observers */ 2195 _pubsub_observers = {}, 2196 2197 /* skip published items older than current timestamp */ 2198 _pubsub_last = +new Date(), 2199 2200 /* Next check for TTL */ 2201 _ttl_timeout, 2202 2203 /** 2204 * XML encoding and decoding as XML nodes can't be JSON'ized 2205 * XML nodes are encoded and decoded if the node is the value to be saved 2206 * but not if it's as a property of another object 2207 * Eg. - 2208 * $.jStorage.set('key', xmlNode); // IS OK 2209 * $.jStorage.set('key', {xml: xmlNode}); // NOT OK 2210 */ 2211 _XMLService = { 2212 2213 /** 2214 * Validates a XML node to be XML 2215 * based on jQuery.isXML function 2216 */ 2217 isXML: function(elm) { 2218 var documentElement = (elm ? elm.ownerDocument || elm : 0).documentElement; 2219 return documentElement ? documentElement.nodeName !== 'HTML' : false; 2220 }, 2221 2222 /** 2223 * Encodes a XML node to string 2224 * based on http://www.mercurytide.co.uk/news/article/issues-when-working-ajax/ 2225 */ 2226 encode: function(xmlNode) { 2227 if (!this.isXML(xmlNode)) { 2228 return false; 2229 } 2230 try { // Mozilla, Webkit, Opera 2231 return new XMLSerializer().serializeToString(xmlNode); 2232 } catch (E1) { 2233 try { // IE 2234 return xmlNode.xml; 2235 } catch (E2) {} 2236 } 2237 return false; 2238 }, 2239 2240 /** 2241 * Decodes a XML node from string 2242 * loosely based on http://outwestmedia.com/jquery-plugins/xmldom/ 2243 */ 2244 decode: function(xmlString) { 2245 var dom_parser = ('DOMParser' in window && (new DOMParser()).parseFromString) || 2246 (window.ActiveXObject && function(_xmlString) { 2247 var xml_doc = new ActiveXObject('Microsoft.XMLDOM'); 2248 xml_doc.async = 'false'; 2249 xml_doc.loadXML(_xmlString); 2250 return xml_doc; 2251 }), 2252 resultXML; 2253 if (!dom_parser) { 2254 return false; 2255 } 2256 resultXML = dom_parser.call('DOMParser' in window && (new DOMParser()) || window, xmlString, 'text/xml'); 2257 return this.isXML(resultXML) ? resultXML : false; 2258 } 2259 }; 2260 2261 2262 ////////////////////////// PRIVATE METHODS //////////////////////// 2263 2264 /** 2265 * Initialization function. Detects if the browser supports DOM Storage 2266 * or userData behavior and behaves accordingly. 2267 */ 2268 function _init() { 2269 /* Check if browser supports localStorage */ 2270 var localStorageReallyWorks = false; 2271 if ('localStorage' in window) { 2272 try { 2273 window.localStorage.setItem('_tmptest', 'tmpval'); 2274 localStorageReallyWorks = true; 2275 window.localStorage.removeItem('_tmptest'); 2276 } catch (BogusQuotaExceededErrorOnIos5) { 2277 // Thanks be to iOS5 Private Browsing mode which throws 2278 // QUOTA_EXCEEDED_ERRROR DOM Exception 22. 2279 } 2280 } 2281 2282 if (localStorageReallyWorks) { 2283 try { 2284 if (window.localStorage) { 2285 _storage_service = window.localStorage; 2286 _backend = 'localStorage'; 2287 _observer_update = _storage_service.jStorage_update; 2288 } 2289 } catch (E3) { /* Firefox fails when touching localStorage and cookies are disabled */ } 2290 } 2291 /* Check if browser supports globalStorage */ 2292 else if ('globalStorage' in window) { 2293 try { 2294 if (window.globalStorage) { 2295 if (window.location.hostname == 'localhost') { 2296 _storage_service = window.globalStorage['localhost.localdomain']; 2297 } else { 2298 _storage_service = window.globalStorage[window.location.hostname]; 2299 } 2300 _backend = 'globalStorage'; 2301 _observer_update = _storage_service.jStorage_update; 2302 } 2303 } catch (E4) { /* Firefox fails when touching localStorage and cookies are disabled */ } 2304 } 2305 /* Check if browser supports userData behavior */ 2306 else { 2307 _storage_elm = document.createElement('link'); 2308 if (_storage_elm.addBehavior) { 2309 2310 /* Use a DOM element to act as userData storage */ 2311 _storage_elm.style.behavior = 'url(#default#userData)'; 2312 2313 /* userData element needs to be inserted into the DOM! */ 2314 document.getElementsByTagName('head')[0].appendChild(_storage_elm); 2315 2316 try { 2317 _storage_elm.load('jStorage'); 2318 } catch (E) { 2319 // try to reset cache 2320 _storage_elm.setAttribute('jStorage', '{}'); 2321 _storage_elm.save('jStorage'); 2322 _storage_elm.load('jStorage'); 2323 } 2324 2325 var data = '{}'; 2326 try { 2327 data = _storage_elm.getAttribute('jStorage'); 2328 } catch (E5) {} 2329 2330 try { 2331 _observer_update = _storage_elm.getAttribute('jStorage_update'); 2332 } catch (E6) {} 2333 2334 _storage_service.jStorage = data; 2335 _backend = 'userDataBehavior'; 2336 } else { 2337 _storage_elm = null; 2338 return; 2339 } 2340 } 2341 2342 // Load data from storage 2343 _load_storage(); 2344 2345 // remove dead keys 2346 _handleTTL(); 2347 2348 // start listening for changes 2349 _setupObserver(); 2350 2351 // initialize publish-subscribe service 2352 _handlePubSub(); 2353 2354 // handle cached navigation 2355 if ('addEventListener' in window) { 2356 window.addEventListener('pageshow', function(event) { 2357 if (event.persisted) { 2358 _storageObserver(); 2359 } 2360 }, false); 2361 } 2362 } 2363 2364 /** 2365 * Reload data from storage when needed 2366 */ 2367 function _reloadData() { 2368 var data = '{}'; 2369 2370 if (_backend == 'userDataBehavior') { 2371 _storage_elm.load('jStorage'); 2372 2373 try { 2374 data = _storage_elm.getAttribute('jStorage'); 2375 } catch (E5) {} 2376 2377 try { 2378 _observer_update = _storage_elm.getAttribute('jStorage_update'); 2379 } catch (E6) {} 2380 2381 _storage_service.jStorage = data; 2382 } 2383 2384 _load_storage(); 2385 2386 // remove dead keys 2387 _handleTTL(); 2388 2389 _handlePubSub(); 2390 } 2391 2392 /** 2393 * Sets up a storage change observer 2394 */ 2395 function _setupObserver() { 2396 if (_backend == 'localStorage' || _backend == 'globalStorage') { 2397 if ('addEventListener' in window) { 2398 window.addEventListener('storage', _storageObserver, false); 2399 } else { 2400 document.attachEvent('onstorage', _storageObserver); 2401 } 2402 } else if (_backend == 'userDataBehavior') { 2403 setInterval(_storageObserver, 1000); 2404 } 2405 } 2406 2407 /** 2408 * Fired on any kind of data change, needs to check if anything has 2409 * really been changed 2410 */ 2411 function _storageObserver() { 2412 var updateTime; 2413 // cumulate change notifications with timeout 2414 clearTimeout(_observer_timeout); 2415 _observer_timeout = setTimeout(function() { 2416 2417 if (_backend == 'localStorage' || _backend == 'globalStorage') { 2418 updateTime = _storage_service.jStorage_update; 2419 } else if (_backend == 'userDataBehavior') { 2420 _storage_elm.load('jStorage'); 2421 try { 2422 updateTime = _storage_elm.getAttribute('jStorage_update'); 2423 } catch (E5) {} 2424 } 2425 2426 if (updateTime && updateTime != _observer_update) { 2427 _observer_update = updateTime; 2428 _checkUpdatedKeys(); 2429 } 2430 2431 }, 25); 2432 } 2433 2434 /** 2435 * Reloads the data and checks if any keys are changed 2436 */ 2437 function _checkUpdatedKeys() { 2438 var oldCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32)), 2439 newCrc32List; 2440 2441 _reloadData(); 2442 newCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32)); 2443 2444 var key, 2445 updated = [], 2446 removed = []; 2447 2448 for (key in oldCrc32List) { 2449 if (oldCrc32List.hasOwnProperty(key)) { 2450 if (!newCrc32List[key]) { 2451 removed.push(key); 2452 continue; 2453 } 2454 if (oldCrc32List[key] != newCrc32List[key] && String(oldCrc32List[key]).substr(0, 2) == '2.') { 2455 updated.push(key); 2456 } 2457 } 2458 } 2459 2460 for (key in newCrc32List) { 2461 if (newCrc32List.hasOwnProperty(key)) { 2462 if (!oldCrc32List[key]) { 2463 updated.push(key); 2464 } 2465 } 2466 } 2467 2468 _fireObservers(updated, 'updated'); 2469 _fireObservers(removed, 'deleted'); 2470 } 2471 2472 /** 2473 * Fires observers for updated keys 2474 * 2475 * @param {Array|String} keys Array of key names or a key 2476 * @param {String} action What happened with the value (updated, deleted, flushed) 2477 */ 2478 function _fireObservers(keys, action) { 2479 keys = [].concat(keys || []); 2480 2481 var i, j, len, jlen; 2482 2483 if (action == 'flushed') { 2484 keys = []; 2485 for (var key in _observers) { 2486 if (_observers.hasOwnProperty(key)) { 2487 keys.push(key); 2488 } 2489 } 2490 action = 'deleted'; 2491 } 2492 for (i = 0, len = keys.length; i < len; i++) { 2493 if (_observers[keys[i]]) { 2494 for (j = 0, jlen = _observers[keys[i]].length; j < jlen; j++) { 2495 _observers[keys[i]][j](keys[i], action); 2496 } 2497 } 2498 if (_observers['*']) { 2499 for (j = 0, jlen = _observers['*'].length; j < jlen; j++) { 2500 _observers['*'][j](keys[i], action); 2501 } 2502 } 2503 } 2504 } 2505 2506 /** 2507 * Publishes key change to listeners 2508 */ 2509 function _publishChange() { 2510 var updateTime = (+new Date()).toString(); 2511 2512 if (_backend == 'localStorage' || _backend == 'globalStorage') { 2513 try { 2514 _storage_service.jStorage_update = updateTime; 2515 } catch (E8) { 2516 // safari private mode has been enabled after the jStorage initialization 2517 _backend = false; 2518 } 2519 } else if (_backend == 'userDataBehavior') { 2520 _storage_elm.setAttribute('jStorage_update', updateTime); 2521 _storage_elm.save('jStorage'); 2522 } 2523 2524 _storageObserver(); 2525 } 2526 2527 /** 2528 * Loads the data from the storage based on the supported mechanism 2529 */ 2530 function _load_storage() { 2531 /* if jStorage string is retrieved, then decode it */ 2532 if (_storage_service.jStorage) { 2533 try { 2534 _storage = JSON.parse(String(_storage_service.jStorage)); 2535 } catch (E6) { 2536 _storage_service.jStorage = '{}'; 2537 } 2538 } else { 2539 _storage_service.jStorage = '{}'; 2540 } 2541 _storage_size = _storage_service.jStorage ? String(_storage_service.jStorage).length : 0; 2542 2543 if (!_storage.__jstorage_meta) { 2544 _storage.__jstorage_meta = {}; 2545 } 2546 if (!_storage.__jstorage_meta.CRC32) { 2547 _storage.__jstorage_meta.CRC32 = {}; 2548 } 2549 } 2550 2551 /** 2552 * This functions provides the 'save' mechanism to store the jStorage object 2553 */ 2554 function _save() { 2555 _dropOldEvents(); // remove expired events 2556 try { 2557 _storage_service.jStorage = JSON.stringify(_storage); 2558 // If userData is used as the storage engine, additional 2559 if (_storage_elm) { 2560 _storage_elm.setAttribute('jStorage', _storage_service.jStorage); 2561 _storage_elm.save('jStorage'); 2562 } 2563 _storage_size = _storage_service.jStorage ? String(_storage_service.jStorage).length : 0; 2564 } catch (E7) { /* probably cache is full, nothing is saved this way*/ } 2565 } 2566 2567 /** 2568 * Function checks if a key is set and is string or numberic 2569 * 2570 * @param {String} key Key name 2571 */ 2572 function _checkKey(key) { 2573 if (typeof key != 'string' && typeof key != 'number') { 2574 throw new TypeError('Key name must be string or numeric'); 2575 } 2576 if (key == '__jstorage_meta') { 2577 throw new TypeError('Reserved key name'); 2578 } 2579 return true; 2580 } 2581 2582 /** 2583 * Removes expired keys 2584 */ 2585 function _handleTTL() { 2586 var curtime, i, TTL, CRC32, nextExpire = Infinity, 2587 changed = false, 2588 deleted = []; 2589 2590 clearTimeout(_ttl_timeout); 2591 2592 if (!_storage.__jstorage_meta || typeof _storage.__jstorage_meta.TTL != 'object') { 2593 // nothing to do here 2594 return; 2595 } 2596 2597 curtime = +new Date(); 2598 TTL = _storage.__jstorage_meta.TTL; 2599 2600 CRC32 = _storage.__jstorage_meta.CRC32; 2601 for (i in TTL) { 2602 if (TTL.hasOwnProperty(i)) { 2603 if (TTL[i] <= curtime) { 2604 delete TTL[i]; 2605 delete CRC32[i]; 2606 delete _storage[i]; 2607 changed = true; 2608 deleted.push(i); 2609 } else if (TTL[i] < nextExpire) { 2610 nextExpire = TTL[i]; 2611 } 2612 } 2613 } 2614 2615 // set next check 2616 if (nextExpire != Infinity) { 2617 _ttl_timeout = setTimeout(_handleTTL, Math.min(nextExpire - curtime, 0x7FFFFFFF)); 2618 } 2619 2620 // save changes 2621 if (changed) { 2622 _save(); 2623 _publishChange(); 2624 _fireObservers(deleted, 'deleted'); 2625 } 2626 } 2627 2628 /** 2629 * Checks if there's any events on hold to be fired to listeners 2630 */ 2631 function _handlePubSub() { 2632 var i, len; 2633 if (!_storage.__jstorage_meta.PubSub) { 2634 return; 2635 } 2636 var pubelm, 2637 _pubsubCurrent = _pubsub_last; 2638 2639 for (i = len = _storage.__jstorage_meta.PubSub.length - 1; i >= 0; i--) { 2640 pubelm = _storage.__jstorage_meta.PubSub[i]; 2641 if (pubelm[0] > _pubsub_last) { 2642 _pubsubCurrent = pubelm[0]; 2643 _fireSubscribers(pubelm[1], pubelm[2]); 2644 } 2645 } 2646 2647 _pubsub_last = _pubsubCurrent; 2648 } 2649 2650 /** 2651 * Fires all subscriber listeners for a pubsub channel 2652 * 2653 * @param {String} channel Channel name 2654 * @param {Mixed} payload Payload data to deliver 2655 */ 2656 function _fireSubscribers(channel, payload) { 2657 if (_pubsub_observers[channel]) { 2658 for (var i = 0, len = _pubsub_observers[channel].length; i < len; i++) { 2659 // send immutable data that can't be modified by listeners 2660 try { 2661 _pubsub_observers[channel][i](channel, JSON.parse(JSON.stringify(payload))); 2662 } catch (E) {} 2663 } 2664 } 2665 } 2666 2667 /** 2668 * Remove old events from the publish stream (at least 2sec old) 2669 */ 2670 function _dropOldEvents() { 2671 if (!_storage.__jstorage_meta.PubSub) { 2672 return; 2673 } 2674 2675 var retire = +new Date() - 2000; 2676 2677 for (var i = 0, len = _storage.__jstorage_meta.PubSub.length; i < len; i++) { 2678 if (_storage.__jstorage_meta.PubSub[i][0] <= retire) { 2679 // deleteCount is needed for IE6 2680 _storage.__jstorage_meta.PubSub.splice(i, _storage.__jstorage_meta.PubSub.length - i); 2681 break; 2682 } 2683 } 2684 2685 if (!_storage.__jstorage_meta.PubSub.length) { 2686 delete _storage.__jstorage_meta.PubSub; 2687 } 2688 2689 } 2690 2691 /** 2692 * Publish payload to a channel 2693 * 2694 * @param {String} channel Channel name 2695 * @param {Mixed} payload Payload to send to the subscribers 2696 */ 2697 function _publish(channel, payload) { 2698 if (!_storage.__jstorage_meta) { 2699 _storage.__jstorage_meta = {}; 2700 } 2701 if (!_storage.__jstorage_meta.PubSub) { 2702 _storage.__jstorage_meta.PubSub = []; 2703 } 2704 2705 _storage.__jstorage_meta.PubSub.unshift([+new Date(), channel, payload]); 2706 2707 _save(); 2708 _publishChange(); 2709 } 2710 2711 2712 /** 2713 * JS Implementation of MurmurHash2 2714 * 2715 * SOURCE: https://github.com/garycourt/murmurhash-js (MIT licensed) 2716 * 2717 * @author <a href='mailto:[email protected]'>Gary Court</a> 2718 * @see http://github.com/garycourt/murmurhash-js 2719 * @author <a href='mailto:[email protected]'>Austin Appleby</a> 2720 * @see http://sites.google.com/site/murmurhash/ 2721 * 2722 * @param {string} str ASCII only 2723 * @param {number} seed Positive integer only 2724 * @return {number} 32-bit positive integer hash 2725 */ 2726 2727 function murmurhash2_32_gc(str, seed) { 2728 var 2729 l = str.length, 2730 h = seed ^ l, 2731 i = 0, 2732 k; 2733 2734 while (l >= 4) { 2735 k = 2736 ((str.charCodeAt(i) & 0xff)) | 2737 ((str.charCodeAt(++i) & 0xff) << 8) | 2738 ((str.charCodeAt(++i) & 0xff) << 16) | 2739 ((str.charCodeAt(++i) & 0xff) << 24); 2740 2741 k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16)); 2742 k ^= k >>> 24; 2743 k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16)); 2744 2745 h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k; 2746 2747 l -= 4; 2748 ++i; 2749 } 2750 2751 switch (l) { 2752 case 3: 2753 h ^= (str.charCodeAt(i + 2) & 0xff) << 16; 2754 case 2: 2755 h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
vendor: 9,940 bytes, lines 2755-3084
2755 2756 case 1: 2757 h ^= (str.charCodeAt(i) & 0xff); 2758 h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)); 2759 } 2760 2761 h ^= h >>> 13; 2762 h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)); 2763 h ^= h >>> 15; 2764 2765 return h >>> 0; 2766 } 2767 2768 ////////////////////////// PUBLIC INTERFACE ///////////////////////// 2769 2770 $.jStorage = { 2771 /* Version number */ 2772 version: JSTORAGE_VERSION, 2773 2774 /** 2775 * Sets a key's value. 2776 * 2777 * @param {String} key Key to set. If this value is not set or not 2778 * a string an exception is raised. 2779 * @param {Mixed} value Value to set. This can be any value that is JSON 2780 * compatible (Numbers, Strings, Objects etc.). 2781 * @param {Object} [options] - possible options to use 2782 * @param {Number} [options.TTL] - optional TTL value, in milliseconds 2783 * @return {Mixed} the used value 2784 */ 2785 set: function(key, value, options) { 2786 _checkKey(key); 2787 2788 options = options || {}; 2789 2790 // undefined values are deleted automatically 2791 if (typeof value == 'undefined') { 2792 this.deleteKey(key); 2793 return value; 2794 } 2795 2796 if (_XMLService.isXML(value)) { 2797 value = { 2798 _is_xml: true, 2799 xml: _XMLService.encode(value) 2800 }; 2801 } else if (typeof value == 'function') { 2802 return undefined; // functions can't be saved! 2803 } else if (value && typeof value == 'object') { 2804 // clone the object before saving to _storage tree 2805 value = JSON.parse(JSON.stringify(value)); 2806 } 2807 2808 _storage[key] = value; 2809 2810 _storage.__jstorage_meta.CRC32[key] = '2.' + murmurhash2_32_gc(JSON.stringify(value), 0x9747b28c); 2811 2812 this.setTTL(key, options.TTL || 0); // also handles saving and _publishChange 2813 2814 _fireObservers(key, 'updated'); 2815 return value; 2816 }, 2817 2818 /** 2819 * Looks up a key in cache 2820 * 2821 * @param {String} key - Key to look up. 2822 * @param {mixed} def - Default value to return, if key didn't exist. 2823 * @return {Mixed} the key value, default value or null 2824 */ 2825 get: function(key, def) { 2826 _checkKey(key); 2827 if (key in _storage) { 2828 if (_storage[key] && typeof _storage[key] == 'object' && _storage[key]._is_xml) { 2829 return _XMLService.decode(_storage[key].xml); 2830 } else { 2831 return _storage[key]; 2832 } 2833 } 2834 return typeof(def) == 'undefined' ? null : def; 2835 }, 2836 2837 /** 2838 * Deletes a key from cache. 2839 * 2840 * @param {String} key - Key to delete. 2841 * @return {Boolean} true if key existed or false if it didn't 2842 */ 2843 deleteKey: function(key) { 2844 _checkKey(key); 2845 if (key in _storage) { 2846 delete _storage[key]; 2847 // remove from TTL list 2848 if (typeof _storage.__jstorage_meta.TTL == 'object' && 2849 key in _storage.__jstorage_meta.TTL) { 2850 delete _storage.__jstorage_meta.TTL[key]; 2851 } 2852 2853 delete _storage.__jstorage_meta.CRC32[key]; 2854 2855 _save(); 2856 _publishChange(); 2857 _fireObservers(key, 'deleted'); 2858 return true; 2859 } 2860 return false; 2861 }, 2862 2863 /** 2864 * Sets a TTL for a key, or remove it if ttl value is 0 or below 2865 * 2866 * @param {String} key - key to set the TTL for 2867 * @param {Number} ttl - TTL timeout in milliseconds 2868 * @return {Boolean} true if key existed or false if it didn't 2869 */ 2870 setTTL: function(key, ttl) { 2871 var curtime = +new Date(); 2872 _checkKey(key); 2873 ttl = Number(ttl) || 0; 2874 if (key in _storage) { 2875 2876 if (!_storage.__jstorage_meta.TTL) { 2877 _storage.__jstorage_meta.TTL = {}; 2878 } 2879 2880 // Set TTL value for the key 2881 if (ttl > 0) { 2882 _storage.__jstorage_meta.TTL[key] = curtime + ttl; 2883 } else { 2884 delete _storage.__jstorage_meta.TTL[key]; 2885 } 2886 2887 _save(); 2888 2889 _handleTTL(); 2890 2891 _publishChange(); 2892 return true; 2893 } 2894 return false; 2895 }, 2896 2897 /** 2898 * Gets remaining TTL (in milliseconds) for a key or 0 when no TTL has been set 2899 * 2900 * @param {String} key Key to check 2901 * @return {Number} Remaining TTL in milliseconds 2902 */ 2903 getTTL: function(key) { 2904 var curtime = +new Date(), 2905 ttl; 2906 _checkKey(key); 2907 if (key in _storage && _storage.__jstorage_meta.TTL && _storage.__jstorage_meta.TTL[key]) { 2908 ttl = _storage.__jstorage_meta.TTL[key] - curtime; 2909 return ttl || 0; 2910 } 2911 return 0; 2912 }, 2913 2914 /** 2915 * Deletes everything in cache. 2916 * 2917 * @return {Boolean} Always true 2918 */ 2919 flush: function() { 2920 _storage = { 2921 __jstorage_meta: { 2922 CRC32: {} 2923 } 2924 }; 2925 _save(); 2926 _publishChange(); 2927 _fireObservers(null, 'flushed'); 2928 return true; 2929 }, 2930 2931 /** 2932 * Returns a read-only copy of _storage 2933 * 2934 * @return {Object} Read-only copy of _storage 2935 */ 2936 storageObj: function() { 2937 function F() {} 2938 F.prototype = _storage; 2939 return new F(); 2940 }, 2941 2942 /** 2943 * Returns an index of all used keys as an array 2944 * ['key1', 'key2',..'keyN'] 2945 * 2946 * @return {Array} Used keys 2947 */ 2948 index: function() { 2949 var index = [], 2950 i; 2951 for (i in _storage) { 2952 if (_storage.hasOwnProperty(i) && i != '__jstorage_meta') { 2953 index.push(i); 2954 } 2955 } 2956 return index; 2957 }, 2958 2959 /** 2960 * How much space in bytes does the storage take? 2961 * 2962 * @return {Number} Storage size in chars (not the same as in bytes, 2963 * since some chars may take several bytes) 2964 */ 2965 storageSize: function() { 2966 return _storage_size; 2967 }, 2968 2969 /** 2970 * Which backend is currently in use? 2971 * 2972 * @return {String} Backend name 2973 */ 2974 currentBackend: function() { 2975 return _backend; 2976 }, 2977 2978 /** 2979 * Test if storage is available 2980 * 2981 * @return {Boolean} True if storage can be used 2982 */ 2983 storageAvailable: function() { 2984 return !!_backend; 2985 }, 2986 2987 /** 2988 * Register change listeners 2989 * 2990 * @param {String} key Key name 2991 * @param {Function} callback Function to run when the key changes 2992 */ 2993 listenKeyChange: function(key, callback) { 2994 _checkKey(key); 2995 if (!_observers[key]) { 2996 _observers[key] = []; 2997 } 2998 _observers[key].push(callback); 2999 }, 3000 3001 /** 3002 * Remove change listeners 3003 * 3004 * @param {String} key Key name to unregister listeners against 3005 * @param {Function} [callback] If set, unregister the callback, if not - unregister all 3006 */ 3007 stopListening: function(key, callback) { 3008 _checkKey(key); 3009 3010 if (!_observers[key]) { 3011 return; 3012 } 3013 3014 if (!callback) { 3015 delete _observers[key]; 3016 return; 3017 } 3018 3019 for (var i = _observers[key].length - 1; i >= 0; i--) { 3020 if (_observers[key][i] == callback) { 3021 _observers[key].splice(i, 1); 3022 } 3023 } 3024 }, 3025 3026 /** 3027 * Subscribe to a Publish/Subscribe event stream 3028 * 3029 * @param {String} channel Channel name 3030 * @param {Function} callback Function to run when the something is published to the channel 3031 */ 3032 subscribe: function(channel, callback) { 3033 channel = (channel || '').toString(); 3034 if (!channel) { 3035 throw new TypeError('Channel not defined'); 3036 } 3037 if (!_pubsub_observers[channel]) { 3038 _pubsub_observers[channel] = []; 3039 } 3040 _pubsub_observers[channel].push(callback); 3041 }, 3042 3043 /** 3044 * Publish data to an event stream 3045 * 3046 * @param {String} channel Channel name 3047 * @param {Mixed} payload Payload to deliver 3048 */ 3049 publish: function(channel, payload) { 3050 channel = (channel || '').toString(); 3051 if (!channel) { 3052 throw new TypeError('Channel not defined'); 3053 } 3054 3055 _publish(channel, payload); 3056 }, 3057 3058 /** 3059 * Reloads the data from browser storage 3060 */ 3061 reInit: function() { 3062 _reloadData(); 3063 }, 3064 3065 /** 3066 * Removes reference from global objects and saves it as jStorage 3067 * 3068 * @param {Boolean} option if needed to save object as simple 'jStorage' in windows context 3069 */ 3070 noConflict: function(saveInGlobal) { 3071 delete window.$.jStorage; 3072 3073 if (saveInGlobal) { 3074 window.jStorage = this; 3075 } 3076 3077 return this; 3078 } 3079 }; 3080 3081 // Initialize jStorage 3082 _init(); 3083 3084})();
vendor: 6,162 bytes, lines 3084-3265
3084 3085/************************** </jStorage-jquery-plugin> ********************************/ 3086 3087/************************** <.toISOString() shim for IE8> ********************************/ 3088if ( !Date.prototype.toISOString ) { 3089 3090 ( function() { 3091 3092 function pad(number) { 3093 var r = String(number); 3094 if ( r.length === 1 ) { 3095 r = '0' + r; 3096 } 3097 return r; 3098 } 3099 3100 Date.prototype.toISOString = function() { 3101 return this.getUTCFullYear() 3102 + '-' + pad( this.getUTCMonth() + 1 ) 3103 + '-' + pad( this.getUTCDate() ) 3104 + 'T' + pad( this.getUTCHours() ) 3105 + ':' + pad( this.getUTCMinutes() ) 3106 + ':' + pad( this.getUTCSeconds() ) 3107 + '.' + String( (this.getUTCMilliseconds()/1000).toFixed(3) ).slice( 2, 5 ) 3108 + 'Z'; 3109 }; 3110 3111 }() ); 3112} 3113/************************** </.toISOString() shim for IE8> ********************************/ 3114 3115/************************** <http://timeago.yarp.com/jquery.timeago.js> ********************************/ 3116/** 3117 * Timeago is a jQuery plugin that makes it easy to support automatically 3118 * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago"). 3119 * 3120 * @name timeago 3121 * @version 1.4.1 3122 * @requires jQuery v1.2.3+ 3123 * @author Ryan McGeary 3124 * @license MIT License - http://www.opensource.org/licenses/mit-license.php 3125 * 3126 * For usage and examples, visit: 3127 * http://timeago.yarp.com/ 3128 * 3129 * Copyright (c) 2008-2013, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org) 3130 */ 3131 3132(function (factory) { 3133 if (typeof define === 'function' && define.amd) { 3134 // AMD. Register as an anonymous module. 3135 define(['jquery'], factory); 3136 } else { 3137 // Browser globals 3138 factory(jQuery); 3139 } 3140}(function ($) { 3141 $.timeago = function(timestamp) { 3142 if (timestamp instanceof Date) { 3143 return inWords(timestamp); 3144 } else if (typeof timestamp === "string") { 3145 return inWords($.timeago.parse(timestamp)); 3146 } else if (typeof timestamp === "number") { 3147 return inWords(new Date(timestamp)); 3148 } else { 3149 return inWords($.timeago.datetime(timestamp)); 3150 } 3151 }; 3152 var $t = $.timeago; 3153 3154 $.extend($.timeago, { 3155 settings: { 3156 refreshMillis: 60000, 3157 allowPast: true, 3158 allowFuture: false, 3159 localeTitle: false, 3160 cutoff: 0, 3161 strings: { 3162 prefixAgo: null, 3163 prefixFromNow: null, 3164 suffixAgo: "ago", 3165 suffixFromNow: "from now", 3166 inPast: 'any moment now', 3167 seconds: "less than a minute", 3168 minute: "about a minute", 3169 minutes: "%d minutes", 3170 hour: "about an hour", 3171 hours: "about %d hours", 3172 day: "a day", 3173 days: "%d days", 3174 month: "about a month", 3175 months: "%d months", 3176 year: "about a year", 3177 years: "%d years", 3178 wordSeparator: " ", 3179 numbers: [] 3180 } 3181 }, 3182 3183 inWords: function(distanceMillis) { 3184 if(!this.settings.allowPast && ! this.settings.allowFuture) { 3185 throw 'timeago allowPast and allowFuture settings can not both be set to false.'; 3186 } 3187 3188 var $l = this.settings.strings; 3189 var prefix = $l.prefixAgo; 3190 var suffix = $l.suffixAgo; 3191 if (this.settings.allowFuture) { 3192 if (distanceMillis < 0) { 3193 prefix = $l.prefixFromNow; 3194 suffix = $l.suffixFromNow; 3195 } 3196 } 3197 3198 if(!this.settings.allowPast && distanceMillis >= 0) { 3199 return this.settings.strings.inPast; 3200 } 3201 3202 var seconds = Math.abs(distanceMillis) / 1000; 3203 var minutes = seconds / 60; 3204 var hours = minutes / 60; 3205 var days = hours / 24; 3206 var years = days / 365; 3207 3208 function substitute(stringOrFunction, number) { 3209 var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction; 3210 var value = ($l.numbers && $l.numbers[number]) || number; 3211 return string.replace(/%d/i, value); 3212 } 3213 3214 var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) || 3215 seconds < 90 && substitute($l.minute, 1) || 3216 minutes < 45 && substitute($l.minutes, Math.round(minutes)) || 3217 minutes < 90 && substitute($l.hour, 1) || 3218 hours < 24 && substitute($l.hours, Math.round(hours)) || 3219 hours < 42 && substitute($l.day, 1) || 3220 days < 30 && substitute($l.days, Math.round(days)) || 3221 days < 45 && substitute($l.month, 1) || 3222 days < 365 && substitute($l.months, Math.round(days / 30)) || 3223 years < 1.5 && substitute($l.year, 1) || 3224 substitute($l.years, Math.round(years)); 3225 3226 var separator = $l.wordSeparator || ""; 3227 if ($l.wordSeparator === undefined) { separator = " "; } 3228 return $.trim([prefix, words, suffix].join(separator)); 3229 }, 3230 3231 parse: function(iso8601) { 3232 var s = $.trim(iso8601); 3233 s = s.replace(/\.\d+/,""); // remove milliseconds 3234 s = s.replace(/-/,"/").replace(/-/,"/"); 3235 s = s.replace(/T/," ").replace(/Z/," UTC"); 3236 s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400 3237 s = s.replace(/([\+\-]\d\d)$/," $100"); // +09 -> +0900 3238 return new Date(s); 3239 }, 3240 datetime: function(elem) { 3241 var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title"); 3242 return $t.parse(iso8601); 3243 }, 3244 isTime: function(elem) { 3245 // jQuery's `is()` doesn't play well with HTML5 in IE 3246 return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time"); 3247 } 3248 }); 3249 3250 // functions that can be called via $(el).timeago('action') 3251 // init is default when no action is given 3252 // functions are called with context of a single element 3253 var functions = { 3254 init: function(){ 3255 var refresh_el = $.proxy(refresh, this); 3256 refresh_el(); 3257 var $s = $t.settings; 3258 if ($s.refreshMillis > 0) { 3259 this._timeagoInterval = setInterval(refresh_el, $s.refreshMillis); 3260 } 3261 }, 3262 update: function(time){ 3263 var parsedTime = $t.parse(time); 3264 $(this).data('timeago', { datetime: parsedTime }); 3265 if($t.settings.localeTitle) $(this).attr("title", parsedTime.toLocaleStr
3265ing()); 3266 refresh.apply(this); 3267 }, 3268 updateFromDOM: function(){ 3269 $(this).data('timeago', { datetime: $t.parse( $t.isTime(this) ? $(this).attr("datetime") : $(this).attr("title") ) }); 3270 refresh.apply(this); 3271 }, 3272 dispose: function () { 3273 if (this._timeagoInterval) { 3274 window.clearInterval(this._timeagoInterval); 3275 this._timeagoInterval = null; 3276 } 3277 } 3278 }; 3279 3280 $.fn.timeago = function(action, options) { 3281 var fn = action ? functions[action] : functions.init; 3282 if(!fn){ 3283 throw new Error("Unknown function name '"+ action +"' for timeago"); 3284 } 3285 // each over objects here and call the requested function 3286 this.each(function(){ 3287 fn.call(this, options); 3288 }); 3289 return this; 3290 }; 3291 3292 function refresh() { 3293 var data = prepareData(this); 3294 var $s = $t.settings; 3295 3296 if (!isNaN(data.datetime)) { 3297 if ( $s.cutoff == 0 || Math.abs(distance(data.datetime)) < $s.cutoff) { 3298 $(this).text(inWords(data.datetime)); 3299 } 3300 } 3301 return this; 3302 } 3303 3304 function prepareData(element) { 3305 element = $(element); 3306 if (!element.data("timeago")) { 3307 element.data("timeago", { datetime: $t.datetime(element) }); 3308 var text = $.trim(element.text()); 3309 if ($t.settings.localeTitle) { 3310 element.attr("title", element.data('timeago').datetime.toLocaleString()); 3311 } else if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) { 3312 element.attr("title", text); 3313 } 3314 } 3315 return element.data("timeago"); 3316 } 3317 3318 function inWords(date) { 3319 return $t.inWords(distance(date)); 3320 } 3321 3322 function distance(date) { 3323 return (new Date().getTime() - date.getTime()); 3324 } 3325 3326 // fix for IE6 suckage 3327 document.createElement("abbr"); 3328 document.createElement("time"); 3329})); 3330/************************** </http://timeago.yarp.com/jquery.timeago.js> ********************************/ 3331 3332$( document ).ready(function() { 3333 3334 new DALAutoComplete({ 3335 "count": 5, 3336 "searchDelay": 1000, 3337 "url":"/projectdata", 3338 "textBoxSelector": "#search-query", 3339 "ds": "OQPC-BrowseDataSource", 3340 "collections": ["OQPC.toc"], 3341 "subsets": ["link"], 3342 "renderFunc": function(rec) { 3343 return rec.title.__value__.replace(/^ +| +$/, "");; 3344 }, 3345 "textFunc": function(rec) { 3346 return rec.title.__value__.replace(/^ +| +$/, "");; 3347 }, 3348 "searchFunc": function(text) { 3349 if(text == "") { 3350 return ""; 3351 } 3352 this.expression = '(title=(?"' + text.split(" ").join('"? AND ?"') + 3353 '"?) AND ((PitValid=@pointInTime(' + DALCore.JsDateToString(new Date(), "yymmddhhiiss") + ')' + 3354 'AND (PrintType="act.reprint" OR PrintType="reprint")) OR ' + 3355 '(PrintType="bill.first" OR PrintType="bill.third" OR ' + getRenditionPrintTypeQuery() + ')))'; 3356 return "?"; 3357 }, 3358 "selectFunc": function(rec) { 3359 window.location = createUrl(rec); 3360 }, 3361 "sortField" : ["print.type","sort.title"] // Sort by print.type then by sort.title 3362 }); 3363 3364 //var qldGovSearch = "https://find.search.qld.gov.au/s/search.html?collection=qld-gov&profile=qld"; 3365 3366 //Load stored font size 3367 if ($.jStorage.get("currFontSize") != null) { 3368 var fs = $.jStorage.get("currFontSize") + "%"; 3369 $("#main").css("font-size", fs); 3370 if(fs == (g_minF + "%")) { 3371 $("#resizeDown").prop("disabled", true); 3372 } 3373 else if(fs == (g_maxF + "%")) { 3374 $("#resizeUp").prop("disabled", true); 3375 } 3376 } 3377 else { 3378 $.jStorage.set("currFontSize", g_minF); 3379 $("#resizeDown").prop("disabled", true); 3380 } 3381 3382 $("#search-form").submit(function(e){ 3383 e.preventDefault(); 3384 var query = $("#search-query").val(); 3385 //var query = $("#search-query").val().replace(/\s\s+/g, '+'); 3386 if(window.location.pathname.match(/\/search/)) { 3387 $('#basic-search-form input[name=searchfor]').val(query); 3388 window.quicksearch = true; 3389 $("#basic-search-form").submit(); 3390 } else { 3391 window.location = window.location.origin + "/search/inforce#?action=quicksearch&query=" + encodeURIComponent(query); 3392 //window.location = qldGovSearch + "&query=" + encodeURI(query); 3393 } 3394 }); 3395 3396 //Mark currently active URL 3397 $("a[href]").each(function() { 3398 if (this.href == window.location.href) { 3399 $(this).addClass("currentPage"); 3400 } 3401 }); 3402 3403 $('.btn-tooltip').tooltip();
3404 $('.bs-popover').popover({ trigger: "hover" }); 3405 3406 var offset = 220; 3407 var duration = 100; 3408 3409 $(window).scroll(function() { 3410 if ($(this).scrollTop() > offset) { 3411 $('#top-link-block').fadeIn(duration); 3412 } else { 3413 $('#top-link-block').fadeOut(duration); 3414 } 3415 }); 3416 3417 $('#top-link-block').click(function(event) { 3418 event.preventDefault(); 3419 $('html, body').animate({scrollTop: 0}, duration); 3420 return false; 3421 }); 3422 3423 /*Just this has to be replaced in top.ace*/ 3424 if($.cookie("logged-on") === "true") 3425 { 3426 $('.logout').removeClass('display-none'); 3427 $('.logout').addClass('display-inline-block'); 3428 } 3429 else 3430 { 3431 $('#mobileLogout').removeClass('display-inline-block'); 3432 $('#mobileLogout').addClass('display-none'); 3433 } 3434 3435 // Bind print events 3436 $("#access-toolbar > button[data-original-title=Print], #access-toolbar > button[title=Print]").click(function() { 3437 window.print(); 3438 return false; 3439 }); 3440}); 3441 3442var getRenditionPrintTypeExtensions = function() { 3443 return [ 3444 "exp", 3445 "risras", 3446 "err", 3447 "hrc", 3448 "hrcerr" 3449 ]; 3450} 3451// Don't forget to check the getCollectionExpression method inside search.js when updating the function below 3452var getRenditionPrintTypeQuery = function() { 3453 return "PrintType=(?\"." + getRenditionPrintTypeExtensions().join("\" OR ?\".") + "\")"; 3454}
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.