1// Widget loader plugin to handle all widget loading via ajax needs 2var widgetLoader = (function($){ 3 4 // Possible events array to keep it consistant. 5 var events = { 6 rendered : 'widgetRendered', 7 fetching: 'widgetFetching', 8 preQueue: 'widgetQueued', 9 preRender: 'widgetPreRender' 10 }; 11 12 // Widget object to store all widget information. 13 var widgets = {}; 14 15 // Loader styles 16 var link = document.createElement('link'); 17 link.setAttribute('rel', 'stylesheet'); 18 link.setAttribute('type', 'text/css'); 19 link.setAttribute('href', '/modules/WidgetsManager/css/widgetLoader.css?1'); 20 document.getElementsByTagName('head')[0].appendChild(link); 21 22 // Check if we have intersection for this browser and set this value for our variable 23 var intersectionAllowed = (function(){ 24 return ('IntersectionObserver' in window); 25 })(); 26 27 var isBot = (function(){ 28 return (/bot|googlebot|crawler|spider|robot|crawling/i).test(navigator.userAgent); 29 })(); 30 31 // On Scroll Event Render all unrendered widgets and remove the scrolled listener 32 var userScrolled = false; 33 var scrolled = window.addEventListener('scroll', function(e){ 34 userScrolled = true; 35 window.removeEventListener('scroll',scrolled) 36 Object.keys(widgets).map(function(widget){ 37 if(!widgets[widget].rendered && !widgets[widget].speed != 'observer'){ 38 fetchWidget(widgets[widget].wid,widgets[widget].module); 39 } 40 }); 41 }); 42 43 // Widget intersection observer 44 var widgetObserver = ''; 45 if(intersectionAllowed){ 46 widgetObserver = new IntersectionObserver(function(entries, observer){ 47 entries.forEach(function(entry){ 48 if(entry.isIntersecting){ 49 var widget = widgetModuleID(entry.target.id); // get widget from id 50 widgetObserver.unobserve(entry.target); // Remove Observer since we have rendered. 51 fetchWidget(widget.wid,widget.moduleName); // Fetch widget 52 } 53 }); 54 },{rootMargin: '0px',threshold:0.01}); 55 }; 56 57 // Render Function used to add widget to render Queue or immidiatly render. 58 function renderWidget(_wid,_module,speed){ 59 widgets[_wid] = { 60 wid: _wid, 61 module: _module, 62 speed: speed == 'delayed' ? 'delayed' : 'immidiate', 63 rendered: false 64 }; 65 triggerEvent(events.preQueue, widgets[_wid]); // Before adding to render quque/rendering pass widget to event in case themers want to alter loading speed 66 // If widget should load immidiatly or intersection is not available for browser load immidiatly 67 if(widgets[_wid].speed === 'immidiate' || !intersectionAllowed || (userScrolled && widgets[_wid].speed !== 'observer')){ 68 fetchWidget(_wid,_module); 69 } else { 70 addToObserver(_wid,_module); 71 } 72 }; 73 74 // Function to fetch html contents of widget via ajax 75 function fetchWidget(_wid,_module){ 76 if(widgets[_wid].rendering){ 77 return; 78 } 79 widgets[_wid].rendering = true; 80 triggerEvent(events.fetching, widgets[_wid]); 81 $.ajax({
82 url: '/WidgetsManager/getWidgetContents', 83 dataType: 'html', 84 data: {wid:_wid}, 85 type: 'post', 86 success: function(data){ 87 // Set response into widget.html and pass this for prerender and use the html for replacing on screen 88 widgets[_wid].html = data; 89 triggerEvent(events.preRender, widgets[_wid]); 90 triggerEvent(events.preRender+'_'+widgets[_wid].wid);// Single Widget PreRender Event 91 triggerEvent(events.preRender+'_'+widgets[_wid].module);// Single Widget module PreRender Event 92 $('#' + _module + '-0-' + _wid + ' .widget-loading').replaceWith(widgets[_wid].html); 93 widgets[_wid].rendered = true; 94 // Clean up variable after render free up some memory 95 widgets[_wid].html = ''; 96 triggerEvent(events.rendered, widgets[_wid]); 97 triggerEvent(events.rendered+'_'+widgets[_wid].wid);// Single Widget Render Event 98 triggerEvent(events.rendered+'_'+widgets[_wid].module);// Single Widget module Render Event 99 } 100 }) 101 }; 102 103 // Helper add to observer function 104 function addToObserver(wid,module){ 105 widgetObserver.observe($('#'+module+'-0-'+wid)[0]); 106 }; 107 108 // Helper function returns wid and module object 109 function widgetModuleID(target){ 110 return { 111 wid: target.match(/[1-9][0-9]*/g)[0], 112 moduleName: target.match(/[a-zA-Z\_]*/g)[0] 113 } 114 }; 115 116 // Helper event dispatcher for all potential events and its data. 117 function triggerEvent(event, evData){ 118 var event = new CustomEvent(event); 119 event.widget = evData; 120 document.dispatchEvent(event); 121 }; 122 123 //if is bot run rendered event for widgets to trigger js 124 if(isBot){ 125 window.addEventListener('DOMContentLoaded', function(){ 126 $('.block.widget').each(function(){ 127 var widget = widgetModuleID($(this).attr('id')); 128 triggerEvent(events.rendered,{wid:widget.wid,module:widget.moduleName}) 129 }) 130 }); 131 } 132 133 // On specific widget Render Helper Method 134 function onSingleWidget(el,callback,event){ 135 if(el.length>1){ 136 console.log('More then 1 element passsed'); 137 return; 138 } 139 if(!callback){ 140 console.log("Callback is required"); 141 return; 142 } 143 if(typeof(callback) != 'function'){ 144 console.log('Callback is not a function. Passed '+typeof(callback)+' instead.'); 145 return; 146 } 147 try{ 148 var wid = widgetModuleID(el.attr('id')).wid; 149 } catch(e){ 150 console.log('Passed element is not a widget.'); 151 return; 152 } 153 if(!widgets[wid]){ 154 console.log('Passed Widget is not loaded by ajax.'); 155 return; 156 } 157 if(widgets[wid].rendered === true){ 158 callback(widgets[wid]); 159 event === events.preRender && console.log('The preRender event has alredy happened.'); 160 } else { 161 document.addEventListener(event + '_' + wid, function(){ 162 callback(widgets[wid]); 163 }); 164 }; 165 }; 166 167 // JQUERY EXTEND METHODS 168 // Extending for render and pre render events. Return this for function chaining. 169 $.fn.onWidgetRender = function(callback){ 170 onSingleWidget($(this),callback,events.rendered); 171 return this; 172 }; 173 174 $.fn.onWidgetPreRender = function(callback){ 175 onSingleWidget($(this),callback,events.preRender); 176 return this; 177 }; 178 179 // Return api if you need to expose additional functions/variables simple add as: exposedFunctionName: functionInFile 180 return{ 181 widgets: widgets, 182 renderWidget: renderWidget, 183 triggerEvent: triggerEvent // exposing trigger event from widgetLoader 184 }; 185})(jQuery); 186
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.