PageSourceSearch

https://partner.callcabinet.com/_assets/scripts/components/popup-campaign.js

js callcabinet.com collected 2026-09-25 14:19:31 UTC 17,898 bytes, 613 lines download raw bytes

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'>&times;</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.