1/** 2 * Helper functions 3 */ 4 5define(function () { 6 'use strict'; 7 8 /** 9 * Returns a function, that, as long as it continues to be invoked, will not 10 * be triggered. The function will be called after it stops being called for 11 * N milliseconds. If `immediate` is passed, trigger the function on the 12 * leading edge, instead of the trailing. 13 * @param {Function} func 14 * @param {int} wait 15 * @param {bool} immediate 16 * @returns {Function} 17 */ 18 function deBounce (func, wait, immediate) { 19 var timeout; 20 return function () { 21 var context = this; 22 var args = arguments; 23 var later = function() { 24 timeout = null; 25 if (!immediate) { 26 func.apply(context, args); 27 } 28 }; 29 var callNow = immediate && !timeout; 30 clearTimeout(timeout); 31 timeout = setTimeout(later, wait); 32 if (callNow) { 33 func.apply(context, args); 34 } 35 }; 36 } 37 38 /** 39 * Check on if Medium viewport 40 * 41 * @private 42 * @returns {Boolean} 43 */ 44 function isSmallViewport () { 45 return window.matchMedia && window.matchMedia('(max-width: 767px)').matches; 46 } 47 48 /** 49 * Check on if Medium viewport 50 * 51 * @private 52 * @returns {Boolean} 53 */ 54 function isMediumViewport () { 55 return window.matchMedia && window.matchMedia('(min-width: 768px)').matches; 56 } 57 58 /** 59 * Check on if large viewport 60 * 61 * @private 62 * @returns {Boolean} 63 */ 64 function isLargeViewport () { 65 return window.matchMedia && window.matchMedia('(min-width: 1024px)').matches; 66 } 67 68 /** 69 * Try to find parent node for element by className 70 * 71 * @private 72 * @param {Object} element 73 * @param {string} className 74 * @returns {*} 75 */ 76 function getParentByClassName (element, className) { 77 while (element.parentNode) { 78 if (element.classList && element.classList.contains(className)) { 79 return element; 80 } else if (element.classList.contains(className)) { 81 return element; 82 } 83 84 element = element.parentNode; 85 } 86 87 return false; 88 } 89 90 function getViewportHeight () { 91 return window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; 92 } 93 94 /** 95 * Check if device supports touch 96 * @returns {Boolean} 97 */ 98 99 function isTouchEnabled () { 100 if ('ontouchstart' in window || 'onmsgesturechange' in window) { 101 return true; 102 } 103 104 return false; 105 } 106 107 /** 108 * Save the current location in the DOM tree. 109 * @param {object} element 110 */ 111 function setInitialDomTreeLocation (element) { 112 element.initialParent = element.parentElement; 113 element.initialNextSibling = element.nextSibling; 114 element.initialPreviousSibling = element.previousSibling; 115 } 116 117 /** 118 * Save the current location in the DOM tree. 119 * @param {object} element 120 */ 121 function resetDomTreeLocation (element) { 122 var parentHasChanged = !element.parentElement.isEqualNode(element.initialParent); 123 var hasSameParentAsInitialNextSibling = element.initialNextSibling && element.initialNextSibling.parentElement.isEqualNode(element.initialParent); 124 var hasSameParentAsInitialPreviousSibling = element.initialPreviousSibling && element.initialPreviousSibling.parentElement.isEqualNode(element.initialParent) 125 126 if (parentHasChanged) { 127 if (hasSameParentAsInitialNextSibling) { 128 element.initialParent.insertBefore(element, element.initialNextSibling); 129 } else if (hasSameParentAsInitialPreviousSibling) { 130 element.initialParent.insertBefore(element, element.initialPreviousSibling.nextSibling); 131 } else { 132 element.initialParent.appendChild(element); 133 } 134 } 135 } 136 137 /** 138 * Get parent node that is an Element 139 * @param {Object} elem 140 * @returns {Object} 141 */ 142 function getParentElement (elem) { 143 while (elem && elem.parentNode) { 144 elem = elem.parentNode; 145 if (elem && elem.nodeType === 1) { 146 return elem; 147 } 148 } 149 150 // Many DOM methods return null if they don't 151 // find the element they are searching for
152 // It would be OK to omit the following and just 153 // return undefined 154 return null; 155 } 156 157 function isFastTapCapable () { 158 return (PbLib.UI && PbLib.UI.FastTap && document.addEventListener && isTouchEnabled()) ? true : false; 159 } 160 161 162 /** 163 * Make videos responsive by 164 * @param {Array} videoElements 165 */ 166 function makeVideosResponsive (videoElements) { 167 var i; 168 169 for (i = 0; videoElements.length > i; i++) { 170 var video = videoElements[i]; 171 var videoHeightPercentage = (100 / video.clientWidth) * video.clientHeight; 172 var videoWrapper = document.createElement('div'); 173 174 videoWrapper.setAttribute('class', 'video-wrapper'); 175 videoWrapper.style.paddingBottom = videoHeightPercentage + '%'; 176 177 video.parentNode.insertBefore(videoWrapper, video.nextSibling); 178 videoWrapper.appendChild(video); 179 } 180 } 181 182 /** 183 * Add a class to the .article div of an Article Template 184 * @param {Array} elements 185 * @param {string} className 186 */ 187 function addClassToArticleDivs (elements, className) { 188 for (var i = 0; i < elements.length; i++) { 189 elements[i].up('.article').classList.add(className); 190 } 191 } 192 193 /** 194 * Add wrapper to around all tables (to apply styling with CSS: horizontal scroll on smaller screens) 195 */ 196 function addTableWrappers () { 197 var allTables = document.querySelectorAll('table'); 198 var i; 199 200 for (i = 0; i < allTables.length; i++) { 201 var table = allTables[i]; 202 var tableWrapper = document.createElement('div'); 203 204 tableWrapper.setAttribute('class', 'table-wrapper'); 205 table.parentNode.insertBefore(tableWrapper, table.nextSibling); 206 tableWrapper.appendChild(table); 207 } 208 } 209 210 return { 211 deBounce: deBounce, 212 isSmallViewport: isSmallViewport, 213 isMediumViewport: isMediumViewport, 214 isLargeViewport: isLargeViewport, 215 getParentByClassName: getParentByClassName, 216 getViewportHeight: getViewportHeight, 217 isTouchEnabled: isTouchEnabled, 218 setInitialDomTreeLocation: setInitialDomTreeLocation, 219 resetDomTreeLocation: resetDomTreeLocation, 220 getParentElement: getParentElement, 221 isFastTapCapable: isFastTapCapable, 222 makeVideosResponsive: makeVideosResponsive, 223 addClassToArticleDivs: addClassToArticleDivs, 224 addTableWrappers: addTableWrappers 225 }; 226});
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.