1(function($) { 2 jQuery.popupCampaign = function(options) { 3 var internal_template = [ 4 "<div id='popup_{{Id}}' class='mag-popup rounded {{popupClasses}}' aria-hidden='false'>", 5 '<div class="mag-popup-dialog container-fluid">', 6 '{{#DisplayCloseButton}}', 7 '<div class="mag-popup-close-wrapper">', 8 "<button type='button' class='close mag-popup-close' data-dismiss='modal'><span aria-hidden='true'>×</span><span class='sr-only'>Close</span></button>", 9 '</div>', 10 '{{/DisplayCloseButton}}', 11 '<div class="row">', 12 '<div class="nopadding {{grid_left_cell}}">', 13 '{{#resources}}', 14 '<div>', 15 '{{#isImage}}<div class="img-container {{img_rounding}}" style="background-image:url(/contents/assets/{{Path}})"><img src="/contents/assets/{{Path}}" class="mag-popup-img {{img_rounding}}" alt="{{Title}}"/></div>{{/isImage}}', 16 '{{#isVideo}}', 17 '<div class="embed-responsive embed-responsive-{{videoAspectRatio}}">', 18 '<video class="img-responsive centered" controls><source src="{{Path}}" type="video/mp4"></video>', 19 '</div>', 20 '{{/isVideo}}', 21 '{{#isIframe}}', 22 '<div class="embed-responsive embed-responsive-{{videoAspectRatio}} rounded-top">', 23 '<iframe class="embed-responsive-item" src="{{Path}}" allowfullscreen="true" allow="autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media"></iframe>', 24 '</div>', 25 '{{/isIframe}}', 26 '</div>', 27 '{{/resources}}', 28 '</div>', 29 '<div class="nopadding {{grid_right_cell}}">', 30 '<div class="mag-popup-content {{contentAlignment}}">', 31 '<h1 class="mag-popup-title heading-responsive">{{Title}}</h1>', 32 '{{#Text}}<div class="mag-popup-desc">{{{Text}}}</div>{{/Text}}', 33 '<button type="button" class="btn btn-primary btn-mag-popup">{{ButtonLabel}}</button>', 34 '</div>', 35 '</div>', 36 '</div>', 37 '</div>', 38 '</div>' 39 ].join(''); 40 41 var props = { 42 preview: false, 43 container: "body", 44 data: null, 45 template: internal_template, 46 track: false, 47 event_prefix: "popup", 48 track_activity_endpoint: "/popupcampaignactivity/track" 49 }; 50 51 var compSettings = $.extend(true, {}, props, options); 52 53 if (!compSettings.data) 54 return this; 55 56 function getTemplate(settings) { 57 Mustache.parse(settings.template); 58 return settings.template; 59 } 60 61 function prepareData(settings) { 62 function removeSpace(str) { 63 if (!str) return ""; 64 return str.replaceAll(" ", "").toLowerCase(); 65 } 66 var data = settings.data; 67 68 if (!data.Id) 69 data.Id = new Date().getTime(); 70 71 if (!settings.preview) 72 data.resources = JSON.parse(data.Media); 73 74 var aspectRatio = (data.MediaPosition != "Top") ? "4by3" : "16by9"; 75 var rounding = "rounded-top"; 76 77 if (data.MediaPosition == "Left") 78 rounding = "rounded-left"; 79 else if (data.MediaPosition == "Right") 80 rounding = "rounded-right"; 81 82 settings.data.popupClasses = "pos-" + removeSpace(settings.data.PopupPosition) + " size-" + removeSpace(settings.data.Size); 83 if (settings.preview) 84 settings.data.popupClasses += " mode-preview"; 85 86 data.contentAlignment = (data.ContentAlignment == "Middle") ? "center" : data.ContentAlignment.toLowerCase(); 87 data.isImage = function () { 88 return this.Type == "Image"; 89 }; 90 data.isVideo = function () { 91 return this.Type == "Video"; 92 }; 93 data.isIframe = function() { 94 return this.Type != "Image" && this.Type != "Video"; 95 }; 96 data.grid_left_cell = function() { 97 if (Array.isArray(this.resources) && this.resources.length > 0) { 98 if (this.MediaPosition == "Top") { 99 return "col-md-12"; 100 } else if (this.MediaPosition == "Left") { 101 return (this.Size=="Full Width")? "col-lg-2 col-sm-3" : "col-md-6"; 102 } else if (this.MediaPosition == "Right") { 103 return (this.Size == "Full Width") ? "col-lg-2 col-sm-3 col-sm-push-9 col-lg-push-10" : "col-md-6 col-md-push-6"; 104 } 105 } else { 106 return ""; 107 } 108 }; 109 data.grid_right_cell = function() { 110 var hasMedia = Array.isArray(this.resources) && this.resources.length > 0;
111 112 if (this.MediaPosition == "Top" || !hasMedia) { 113 return "col-md-12"; 114 } else if (this.MediaPosition == "Left") { 115 return (this.Size == "Full Width") ? "col-sm-9 col-lg-10" : "col-md-6"; 116 } else if (this.MediaPosition == "Right") { 117 return (this.Size == "Full Width") ? "col-sm-9 col-sm-pull-3 col-lg-10 col-lg-pull-2" : "col-md-6 col-md-pull-6"; 118 } 119 120 }; 121 data.videoAspectRatio = function () { 122 return aspectRatio; 123 } 124 data.img_rounding = function () { 125 return rounding; 126 } 127 return settings.data; 128 } 129 130 function destroy() { 131 var data = compSettings.data; 132 133 if (data.UseOverlay) 134 $('#popup_ol_{0}'.format(data.Id)).remove(); 135 136 getPopupElement().remove(); 137 } 138 139 function getPopupElement() { 140 return $("#popup_{0}".format(compSettings.data.Id)); 141 } 142 143 function trackActivity(action, callback) { 144 var camp = compSettings.data; 145 146 if (compSettings.track) { 147 REST2.exec({ 148 url: props.track_activity_endpoint, 149 data: { id: camp.Id, action: action, pageUrl: $.request().uri }, 150 callback: function(context) { 151 if (REST2.isSuccess(context) && callback) { 152 callback(camp); 153 } 154 } 155 }); 156 } else if (callback) 157 callback(camp); 158 } 159 160 function trackDocumentActivity(path, callback) { 161 var match = path.match(/\/sys\/document\/open\/([^?]+)/); 162 163 REST2.exec({ 164 url: "/sys/document/trackview?id=" + match[1], 165 callback: function(context) { 166 if (REST2.isSuccess(context) && callback) { 167 callback(); 168 } 169 } 170 }); 171 } 172 173 function buttonClickHandler() { 174 175 function execClick(popup) { 176 $("body").trigger(`${compSettings.event_prefix}:click`, popup); 177 if (popup.DontShowWhenClicked || popup.Frequency == "Every session") 178 $("body").trigger(`${compSettings.event_prefix}:dismissed`, popup); 179 if (popup.ButtonAction == "Load a new page") { 180 navigateUrl(popup.ButtonUrl, (popup.ButtonTarget == "New Window") ? "_blank" : "", {}); 181 } else if (popup.ButtonAction == "Close the pop-up") { 182 destroy(); 183 } else { 184 destroy(); 185 openPopupCampaignMessageBox({ message: popup.ThankYouMessage }); 186 } 187 } 188 189 trackActivity("click", execClick); 190 } 191 192 function openPopupCampaignMessageBox(options) { 193 var options = $.extend({ size: "sm" }, options); 194 195 var $modalContent = $("<div></div>"); 196 $("body").append($modalContent); 197 198 var $htmlMsgBox = $("<div></div>"); 199 $modalContent.append($htmlMsgBox); 200 201 if (options.message) { 202 var $p = $("<div></div>").html(options.message); 203 $htmlMsgBox.append($p); 204 } 205 206 return $modalContent.modalDialog({ 207 title: " ", 208 show: true, 209 backdrop: "static", 210 destroyOnClose: true, 211 size: options.size, 212 buttonsAlignment: "center", 213 buttons: { 214 "OK": function () { 215 $modalContent.modalDialog("hide"); 216 } 217 } 218 }); 219 220 }; 221 222 function closeBtnClickHandler() { 223 var popupCamp = compSettings.data; 224 $("body").trigger(`${compSettings.event_prefix}:close`, popupCamp); 225 226 if (popupCamp.DontShowWhenClosed) { 227 trackActivity("close", function (popup) { 228 $("body").trigger(`${compSettings.event_prefix}:dismissed`, popup); 229 }); 230 } else if (popupCamp.Frequency == "Every session") { 231 $("body").trigger(`${compSettings.event_prefix}:dismissed`, popupCamp); 232 } 233 destroy(); 234 } 235 236 function loadComponent(settings) { 237 $.getRestScript(function() { 238 $.requiresLib("mustache", function() { 239 var data = prepareData(settings); 240 241 //destroy the previous version 242 destroy(); 243 244 //get the template and render the popup 245 var template = getTemplate(settings); 246 var rendered = Mustache.render(template, data); 247 var $parent = $(settings.container); 248 $parent.append(rendered); 249 250 if (!settings.preview) { 251 var $popup = getPopupElement(); 252 $popup.find(".btn-mag-popup").click(buttonClickHandler); 253 $popup.find(".mag-popup-close").click(closeBtnClickHandler); 254 255 if (data.UseOverlay) { 256 $("body").append('<div id="popup_ol_{0}" class="modal-backdrop fade in"></div>'.format(data.Id)); 257 if (data.CloseWhenOverlayIsClicked) { 258 $("#popup_ol_{0}".format(data.Id)).click(closeBtnClickHandler); 259 } 260 } 261 262 if (settings.track) 263 trackActivity("view"); 264 265 var media = JSON.parse(settings.data.Media)[0]; 266 267 if (media && media.Type == "Video") 268 trackDocumentActivity(media.Path); 269 } 270 271 }); 272 }, 2); 273 } 274 275 loadComponent(compSettings); 276 }; 277 278 jQuery.popupManager = function(options) { 279 var props = { 280 cacheTimeout: 600000 281 }; 282 283 var compSettings = $.extend(true, {}, props, options); 284 285 function getActiveCampaigns(settings, dataLoaded) { 286 REST2.exec({ 287 url: "/popupcampaignactivity/getactivecampaigns", 288 callback: function(context) { 289 //track in storage 290 var popupData = { 291 createdOn: new Date(), 292 userId: __mag__system_variables.userId, 293 data: context.Result 294 }; 295 storePopupData(popupData); 296 297 //callback 298 if (dataLoaded) 299 dataLoaded(popupData.data); 300 } 301 }); 302 } 303 304 function retrieveActiveCampaigns(settings, dataLoaded) { 305 306 function isExpired(storageContext) { 307 var now = new Date(); 308 return (now - new Date(storageContext.createdOn)) > settings.cacheTimeout; 309 } 310 311 var dataContext = readPopupData(); 312 313 if (dataContext) { 314 if (dataContext.userId != __mag__system_variables.userId) { 315 getActiveCampaigns(settings, dataLoaded); 316 } 317 else if (isExpired(dataContext)) { 318 getActiveCampaigns(settings, dataLoaded); 319 } else { 320 dataLoaded(dataContext.data); 321 } 322 return; 323 } else { 324 getActiveCampaigns(settings, dataLoaded); 325 } 326 327 } 328 329 function readPopupData() { 330 var popupString = localStorage.getItem("mag__popups"); 331 if (popupString) { 332 return JSON.parse(popupString); 333 } 334 else 335 return null; 336 } 337 338 function storePopupData(data) { 339 localStorage.setItem("mag__popups", JSON.stringify(data)); 340 } 341 342 function displayPopups(settings) { 343 retrieveActiveCampaigns(settings, function(camps) { 344 if (!camps) return; 345 346 //logic to display the popups 347 $.each(camps, function(i, popup) { 348 if (popup.TargetPageUrl && window.location.href.toLowerCase().indexOf(popup.TargetPageUrl.toLowerCase()) < 0) 349 return true; 350 $.popupCampaign({ data: popup, track: true });
351 }); 352 }); 353 } 354 355 function popupDismissed(popup) { 356 //manually update the popups in login as mode 357 var dataContext = readPopupData(); 358 if (dataContext) { 359 var inx = findIndexOfObject(dataContext.data, "Id", popup.Id); 360 361 if (inx >= 0) { 362 dataContext.data.splice(inx, 1); 363 storePopupData(dataContext); 364 } 365 } 366 } 367 368 function loadComponent(settings) { 369 //exclude profile update page 370 try { 371 var path = $.request().path.toLowerCase(); 372 if (path == "/user/updateprofileinfo" || path == "//user/updateprofileinfo") { 373 return; 374 } 375 } catch (err) { 376 //nothing needs to be done. 377 } 378 379 $.getRestScript(function() { 380 displayPopups(settings); 381 382 //register for events 383 $("body").on("popup:dismissed", function(event,popup) { 384 if (__mag__system_variables && __mag__system_variables.impr) 385 popupDismissed(popup); 386 else 387 getActiveCampaigns(settings); 388 }); 389 390 $("body").on("popup:changed", function() { 391 getActiveCampaigns(settings, function() { 392 displayPopups(settings); 393 }); 394 }); 395 396 }, 2); 397 } 398 399 loadComponent(compSettings); 400 }; 401 402 jQuery.popupTrainingManager = function (options) { 403 var props = { 404 cacheTimeout: 600000 405 }; 406 407 var compSettings = $.extend(true, {}, props, options); 408 const STORAGE_KEY = 'mag_video_training'; 409 410 function getActiveCampaigns(settings, dataLoaded) { 411 REST2.exec({ 412 url: "/setup/home/gettrainingvideos", 413 callback: function (context) { 414 //track in storage 415 var popupData = { 416 createdOn: new Date(), 417 data: context.Result 418 }; 419 420 storePopupData(popupData); 421 422 //callback 423 if (dataLoaded) 424 dataLoaded(popupData.data); 425 } 426 }); 427 } 428 429 function retrieveActiveCampaigns(settings, dataLoaded) { 430 431 function isExpired(storageContext) { 432 var now = new Date(); 433 return (now - new Date(storageContext.createdOn)) > settings.cacheTimeout; 434 } 435 436 var dataContext = readPopupData(); 437 438 if (dataContext) { 439 if (isExpired(dataContext)) 440 getActiveCampaigns(settings, dataLoaded); 441 else 442 dataLoaded(dataContext.data); 443 444 return; 445 } else 446 getActiveCampaigns(settings, dataLoaded); 447 } 448 449 function readPopupTrackingData(scope) { 450 if (!scope) 451 scope = "localSorage"; 452 453 var storage = (scope == "localSorage") ? localStorage : sessionStorage; 454 var popupString = storage.getItem(`${STORAGE_KEY}_wis`); 455 456 if (popupString) 457 return JSON.parse(popupString); 458 else 459 return []; 460 } 461 462 function trackVideoVisited(videoId, scope) { 463 if (!scope) 464 scope = "localSorage"; 465 466 var items = readPopupTrackingData(scope); 467 468 if (items.indexOf(videoId) < 0) { 469 items.push(videoId); 470 var storage = (scope == "localSorage") ? localStorage : sessionStorage; 471 storage.setItem(`${STORAGE_KEY}_wis`, JSON.stringify(items)); 472 } 473 } 474 475 function isVideoVisited(videoId) { 476 let items = readPopupTrackingData(); 477 let isVisited = (items.indexOf(videoId) >= 0); 478 479 if (!isVisited) { 480 items = readPopupTrackingData('session'); 481 isVisited = (items.indexOf(videoId) >= 0); 482 } 483 484 return isVisited; 485 } 486 487 function readPopupData() { 488 var popupString = localStorage.getItem(STORAGE_KEY); 489 490 if (popupString) 491 return JSON.parse(popupString); 492 else 493 return null; 494 } 495 496 function storePopupData(data) { 497 localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); 498 } 499 500 function displayPopups(settings) { 501 retrieveActiveCampaigns(settings, function (camps) { 502 if (!camps) 503 return; 504 505 //logic to display the popups 506 $.each(camps, function (i, camp) { 507 if (camp.TargetUrl__c && window.location.href.toLowerCase().indexOf(camp.TargetUrl__c.toLowerCase()) < 0) 508 return true; 509 510 if (isVideoVisited(camp.Id)) 511 return true; 512 513 const videoLink = camp.VideoLink__c + "&badge=0&autopause=0player_id=0&app_id=58479"; 514 515 var popup = { 516 "Active": true, 517 "ButtonAction": "Close the pop-up", 518 "ButtonLabel": "Show me later", 519 "ButtonTarget": null, 520 "ButtonUrl": null, 521 "CloseWhenOverlayIsClicked": false, 522 "ContentAlignment": "Middle", 523 "DisplayCloseButton": true, 524 "DontShowWhenClicked": false, 525 "DontShowWhenClosed": true, 526 "Frequency": "Every Session", 527 "Id": camp.Id, 528 "Media": `[{\"Path\":\"${videoLink}
528\",\"Type\":\"Vimeo\",\"Order\":0}]`, 529 "MediaPosition": "Top", 530 "Name": "Coming Soon", 531 "PopupPosition": "Middle Center", 532 "PublishEndDate": "2025-02-10T00:00:00", 533 "PublishStartDate": "2025-02-05T00:00:00", 534 "Size": "Large", 535 "TargetPageUrl": camp.TargetUrl__c, 536 "Text": "You can always access this video again by clicking on 'Help on this Page'.", 537 "ThankYouMessage": null, 538 "Title": `Want to learn more about ${camp.Name}?`, 539 "UseOverlay": true, 540 }; 541 542 $.popupCampaign({ data: popup, track: false, event_prefix: "vidtraining" }); 543 wireUpVimeo(camp); 544 }); 545 }); 546 } 547 548 function wireUpVimeo(camp) { 549 $.loadScriptFile("https://player.vimeo.com/api/player.js", function () { 550 var $videoFrame = $(".mag-popup-dialog .embed-responsive-item"); 551 var iframe = ($videoFrame.length > 0) ? $videoFrame[0] : null; 552 553 if (iframe) { 554 var player = new Vimeo.Player(iframe); 555 player.on('play', function () { 556 REST2.exec({ 557 url: "/setup/home/tracktrainingvideo", 558 data: camp, 559 callback: function (context) { 560 if (REST2.isSuccess(context)) { 561 // no actions needed. 562 } 563 } 564 }); 565 }); 566 } 567 }); 568 } 569 570 function popupDismissed(popup, scope) { 571 572 trackVideoVisited(popup.Id, scope); 573 } 574 575 function loadComponent(settings) { 576 if ($systemInfo.role == "Host") 577 return; 578 579 //exclude profile update page 580 try { 581 var path = $.request().path.toLowerCase(); 582 583 if (path == "/user/updateprofileinfo" || path == "//user/updateprofileinfo") 584 return; 585 586 } catch (err) { 587 //nothing needs to be done. 588 } 589 590 $.getRestScript(function () { 591 displayPopups(settings); 592 593 //register for events 594 $("body").on("vidtraining:close", function (event, popup) { 595 if (popup.DontShowWhenClosed) 596 popupDismissed(popup); 597 else if (popup.Frequency == "Every Session") 598 popupDismissed(popup, "session"); 599 }); 600 601 $("body").on("vidtraining:click", function (event, popup) { 602 if (popup.DontShowWhenClicked) 603 popupDismissed(popup); 604 else if (popup.Frequency == "Every Session") 605 popupDismissed(popup, "session"); 606 }); 607 608 }, 2); 609 } 610 611 loadComponent(compSettings); 612 }; 613})(jQuery);
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.