1// https://tc39.github.io/ecma262/#sec-array.prototype.find 2if (!Array.prototype.find) { 3 Object.defineProperty(Array.prototype, "find", { 4 value: function(predicate) { 5 // 1. Let O be ? ToObject(this value). 6 if (this == null) { 7 throw new TypeError('"this" is null or not defined'); 8 } 9 10 var o = Object(this); 11 12 // 2. Let len be ? ToLength(? Get(O, "length")). 13 var len = o.length >>> 0; 14 15 // 3. If IsCallable(predicate) is false, throw a TypeError exception. 16 if (typeof predicate !== "function") { 17 throw new TypeError("predicate must be a function"); 18 } 19 20 // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. 21 var thisArg = arguments[1]; 22 23 // 5. Let k be 0. 24 var k = 0; 25 26 // 6. Repeat, while k < len 27 while (k < len) { 28 // a. Let Pk be ! ToString(k). 29 // b. Let kValue be ? Get(O, Pk). 30 // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). 31 // d. If testResult is true, return kValue. 32 var kValue = o[k]; 33 if (predicate.call(thisArg, kValue, k, o)) { 34 return kValue; 35 } 36 // e. Increase k by 1. 37 k++; 38 } 39 40 // 7. Return undefined. 41 return undefined; 42 }, 43 configurable: true, 44 writable: true 45 }); 46} 47 48(function($, once) { 49 "use strict"; 50 51 Drupal.behaviors.CohesionLink = { 52 attach: function(context) { 53 // Libs 54 var cmm = new Drupal.CohesionResponsiveBreakpoints(); 55 56 // Scroll to functionality. 57 $.each( 58 once("coh-js-scroll-to-init", ".coh-js-scroll-to", context), 59 bindScrollTo 60 ); 61 62 // Scroll to top functionality. 63 $.each( 64 once("coh-js-scroll-top-init", ".coh-js-scroll-top", context), 65 bindScrollTop 66 ); 67 68 // Toggle modifier interactivity. 69 $.each( 70 once("coh-toggle-modifier-init", ".coh-interaction", context), 71 bindModifier 72 ); 73 74 // Animation interactivity. 75 $.each( 76 once("coh-animation-init", ".coh-interaction", context), 77 bindAnimation 78 ); 79 80 // Function from David Walsh: http://davidwalsh.name/css-animation-callback 81 function whichTransitionEvent() { 82 var t, 83 el = document.createElement("fakeelement"); 84 85 var transitions = { 86 transition: "transitionend", 87 OTransition: "oTransitionEnd", 88 MozTransition: "transitionend", 89 WebkitTransition: "webkitTransitionEnd" 90 }; 91 92 for (t in transitions) { 93 if (el.style[t] !== undefined) { 94 return transitions[t]; 95 } 96 } 97 } 98 99 function getComponentClass($el) { 100 if (!$el || !$el.length) { 101 return undefined; 102 } 103 for (var i = 0; i < $el.prop("classList").length; i++) { 104 if ( 105 $el 106 .prop("classList") 107 [i].match( 108 /coh-component-instance-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/ 109 ) 110 ) { 111 return $el.prop("classList")[i]; 112 } 113 } 114 } 115 116 function bindScrollTo() { 117 var $this = $(this); 118 119 $this.on("click", function(e) { 120 // Don't click through to the page. 121 e.preventDefault(); 122 123 var defaultSettings = { 124 duration: 450, 125 offset: 0 126 }; 127 128 var scrollTarget = $this.data("cohScrollTo"); 129 var scrollDuration = $this.data("cohScrollDuration"); 130 131 /** 132 * Offset can either be a jQuery selector (in which cas return elements height) or a number 133 * @returns {*} 134 */ 135 var scrollOffset = function() { 136 var offset = $this.data("cohScrollOffset"); 137 138 if (typeof offset === "string") { 139 var $el = $(offset); 140 141 if ($el.length) { 142 return 0 - $el.height(); 143 } 144 145 return 0; 146 } 147 148 // plugin expects negative value, when positive value is better UX - reverses logic 149 return offset * -1; 150 }; 151 var scrollSettings = { 152 duration: scrollDuration, 153 offset: scrollOffset() 154 }; 155 156 var settings = $.extend(defaultSettings, scrollSettings); 157 158 // And smoothly scroll. 159 $("html, body").scrollTo(scrollTarget, settings); 160 }); 161 } 162 163 function bindScrollTop() { 164 $(this).on("click", function(e) { 165 // Don't click through to the page. 166 e.preventDefault(); 167 168 // And smoothly scroll. 169 $("html, body").scrollTo(0, 450); 170 }); 171 } 172 173 function bindModifier() { 174 var settings = $(this).data("interactionModifiers"); 175 176 // If there are no settings just return 177 if (!settings || settings[0].modifierType === "") { 178 return; 179 } 180 181 $(this).on("click.coh.modifier", function(e) { 182 var $this = $(this); 183 // Don't click through to the page. 184 e.preventDefault(); 185 186 var modifier_types = { 187 "add-modifier": "addClass", 188 "remove-modifier": "removeClass", 189 "toggle-modifier": "toggleClass", 190 "toggle-modifier-accessible-collapsed": "toggleClass", 191 "toggle-modifier-accessible-expanded": "toggleClass" 192 }; 193 194 for (var i = 0; i < settings.length; i++) { 195 if (!settings[i].modifierName) { 196 console.warn( 197 'Link element is set to toggle a modifier class on a target element but no "Modifier class name" was specified. You must specify a "Modifier class name".' 198 ); 199 return; 200 } 201 202 var modifier_name = settings[i].modifierName.replace(/^\./, ""); // Check for and remove leading dot character 203 var interaction_target = settings[i].interactionTarget; 204 var modifier_type = settings[i].modifierType; 205 var transitionEvent = whichTransitionEvent(); 206 var $interaction_scope; 207 var $target; 208 209 // If the scope is something other than 'this' but a target isn't supplied, don't do anything. 210 if ( 211 settings[i].interactionScope !== "this" && 212 !interaction_target 213 ) { 214 console.warn( 215 'Link element is set to "' + 216 modifier_type + 217 '" but does not have a "Target (jQuery selector)" specified. You must specify a "Target (jQuery selector)" or set "Scope to" to "This element"' 218 ); 219 return; 220 } 221 222 $interaction_scope = getScope( 223 $this, 224 settings[i].interactionScope, 225 settings[i].interactionParent 226 ); 227 228 $target = getTarget( 229 $this, 230 interaction_target, 231 $interaction_scope, 232 settings[i].interaction_scope 233 ); 234 235 if ($target.length) { 236 $this.data("clickedModifier", !$this.data.clickedModifier); 237 // Get jQuery method from modifier types object based on model and apply transition class 238 $target[modifier_types[modifier_type]](modifier_name).addClass( 239 "coh-transition" 240 ); 241 242 $target.on(transitionEvent, function() { 243 // Remove transition class once transition has finished 244 $(this) 245 .removeClass("coh-transition") 246 .off(transitionEvent); 247 }); 248 249 // If the modifier is an accessible popup 250 if (modifier_type.indexOf("toggle-modifier-accessible-") === 0) { 251 // Toggle aria-expanded attribute value 252 $(this).attr( 253 "aria-expanded", 254 $(this).attr("aria-expanded") === "true" ? "false" : "true" 255 ); 256 } 257 // Run Drupal behaviors for anything that is hidden 258 Drupal.attachBehaviors($target[0]); 259 } 260 } 261 }); 262 } 263 264 /** 265 * Called when moving between breakpoints. This function compares the breakpoint you have just moved to with the
266 * breakpoint you've just come from (stored in previousBreakPointAnimSettings). If you are moving from a breakpoint 267 * that has animation to a breakpoint that does not have settings for a matching animationTarget 268 * then the css display property is removed. https://cohesion-dev.atlassian.net/browse/COH-4794 269 * @param mm 270 */ 271 function cohCheckDisplayResize(mm) { 272 var currentSettings = 273 mm.cohesion.settings.breakpoints[mm.cohesion.key] || {}; 274 var animSettings = 275 currentSettings.linkAnimation || 276 currentSettings.buttonAnimation || 277 []; 278 mm.cohesion.settings.element 279 .data("previousBreakPointAnimSettings") 280 .forEach(function(prevSetting) { 281 // if prevSetting.target doesn't exist in any of the current settings 282 var matchedSetting = animSettings.find(function(setting) { 283 return prevSetting.animationTarget === setting.animationTarget; 284 }); 285 286 // In future we can add `displayReset` as a bool/toggle to the JSON form and control this behaviour 287 if (!matchedSetting && prevSetting.displayReset !== false) { 288 if (mm.cohesion.settings.element.data("clickedAnimation")) { 289 // mm.cohesion.settings.element.trigger('click.coh.animation'); 290 runAnimation(mm.cohesion.settings.element, prevSetting, true); 291 if (mm.cohesion.settings.element.data("clickedModifier")) { 292 mm.cohesion.settings.element.trigger("click.coh.modifier"); 293 } 294 } else { 295 if (prevSetting.animationTarget) { 296 var $interaction_scope = getScope( 297 mm.cohesion.settings.element, 298 prevSetting.animationScope, 299 prevSetting.animationParent 300 ); 301 var $target = getTarget( 302 mm.cohesion.settings.element, 303 prevSetting.animationTarget, 304 $interaction_scope, 305 prevSetting.animationScope 306 ); 307 $target.css("display", ""); 308 } 309 } 310 } 311 }); 312 313 mm.cohesion.settings.element.data( 314 "previousBreakPointAnimSettings", 315 animSettings || [] 316 ); 317 } 318 319 function bindAnimation() { 320 var $this = $(this), 321 data = $this.data("cohSettings"), 322 settings = { 323 element: $this, 324 breakpoints: {} 325 }, 326 key; 327 328 $this.data("previousBreakPointAnimSettings", []); 329 330 for (var i = 0; i < cmm.breakpoints.length; i++) { 331 key = cmm.breakpoints[i].key; 332 333 // Populate all breakpoints regardless of whether the settings are set or not to simulate inheritance 334 settings.breakpoints[key] = {}; 335 if (typeof data[key] !== "undefined" && !$.isEmptyObject(data[key])) { 336 settings.breakpoints[key] = data[key]; 337 338 var previous = data[key]; 339 } else { 340 if ( 341 typeof cmm.breakpoints[i - 1] !== "undefined" && 342 typeof previous !== "undefined" 343 ) { 344 settings.breakpoints[key] = previous; 345 } 346 } 347 } 348 349 cmm.addListeners(settings, cohCheckDisplayResize); 350 351 $this.on("click.coh.animation", function(e) { 352 e.preventDefault(); 353 354 var currentSettings = 355 settings.breakpoints[cmm.getCurrentBreakpoint().key]; 356 currentSettings = 357 currentSettings.linkAnimation || currentSettings.buttonAnimation; 358 359 if (currentSettings) { 360 for (var i = 0; i < currentSettings.length; i++) { 361 var currentSetting = currentSettings[i]; 362 363 if (currentSetting.animationType !== "none") { 364 runAnimation($this, currentSetting); 365 } 366 } 367 } 368 }); 369 } 370 371 function runAnimation($this, settings, removeDisplay) { 372 var $interaction_scope; 373 var $target, origin; 374 375 $interaction_scope = getScope( 376 $this, 377 settings.animationScope, 378 settings.animationParent 379 ); 380 $target = getTarget( 381 $this, 382 settings.animationTarget, 383 $interaction_scope, 384 settings.animationScope 385 ); 386 387 if ($target.length) { 388 $this.data("clickedAnimation", !$this.data("clickedAnimation")); 389 390 if (settings.animationOrigin) { 391 origin = settings.animationOrigin.split(","); 392 } 393 394 $.each($($target), function() { 395 var $that = $(this); 396 397 $that.toggle({ 398 effect: settings.animationType, 399 direction: settings.animationDirection, 400 distance: settings.animationDistance, 401 pieces: settings.animationPieces, 402 percent: settings.animationScale, 403 origin: origin, 404 size: settings.animationFoldHeight, 405 horizFirst: settings.animationHorizontalFirst, 406 times: settings.animationIterations, 407 easing: settings.animationEasing, 408 duration: removeDisplay ? 0 : settings.animationDuration, 409 complete: function() { 410 // Run Drupal behaviors for anything that is hidden 411 Drupal.attachBehaviors($(this)[0]); 412 if (removeDisplay) { 413 $that.css("display", ""); 414 } 415 } 416 }); 417 }); 418 } 419 } 420 421 function getScope($this, scope, parent) { 422 var $interaction_scope; 423 switch (scope) { 424 case "this": 425 $interaction_scope = $this; 426 break; 427 case "parent": 428 $interaction_scope = $this.closest(parent); 429 break; 430 case "component": 431 var componentClass = getComponentClass( 432 $this.closest(".coh-component") 433 ); 434 435 if (componentClass) { 436 $interaction_scope = $("." + componentClass); 437 } else { 438 // 'component' scope was chosen but there isn't a parent component. (i.e. element is just sat on a layout canvas). 439 $interaction_scope = $(document); 440 } 441 break; 442 default: 443 $interaction_scope = $(document); 444 break; 445 } 446 return $interaction_scope; 447 } 448 449 function getTarget( 450 $this, 451 interaction_target, 452 $interaction_scope, 453 interaction_scope 454 ) { 455 var $target = $(); 456 if (interaction_scope === "this" && !interaction_target) { 457 $target = $this; 458 } else if (!interaction_target) { 459 console.warn( 460 'Element does not have a "Target (jQuery selector)" specified. You must specify a "Target (jQuery selector)" or set "Scope to" to "This element".' 461 ); 462 return $target; 463 } 464 465 if (!$target.length) { 466 // Process the interaction target as a jQuery selector 467 $target = $(interaction_target, $interaction_scope); 468 } 469 470 // Is it one of the top level elements in a component 471 if (!$target.length) { 472 $target = $interaction_scope.filter(interaction_target); 473 } 474 475 // Is it a child of the scope? 476 if (!$target.length) { 477 $target = $interaction_scope.find($(interaction_target)); 478 } 479 480 // Try the interaction target as a className (legacy - we used to except a class, unprefixed with . instead of a jquery selector. 481 if (interaction_target.indexOf(".") !== 0) { 482 if (!$target.length) { 483 $target = $interaction_scope.filter("." + interaction_target); 484 } 485 486 if (!$target.length) { 487 $target = $interaction_scope.find($("." + interaction_target)); 488 } 489 } 490 491 if (!$target.length) { 492 console.warn( 493 'Element has "Target (jQuery selector)" set to "' + 494 interaction_target + 495 '", but no matching element was found on the page.' 496 ); 497 } 498 499 return $target; 500 } 501 } 502 }; 503})(jQuery, once);
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.