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