1/** 2 * @file Expandable Content. jQuery plugin which simplifies accordions in SiteVision. 3 * @author Hampus Nordin <[email protected]> 4 * @copyright Limepark AB 5 * @license https://limepark.se/licensvillkor 6 * @module expandableContent 7 * @version 1.2.1 8 */ 9 10/* eslint-disable no-magic-numbers */ 11 12/* console shim */ 13(function () { 14 var f = function () { 15 // ... 16 }; 17 if (!window.console) { 18 window.console = { 19 log:f, info:f, warn:f, debug:f, error:f 20 }; 21 } 22}()); 23 24/* global define, module, $svjq, jQuery, require, lp */ 25(function (factory) { 26 'use strict'; 27 28 // Use SiteVision's jQuery and fallback on global. 29 /* eslint-disable no-global-assign */ 30 jQuery = $svjq || jQuery; 31 /* eslint-enable no-global-assign */ 32 33 if (typeof define === 'function' && define.amd) { 34 // AMD. Register as an anonymous module. 35 define(['jquery'], factory); 36 } else if (typeof module === 'object' && module.exports) { 37 // Node/CommonJS 38 module.exports = function( root, jQuery ) { 39 if ( jQuery === undefined ) { 40 // require('jQuery') returns a factory that requires window to 41 // build a jQuery instance, we normalize how we use modules 42 // that require this pattern but the window provided is a noop 43 // if it's defined (how jquery works) 44 if ( typeof window !== 'undefined' ) { 45 jQuery = require('jquery'); 46 } 47 else { 48 jQuery = require('jquery')(root); 49 } 50 } 51 factory(jQuery); 52 return jQuery; 53 }; 54 } else { 55 // Browser globals 56 factory(jQuery); 57 } 58}(function ($) { 59 'use strict'; 60 61 var pluginName = 'expandableContent'; 62 var eventKey = 'expandable-content'; 63 var events = { 64 "CHANGE": "change." + eventKey, 65 "TOGGLE": "toggle." + eventKey 66 }; 67 68 // Extract query parameters from url string as js object. 69 function queryParamsFromUrlString (urlString) { 70 var queryDict = {}; 71 var pair; 72 (urlString.split('?')[1] || '').split('&').forEach(function(item) { 73 pair = item.split('='); 74 if (pair[0]) { 75 queryDict[pair[0]] = pair[1]; 76 } 77 }); 78 return queryDict; 79 } 80 81 // Convert an SiteVision NodeId to it's corresponding html ID. 82 function svid2htmlid (svid) { 83 return 'svid' + (svid + '').replace('.', '_'); 84 } 85 86 // Callback for when toggling is finished. 87 function toggleCallback (plugin) { 88 var $toggler = this.$elem; 89 90 // Trigger custom event. 91 $toggler.trigger(events.TOGGLE, [this, plugin]); 92 93 if (this.isOpen()) { 94 $toggler 95 .addClass(plugin.options.openClass) 96 .removeClass(plugin.options.closedClass) 97 .removeClass(plugin.options.openingClass); 98 } else { 99 $toggler 100 .addClass(plugin.options.closedClass) 101 .removeClass(plugin.options.openClass) 102 .removeClass(plugin.options.closingClass); 103 } 104 } 105 106 // Callback for when toggling is starting. 107 function changeCallback (plugin, isOpen) { 108 var $toggler = this.$elem; 109 110 // Trigger custom event. 111 $toggler.trigger(events.CHANGE, [this, plugin, isOpen]); 112 113 if (isOpen) { 114 $toggler.addClass(plugin.options.openingClass); 115 } else { 116 $toggler.addClass(plugin.options.closingClass); 117 } 118 } 119 120 // The actual plugin constructor 121 function Plugin (element, options) { 122 this.element = element; 123 this.options = $.extend(true, {}, $.fn[pluginName].defaults, options); 124 this._name = pluginName; 125 this._toggles = []; 126 127 this.init(); 128 } 129 130 $.extend(Plugin.prototype, { 131 init: function () { 132 var $element = $(this.element); 133 var $children = $element.children(); 134 135 // Iterate over every second child. 136 for (var i = 0; i < $children.length; i += 2) { 137 var $toggler = $children.eq(i); 138 var $content = $children.eq(i + 1); 139 140 if (typeof this.options.createButton === 'function') { 141 $toggler = this.options.createButton($toggler, this); 142 } 143 144 if (typeof this.options.createContent === 'function') { 145 $content = this.options.createContent($content, this); 146 } 147 148 if (this.options.wrapClass) { 149 $toggler.add($content).wrapAll('<div class="' + this.options.wrapClass + '">'); 150 } 151 152 if (typeof this.options.toggleOptions !== 'object') { 153 this.options.toggleOptions = {}; 154 } 155 156 // Setup toggler 157 var toggle = lp.toggle.setup($toggler, $content, this.options.toggleOptions); 158 toggle 159 .opened(toggleCallback.bind(toggle, this)) 160 .closed(toggleCallback.bind(toggle, this)) 161 .change(changeCallback.bind(toggle, this)); 162 163 this._toggles.push(toggle); 164 } 165 166 if (this.options.autoOpenOnUrl) { 167 this.openByUrl(); 168 } 169 }, 170 destroy: function () { 171 // Todo 172 /* eslint-disable no-console */ 173 console.info('Plugin.prototype.destroy is not implemented yet.'); 174 /* eslint-enable no-console */ 175 }, 176 openByUrl: function () { 177 var plugin = this; 178 179 $(function () { 180 var href = location.href; 181 var locationHash = (href.split("#")[1] || ""); 182 var queryParams = queryParamsFromUrlString(href); 183 184 var urlEls = []; 185 if (locationHash) { 186 var locationEl = ''; 187 try { 188 locationEl = $('#' + locationHash).get(0); 189 } catch (e) { 190 // ... 191 } 192 193 if (locationEl) { 194 urlEls.push(locationEl); 195 } 196 } 197 if (queryParams['sv.url']) { 198 var queryEl = $('#' + svid2htmlid(queryParams['sv.url'])).get(0); 199 if (queryEl) { 200 urlEls.push(queryEl); 201 } 202 } 203 204 if (urlEls.length) { 205 for (var i = plugin._toggles.length - 1; i >= 0; i--) { 206 var j = urlEls.length; 207 var wrapEl = plugin._toggles[i].$elem.closest('.' + plugin.options.wrapClass).get(0); 208 while (j--) { 209 if ($.contains(wrapEl, urlEls[j])) { 210 plugin._toggles[i].open(); 211 urlEls.splice(j, 1); 212 } 213 } 214 215 if (urlEls.length === 0) { 216 break; 217 } 218 } 219 } 220 }); 221 }, 222 helpers: { 223 setAttributes: function (node, attrs) { 224 var attr; 225 var attrFunc; 226 for (var i = attrs.length - 1; i >= 0; i--) { 227 // `attr` should be an array of either 2 or 3 strings 228 attr = attrs[i]; 229 if (attr.length === 3 || attr.length === 2) { 230 // Choose either setAttributeNS or setAttribute depending on length of `attr`. 231 attrFunc = attr.length === 3 ? node.setAttributeNS : node.setAttribute;
232 // Apply attr to node. 233 attrFunc.apply(node, attr); 234 } 235 } 236 }, 237 _createSvgIcon: function (iconUrl, iconClass) { 238 var useNode = document.createElementNS('http://www.w3.org/2000/svg', 'use'); 239 var svgNode = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); 240 241 // Set attributes on <use> 242 this.setAttributes(useNode, [ 243 ['http://www.w3.org/1999/xlink', 'xlink:href', iconUrl], 244 ['http://www.w3.org/2000/xmlns/', 'xmlns:xlink', 'http://www.w3.org/1999/xlink'] 245 ]); 246 247 // Set attributes on <svg> 248 this.setAttributes(svgNode, [ 249 ['aria-hidden', 'true'], 250 ['class', iconClass || 'lp-icon'] 251 ]); 252 253 // add <use> to <svg> 254 svgNode.appendChild(useNode); 255 256 return svgNode; 257 }, 258 _createImgIcon: function (iconUrl, iconClass) { 259 var imgNode = document.createElement('img'); 260 261 // Set attributes on <img> 262 this.setAttributes(imgNode, [ 263 ['class', iconClass || 'lp-icon'], 264 ['alt', ''], 265 ['src', iconUrl] 266 ]); 267 268 return imgNode; 269 }, 270 createIcon: function (iconUrl, iconClass) { 271 if (!!iconUrl.match(/\.svg(#[a-z0-9-_]+)?$/i)) { 272 return this._createSvgIcon(iconUrl, iconClass); 273 } else { 274 return this._createImgIcon(iconUrl, iconClass); 275 } 276 }, 277 append: function (icon, target) { 278 target.appendChild(icon); 279 }, 280 prepend: function (icon, target) { 281 var refNode = target.firstChild; 282 target.insertBefore(icon, refNode); 283 } 284 } 285 }); 286 287 /** 288 * Plugin wrapper 289 * 290 * A really lightweight plugin wrapper around the constructor, 291 * preventing against multiple instantiations. 292 * 293 * @param {Object|String} options 294 * @return {jQuery} 295 */ 296 $.fn[pluginName] = function (options) { 297 var key = "plugin_" + pluginName; 298 299 if (typeof window.lp === 'undefined' || typeof window.lp.toggle === 'undefined') { 300 /* eslint-disable no-console */ 301 console.warn('Missing dependency: lp.toggle'); 302 /* eslint-enable no-console */ 303 return this; 304 } 305 306 return this.each(function () { 307 var plugin = $.data(this, key); 308 309 if (!plugin) { 310 plugin = new Plugin(this, options); 311 $.data(this, key, plugin); 312 } else if (options === 'destroy') { 313 plugin.destroy(); 314 $.removeData(this, key); 315 } 316 }); 317 }; 318 319 /** 320 * Default options 321 * 322 * @type {Object} 323 */ 324 $.fn[pluginName].defaults = { 325 buttonClass: "lp-expandable-content__toggler", 326 contentClass: "lp-expandable-content__content", 327 wrapClass: "lp-expandable-content__wrap", 328 openClass: "lp-expandable-content--is-open", 329 closedClass: "lp-expandable-content--is-closed", 330 openingClass: "lp-expandable-content--is-opening", 331 closingClass: "lp-expandable-content--is-closing", 332 iconOpen: "/webdav/files/system/svg/lp-icons.svg#lp-plus", 333 iconClose: "/webdav/files/system/svg/lp-icons.svg#lp-minus", 334 autoOpenOnUrl: true, 335 toggleOptions: {}, 336 createButton: function ($content, plugin) { 337 var $toggler = $content.is('button') ? $content : $content.wrap('<button>').parent(); 338 339 $toggler.addClass(plugin.options.buttonClass); 340 341 // Create icons and add them to toggler. 342 if (plugin.options.iconOpen) { 343 var iconOpenEl = plugin.helpers.createIcon(plugin.options.iconOpen, 'lp-icon lp-toggler-icon lp-toggler-icon--open'); 344 plugin.helpers.prepend(iconOpenEl, $toggler.get(0)); 345 } 346 if (plugin.options.iconClose) { 347 var iconCloseEl = plugin.helpers.createIcon(plugin.options.iconClose, 'lp-icon lp-toggler-icon lp-toggler-icon--close'); 348 plugin.helpers.prepend(iconCloseEl, $toggler.get(0)); 349 } 350 351 return $toggler; 352 }, 353 createContent: function ($content, plugin) { 354 $content.addClass(plugin.options.contentClass); 355 return $content; 356 } 357 }; 358}));
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.