1/* 2 * Inviation Manager Independent Version 3 */ 4 5 6window.addEventListener( "load", imSetup); 7 8 9/* 10 * First function called 11 */ 12function imSetup() { 13 "use strict"; 14 15 // Document all main variables 16 17 var debugMode, // If true, log console info 18 surveyDB, // JSON var of data stored in im.json 19 surveyScope, // Equals 1 if survey page and 2 is survey site 20 dbURL, // location of im.xml, example "/content/dam/canada/json/im.json" 21 Adobe, // Equals to yes if Adobe analytics is set 22 23 // The following variables are used for debugging with query string 24 overrideScope = false, // Query parameter sets this to a text value to force the scope (page or site) 25 overrideStart = false, // Query parameter sets this to true to ignore the start date of surveys 26 overrideID, // Query parameter sets this to an Id value for a specific survey 27 28 29 /* 30 * Name of session storage values 31 */ 32 storageNames = { 33 34 session: "im-settings" 35 }; 36 37 //var dbURL = dbUrlFromJson(); 38 39 try { 40 41 // download the dbURL path 42 if (!dbURL) 43 { 44 dbUrlFromJson(); 45 // asynchronous call 46 } 47 else { 48 49 mainPart1(); 50 } 51 52 } catch (e) { 53 return false; 54 } 55 56 57 /* 58 * main function Part One - setup the survey data 59 */ 60 function mainPart1 () { 61 if (!dbURL) { 62 return; 63 } 64 // Enable console logging if debug mode is turned on 65 debugMode = checkEnableDebugMode(); 66 consoleLog("Start"); 67 68 // Check if any special parameters are used for testing reasons 69 checkTestParams(); 70 consoleLog("Check Test Params"); 71 72 /* In order to handle the proper functioning of IM for websites 73 * that have IM installed on different subdomains from different servers, 74 * survey serving is now conditioned by the presence of the cookie 'lastDateIMShown' and not 75 * by the localstorage item 'lastDateIMShown' 76 * If there is no cookie "lastDateIMShown", the user has not seen a survey 77 */ 78 if ( !getCookie('lastDateIMShown')) { 79 consoleLog("lastDateIMShown === null"); 80 81 // Check if DB is already in session storage 82 surveyDB = JSON.parse(sessionStorage.getItem(storageNames.session)); 83 84 // Download the DB if it is not already stored 85 if (!surveyDB) { 86 consoleLog("downloadSurveyDB"); 87 downloadSurveyDB(); 88 // Asynchronous call, do not execute code here 89 } 90 else { 91 /* To take into consideration the surveys that were visible prior the 'cookie handling' implementation 92 * the script has to check the localstorage for 'lastDateIMShown' and setup the cookie with that date. 93 * The expiration of the cookie should be the sum of lastDateIMShown and the survey setting duration-delay value 94 */ 95 if(localStorage.getItem('lastDateIMShown')){ 96 var cookieName = 'lastDateIMShown', 97 maxNbDaysIMPersist = new Date(localStorage.getItem('lastDateIMShown')); 98 maxNbDaysIMPersist.setDate(maxNbDaysIMPersist.getDate() + surveyDB.settings["duration-delay"]); 99 setCookie(cookieName,localStorage.getItem('lastDateIMShown'),maxNbDaysIMPersist, removeSubdomain(window.location.href.toLowerCase())); 100 }else{ 101 mainPart2(); 102 } 103 } 104 } 105 // Case when the user has already seen an invitation 106 else { 107 consoleLog("User has seen an invitation already"); 108 downloadSurveyDB(); 109 // Asynchronous call may have been made, do not execute code here 110 /* If shown survey was served from another server, make sure the localstorage item 'lastDateIMShown' is set 111 * with the value from 'lastDateIMShown' cookie. 112 */ 113 localStorage.setItem('lastDateIMShown', new Date(getCookie('lastDateIMShown'))); 114 115 } 116 } 117 118 119 /* 120 * main function Part two - select the survey to display 121 */ 122 function mainPart2() { 123 // Make sure the surveyDB object is set, it could not have been defined if 124 // localStorage was not defined and the json is unfound on the server 125 if (!surveyDB || !surveyDB.settings) 126 return; 127 128 if (getCookie('lastDateIMShown')) { 129 var lastDateIMShown = new Date(getCookie('lastDateIMShown')); 130 // If storage delay is expired, remove 'lastDateIMShown' from cookie and localstorage 131 if (isStorageExpired(lastDateIMShown)) { 132 document.cookie = "lastDateIMShown=;expires=Thu, 01 Jan 1970 00:00:00 GMT; Secure;domain=" + removeSubdomain(window.location.href.toLowerCase()) + ";path=/"; 133 localStorage.removeItem( "lastDateIMShown" ); 134 } 135 else{ 136 return; 137 } 138 } 139 140 141 // At this point, we don't know if it the was just downloaded or if it was 142 // retrieved from session storage 143 144 // if the DB doesn't have a scopeHat, then we need to decide on which scope hat to give 145 if (!surveyDB.settings.scopeHat) { 146 firstTimeSetup(); 147 } 148 149 // Check if we need to override the scope hat 150 // This is needed since firstTimeSetup won't run if this is not the first page of the visit 151 if (overrideScope) { 152 surveyDB.settings.scopeHat = overrideScope; 153 } 154 155 surveyScope = surveyDB.settings.scopeHat; 156 consoleLog("Scope hat = " + surveyScope + ", " + surveyDB.surveys.length + " potential surveys, removing surveys outside of date range"); 157 158 // Delete all surveys that are outside of working dates 159 var list = surveyDB.surveys; 160 for (var i = 0; i < list.length; i++) { 161 var n = new Date().getTime(); 162 var end_time = new Date(list[i]["end-on"]).getTime(); 163 if (n < new Date(list[i]["start-on"]).getTime() || 164 n >= end_time) { 165 166 // If overriding start date and still before end date then don't delete this survey 167 if (overrideStart && n < end_time) { 168 continue; 169 } 170 171 // Splice removes the element from the array 172 list.splice(i,1); 173 174 //decrement i since the next record has moved to replace the current record 175 i--; 176 } 177 } 178 179 consoleLog(list.length + " potential surveys, removing surveys based on targeting"); 180 181 surveyDB.surveys = list; 182 183 // save the DB to session storage 184 sessionStorage.setItem(storageNames.session, JSON.stringify(surveyDB)); 185 186 consoleLog("Checking whitelist"); 187 188 // Check if url on whitelist 189 var list = getObjArr(surveyDB.settings.whitelist), 190 a = document.location, 191 //h = a.hostname + ":8080" + a.pathname, 192 h = a.host + a.pathname, 193 didMatch = false;
194 195 if ( !list ) { 196 return false; 197 } 198 199 for (var i = 0; i < list.length; i++) { 200 var b = new RegExp(list[i].url, "i"); 201 if (b.test(h)) 202 didMatch = true; 203 } 204 205 if ( !didMatch ) { 206 return false; 207 } 208 209 consoleLog("Checking blacklist"); 210 211 // Check if url is on blacklist 212 var list = getObjArr(surveyDB.settings.blacklist), 213 a = document.location, 214 //h = a.hostname + a.pathname; 215 h = a.host + a.pathname; 216 217 for (var i = 0; i < list.length; i++) { 218 var l = list[i].url; 219 if (l !== undefined && l.length !== undefined) { 220 if (l.toLowerCase() == h.toLowerCase()) { 221 return false; 222 } 223 } 224 } 225 226 consoleLog("Removing surveys based on page attributes"); 227 228 // Make a deep copy of the survey DB before we remove the applicable surveys 229 // This is needed because getPageAttributeMatches will delete any survey that matches from the surveyDB list 230 var cpySurveys = JSON.parse(JSON.stringify(surveyDB.surveys)); 231 232 // b will be the index of a survey in cpySurveys that was chosen otherwise 233 // it will be undefined if no survey was selected 234 var b = getWeightedRandom(getPageAttributeMatches()); 235 236 if ( b ) { 237 238 for (var j = 0; j < cpySurveys.length; j++) { 239 240 if(cpySurveys[j].id === b){ 241 var selectedSurveyIndex = j; 242 break; 243 244 } 245 } 246 consoleLog("Select survey " + cpySurveys[selectedSurveyIndex].name); 247 // Popup the survey 248 invite(cpySurveys[selectedSurveyIndex]); 249 250 //set lastDateIMShown in localStorage and cookie with the date the visitor was invited 251 if(!getCookie('lastDateIMShown') && !(/[?&]im_nocookiecheck=1/i.test(document.location.search))){ 252 //set a cookie with the domain name and the date visitor was invited 253 var cookieName = 'lastDateIMShown'; 254 var maxNbDaysIMPersist = new Date(), 255 lastDateIMShown = new Date(); 256 maxNbDaysIMPersist.setDate(maxNbDaysIMPersist.getDate() + surveyDB.settings["duration-delay"]);
257 //set the date visitor was invited in localstorage 258 localStorage.setItem('lastDateIMShown', lastDateIMShown); 259 260 setCookie(cookieName,lastDateIMShown,maxNbDaysIMPersist, removeSubdomain(window.location.href.toLowerCase())) 261 } 262 } 263 else { 264 consoleLog("No survey selected, " + surveyDB.surveys.length + " surveys remain in session storage"); 265 //save the updated DB to session storage 266 //the DB must be saved here since we need to remove surveys that were applicable on this page so we don't test for them again in the visit 267 sessionStorage.setItem(storageNames.session, JSON.stringify(surveyDB)); 268 } 269 270 } 271 272 /* 273 * Check if debug mode is enabled 274 */ 275 function checkEnableDebugMode() { 276 277 //Set the local storage token to remember to log console info 278 if (/[?&]logim=(true|1)/i.test(document.location.search)) 279 localStorage.setItem('imlog', 1); 280 281 if (/[?&]logim=(false|0)/i.test(document.location.search)) 282 localStorage.removeItem('imlog'); 283 284 return (localStorage.getItem('imlog') == 1); 285 } 286 287 288 /* 289 * Log console data if debug mode is enabled 290 */ 291 function consoleLog (val) { 292 if (debugMode) { 293 console.log("Invitation Mgr: " + val); 294 } 295 } 296 297 298 /* 299 * Check if any special parameters are used for testing reasons 300 */ 301 function checkTestParams() { 302 // Process query parameters 303 304 // Case of cookies 305 if (/[?&]im_nocookiecheck=1/i.test(document.location.search)) { 306 consoleLog("Treat visitor as new visitor (deleting locally stored data)"); 307 308 // Delete this cookie 309 localStorage.removeItem( "lastDateIMShown" ); 310 311 } 312 313 // Case of scope (page or site) 314 if ( (/[?&]im_scope=page/i.test(document.location.search))) 315 overrideScope = "Page"; 316 else if ( (/[?&]im_scope=site/i.test(document.location.search))) 317 overrideScope = "Entire site"; 318 319 // Case of date 320 if ( (/[?&]im_nodatecheck=1/i.test(document.location.search))) 321 overrideStart = true; 322 323 // Case of Survey Id 324 var b = /[?&]im_surveyid=([^?&]+)/.exec(document.location.search); 325 if (b !== null ) 326 overrideID = b[1]; 327 328 } 329 330 331 /* 332 * Load the survey from json file to storage 333 */ 334 function downloadSurveyDB() { 335 336 $.getJSON( 337 dbURL, 338 function() { 339 consoleLog("Get Json File is Successful"); 340 } ) 341 .done( function(result) { 342 surveyDB = JSON.parse(JSON.stringify(result)); 343 mainPart2(); 344 } ) 345 .fail( function() { 346 consoleLog( "Fail to get JSON File" ); 347 } ) 348 .always( function() { 349 consoleLog( "JSON file Complete" ); 350 } ); 351 352 } 353 354 355 /* 356 * Take a date object as parameter and test if the storage date is expired 357 */ 358 function isStorageExpired(storageDate) { 359 var now = new Date(); 360 var maxNbDaysIMPersist = surveyDB.settings["duration-delay"]; 361 if ( ( ( now - storageDate ) <= ( maxNbDaysIMPersist * 86400000 ) ) || !storageDate ) { 362 return false; 363 364 } 365 return true; 366 } 367 368 369 /* 370 * First time invitation setup. We need to allocate scope hat and remove 371 * surveys that don't match the scope hat 372 */ 373 function firstTimeSetup() { 374 375 // tmpSurveyDB is where we will copy all the wanted data from surveyDB into 376 // this removes non applicable scope surveys 377 var tmpSurveyDB = {settings : {}, surveys : []}; 378 379 consoleLog("Rolling probability for scope hat"); 380 381 if (overrideScope) 382 { 383 surveyScope = overrideScope; // Page or Site 384 consoleLog("surveyScope = overrideScope = " + overrideScope); 385 } 386 else 387 { 388 389 surveyScope = getWeightedRandom({"Page":surveyDB.settings["page-probability"], "Entire site":surveyDB.settings["site-probability"]}); 390 391 consoleLog("surveyScope = getWeightedRandom = " + surveyScope); 392 } 393 394 // get an object array of all surveys in the DB 395 var list = getObjArr (surveyDB.surveys); 396 397 consoleLog(list.length + " potential surveys, removing surveys that don't match scope hat"); 398 399 for (var i = 0; i < list.length; i++) { 400 401 // Get only surveys that apply to this scope 402 if (list[i].type == surveyScope) { 403 404 // Copy good surveys to tmpSurveyDB 405 tmpSurveyDB.surveys[tmpSurveyDB.surveys.length] = list[i]; 406 407 } 408 } 409 410 // Put all the needed settings into tmpSurveyDB 411 tmpSurveyDB.settings["page-probability"] = surveyDB.settings["page-probability"]; 412 tmpSurveyDB.settings["site-probability"] = surveyDB.settings["site-probability"]; 413 tmpSurveyDB.settings.scopeHat = surveyScope; 414 tmpSurveyDB.settings.whitelist = surveyDB.settings.whitelist; 415 tmpSurveyDB.settings.blacklist = surveyDB.settings.blacklist; 416 tmpSurveyDB.settings["duration-delay"] = surveyDB.settings["duration-delay"]; 417
418 //set surveyDB to tmpSurveyDB so we can be sure that surveyDB is the good variable 419 surveyDB = tmpSurveyDB; 420 421 } 422 423 424 /* 425 * Given a JSON array of values and probabilities, output the weighted random selection. 426 * For example {coffee: 0.20, tea: 0.80} 427 * Output nothing if no selection is made (I.E. undefined) 428 */ 429 function getWeightedRandom(spec) { 430 431 var i, sum =0, r = Math.random(); 432 for (i in spec) { 433 434 // be sure to never select something with 0% probability, 435 // since Math.random() can be 0 436 if (spec[i] === 0){ 437 continue; 438 } 439 440 sum += parseFloat(spec[i]); //Number(spec[i]); 441 if (r <= sum) 442 return i; 443 } 444 445 } 446 447 /* 448 * return an object array containing the given parameter. 449 * This allows us to loop through the object array whether there are 0, 1 or more objects in the array 450 */ 451 function getObjArr(o){ 452 453 if (!o) { 454 return []; 455 } 456 else if (Array.isArray(o)) { 457 return o; 458 } 459 else { 460 return [o]; 461 } 462 463 } 464 465 466 /* 467 * Return a list of valid surveys based on page or site 468 */ 469 function getPageAttributeMatches() { 470 471 // Return list of valid surveys based on page / site and check if override survey id needed 472 473 // Remove surveys that are valid from the surveyDB array so that when we save it, 474 // those ones are removed and not tested on future pages in the visit 475 476 var surveySubList = {}; 477 //var url = document.location.hostname + document.location.pathname; 478 var url = document.location.host + document.location.pathname; 479 var count = 0; 480 481 for (var i = 0; i < surveyDB.surveys.length; i++) { 482 483 var survey_i = surveyDB.surveys[i]; 484 485 if (overrideID) { 486 487 // Skip this loop's logic if it's not the desired survey, 488 // therefore there's no chance it will be selected 489 if (survey_i.id !== overrideID){ 490 491 continue; 492 } 493 494 // If it is the desired survey, set it's probability to 100%. 495 // Note that the desired survey must still be applicable on this page 496 // so the logic in the swtich statement still must execute meet the conditions 497 survey_i.probability = 100; 498 } 499 500 switch(survey_i.type) { 501 502 case "Entire site": 503 504 // Get an object array of the sites to run the survey on 505 var sublist = getObjArr(survey_i["survey-urls"]); 506 507 for (var c = 0; c < sublist.length; c++) { 508 509 //convert the value for the site into RegExp non-case sensitive 510 var b = new RegExp(sublist[c].site, "i"); 511 512 //if the url matches the regEx 513 if (b.test(url)) { 514 515 // Store this survey's id and probability in the new object 516 // (this object is later fed to getWeightedRandom) 517 518 // Convert site survey probability into rate since it is 519 // between 0 and Visitor Allocation for site wide type 520 521 surveySubList[survey_i.id] = 522 survey_i.probability * surveyDB.settings["site-probability"]; 523 524 // Keep track of the number of surveys that apply so we can 525 // console log it later 526 count++; 527 528 // Remove this survey from the DB, since we won't test for it on future pages 529 surveyDB.surveys.splice(i,1); 530 531 // Decrement i since the next record has moved to replace the current record 532 i--; 533 } 534 } 535 536 break; 537 538 539 case "Page": 540 541 var sublist = getObjArr(survey_i["survey-urls"]); 542 543 var wLocation = window.location.href.toLowerCase(); 544 545 for (var c = 0; c < sublist.length; c++) { 546 547 if (wLocation.indexOf(sublist[c].url.toLowerCase()) !== -1 && i>=0) { 548 surveySubList[survey_i.id] = survey_i.probability * surveyDB.settings["page-probability"]; 549 count++; 550 551 // Remove the eligible survey from the DB, since we won't test for it on future pages 552 surveyDB.surveys.splice(i,1); 553 554 // Decrement i since the next record has moved to replace the current record 555 i--; 556 } 557 } 558 559 break; 560 } 561 } 562 563 consoleLog(count + " potential surveys, selecting a survey"); 564 565 return surveySubList; 566 } 567 568 569 /* 570 * Display the popup given the survey parameters 571 */ 572 function invite(survey) { 573 var referrerPath = encodeURIComponent(window.location.pathname),
574 surveyLink = survey["link-" + wb_im.lang], 575 delimiter = "?", 576 popupInput; 577 578 if ( surveyLink.includes( "?" ) ) { 579 delimiter = "&"; 580 } 581 if (Adobe.toLowerCase() === "yes") 582 { 583 popupInput = "<input type='hidden' name='popupName' value='" + survey["name"] + "'>"; 584 } 585 else 586 { 587 popupInput = ""; 588 } 589 590 var html = 591 "<aside id='gc-im-popup' class='asideBody gc-im-wb-overlay gc-im-modal-content gc-im-overlay-def gc-im-wb-popup-mid shadow' tabindex='0' >" + 592 "<header class='gc-im-modal-header'>" + 593 "<div class='gc-im-modal-title'>" + 594 "<div class='gc-im-modal-title-fix1'>" + survey["title-" + wb_im.lang] + "</div>" + 595 "<div class='gc-im-modal-title-fix2'>" + "<button id='close-im' type='button' class='gc-im-overlaydef closeIcon zoomX' aria-label='Close' >×</button>" + 596 "</div>" + 597 "<div class='clearfix'></div>" + 598 "</div>" + // for the close icon 599 "</header>" + 600 "<div class='gc-im-modal-body'>" + 601 survey["body-" + wb_im.lang] + 602 "<ul class='list-inline mrgn-sm'>" + 603 "<li class='mrgn-sm marginBottom-yes'><a id='survey-yes' class='gc-im-btn gc-im-btn-primary' href='" + survey["link-" + wb_im.lang] + delimiter + "ref=" + referrerPath + "' target='_blank' referrer-policy='unsafe-url'>" + survey["yes-" + wb_im.lang] + "</a></li> " + 604 "<li class='mrgn-sm marginBottom-no'><button id='survey-no' class='gc-im-btn gc-im-btn-secondary survey-close'>" + survey["no-" + wb_im.lang] + "</button></li>" + 605 "</ul>" + 606 popupInput + 607 "</div>" + 608 "<div class='gc-im-modal-footer hidden'>" + 609 610 "</div>" + 611 "</aside>", 612 613 $html = $( html ), 614 $userFocus = false, 615 overlayIsClosing, 616 focusFlag; 617 618 // Close the overlay if any of its links/buttons get clicked or if the escape key gets pressed. 619 $html.bind( "click vclick mouseup keydown", function( e ) { 620 // Proceed if any of the overlay's links or buttons get clicked (including middle mouse clicks) 621 // or if the escape key gets pressed within the overlay. 622 if ( 623 ( ( e.type === "click" || e.type === "vclick" ) && e.which === 1 && $( e.target ).closest( "a, button", this ).length ) // Clicked/Tapped a link/button. 624 || 625 ( e.type === "mouseup" && e.which === 2 && $( e.target ).closest( "a", this ).length ) // Middle-clicked a link. 626 || 627 ( ( e.type === "keydown" ) && ( e.which === 27 ) ) // Pressed escape key. 628 ) { 629 630 631 // add to remove added classes to overlay when closing 632 $html.removeClass( "open" ); 633 $("#first-focus").remove(); 634 $( "#wb-info" ).removeClass( "im-mrgn" ); 635 636 // Set a flag to indicate the overlay is closing. 637 // Needed to prevent IE11 (possibly also IE8-10/Edge) from failing to return 638 // user focus when closing the overlay (due to a separate focusin event triggering 639 // too quickly and clearing the user focus variable before it's needed). 640 overlayIsClosing = 1; 641 642 // Hide the overlay immediately. 643 $( this ).hide(); 644 645 // Remove the overlay shortly afterwards. 646 // This is being done to prevent problems when the yes link is middle-clicked. If the overlay were to be immediately removed, middle-clicking the yes link would remove the overlay without opening the link in a new tab/window. To avoid that issue, the overlay is now getting immediately hidden, then removed a short time later. 647 setTimeout( function() { $html.empty() }, 1000 ); 648 649 // Remove this event handler. 650 $( this ).off(); 651 } 652 653 // if Tab in the NO button then focus will be triggerred outside of the popup 654 if ( ( e.type === "keydown" ) && ( e.which === 9 ) ) // Pressed the tab key. 655 { 656 if (e.target.id === "survey-no") 657 { 658 setTimeout( function() { 659 $("#wb-tphp").trigger("focus"); 660 },1000); 661 } 662 } 663 664 // if shift-Tab in the close button then focus will be triggerred outside of the popup 665 if ( ( e.type === "keydown" ) && ( e.which === 9 ) && (e.which === 16)) // Pressed the tab key and shift key 666 { 667 if (e.target.id === "close-im") 668 { 669 setTimeout( function() { 670 $("#wb-tphp").trigger("focus"); 671 },1000); 672 } 673 } 674 675 } ); 676 677 678 // Insert the overlay directly before the <main> element. 679 $( "main" ).before( $html ); 680 681 // Since jQuery fix will sanitize the target attribute, here is a quick solution to add it back right after the IM html popup is inserted 682 $("#survey-yes").attr("target", "_blank"); 683 684 // Inset the "Skip to Invitation Manager Popup" link before the <main> element. 685 if (wb_im.lang === "fr") 686 { 687 $( "#wb-tphp" ).prepend("<li id='first-focus' class='wb-slc'>" + 688 "<a class='wb-sl' href='#gc-im-popup'>Passer au Gestionnaire des Invitations</a></li> "); 689 } 690 else { 691 $( "#wb-tphp" ).prepend("<li id='first-focus' class='wb-slc'>" + 692 "<a class='wb-sl' href='#gc-im-popup'>Skip to Invitation Manager Popup</a></li> "); 693 } 694 695 // trigger the init and open event of the overlay 696 $( "#gc-im-popup" ).trigger( "wb-init.gc-im-wb-overlay" ); 697 $( "#gc-im-popup" ).trigger( "open.gc-im-wb-overlay" ); 698 699 // add for Adobe tracking 700 if (!$html.is(":hidden") && Adobe.toLowerCase() === "yes") 701 { 702 var popUpName = $("input[name='popupName']").val(); 703 704 _satellite.setVar('jsPopupName', popUpName); 705 //direct call rule 706 _satellite.track('popUpImpression'); 707 708 } 709 710 // Correct popup positionning on load, on resize an on Y scroll if necessary 711 $( window ).on( "resize scroll", function() { 712 713 714 // Equals to popup default bottom value in CSS 715 var bottomY = 25; 716 var $footer = $( "#wb-info" ); 717 718 if (!$html.is(":hidden")) 719 { 720 // Add some white space over the footer for the popup to sit 721 $footer.addClass( "im-mrgn" ); 722 } 723 else{ 724 $footer.removeClass( "im-mrgn" ); 725 } 726 727 if ( $( window ).scrollTop() >= $( document ).outerHeight() - $( window ).outerHeight() - $footer.outerHeight() ) { 728 $html.css( { 729 bottom: ( $footer.outerHeight() - ( $( document ).outerHeight() - $( window ).outerHeight() - $( window ).scrollTop() ) + bottomY ) 730 } ); 731 } else { 732 $html.css( { 733 bottom: bottomY 734 } ); 735 } 736 } ); 737 738 739 } 740 741 /* 742 * get the dbURL path from the config.json file 743 */ 744 function dbUrlFromJson() { 745 // find the path of the current javascript file "InvitationManager.js" 746 var scripts = document.getElementsByTagName("script"), 747 i = 0, 748 path = ""; 749 while (i < scripts.length) 750 { 751 var src = scripts[i].src; 752 if (src.indexOf("InvitationManager.js") > -1) 753 {
754 path = src.substring(0,src.lastIndexOf("/")+1); 755 break; 756 } 757 i++; 758 } 759 760 /* window.imConfigPath stores the path of the config.JSON file. 761 * if not defined, the script will check for config.JSON in the same directory where InvitationManger.js is located 762 */ 763 if (window.imConfigPath) 764 { 765 path = window.imConfigPath; 766 } 767 768 // get the config.json file 769 $.getJSON( 770 path + "config.JSON", 771 //"/invitation-manager/config.JSON", 772 function() { 773 consoleLog("Get Config File Path is Successful"); 774 }) 775 .done( function (result) { 776 var myConfig = JSON.parse( JSON.stringify( result ) );; 777 dbURL = myConfig.dbURL; 778 Adobe = myConfig.Adobe; 779 if (dbURL) { 780 mainPart1(); 781 } 782 else { 783 return; 784 } 785 }) 786 .fail( function() { 787 consoleLog("Get Config File Path Failed"); 788 }) 789 .always( function() { 790 consoleLog("Get Config File Path is Completed"); 791 }); 792 } 793 794 /** 795 * Return the domain name without the subdomain. 796 * @param {string} url The domain url to be cleaned 797 * @return {string} url without the subdomain; 798 */ 799 function removeSubdomain (url) { 800 const urlSegments = new URL(url).hostname.split('.') 801 // consider domains names having .gc or .qc before the domain name suffix 802 var arrIndex = ['gc', 'qc'].indexOf(urlSegments.slice(-2)[0]) >= 0 ?3:2; 803 return urlSegments.slice(0).slice(-(arrIndex)).join('.') 804 } 805 806 /** 807 * Return the cookie value for a specific cookie. 808 * @param {string} name cookie name 809 * @return {string} cookie value 810 */ 811 function getCookie(name){ 812 if (document.cookie.split(';').some((item) => item.trim().startsWith(name+'='))) { 813 return document.cookie.split('; ').find(row => row.startsWith(name.trim())).split('=')[1] 814 } 815 return false ; 816 } 817 818 /** 819 * Set a cookie. 820 * @param {string} cName cookie name 821 * @param {Date} cValue cookie value 822 * @param {Date} cExpDate cookie expiration date 823 * @param {string} cDomain cookie domain 824 */ 825 function setCookie(cName,cValue,cExpDate,cDomain){ 826 document.cookie = cName +"=" + cValue + ";expires=" + cExpDate 827 + ";domain=" + cDomain + ";Secure;path=/"; 828 } 829}
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.