1(function (root, factory) { 2 if (typeof define === "function" && define.amd) { 3 define([], factory); 4 } else { 5 root.TateUI = factory(); 6 } 7}(this, function () { 8
vendor: 15,332 bytes, lines 9-444
9/** 10 * @license almond 0.3.3 Copyright jQuery Foundation and other contributors. 11 * Released under MIT license, http://github.com/requirejs/almond/LICENSE 12 */ 13//Going sloppy to avoid 'use strict' string cost, but strict practices should 14//be followed. 15/*global setTimeout: false */ 16 17var requirejs, require, define; 18(function (undef) { 19 var main, req, makeMap, handlers, 20 defined = {}, 21 waiting = {}, 22 config = {}, 23 defining = {}, 24 hasOwn = Object.prototype.hasOwnProperty, 25 aps = [].slice, 26 jsSuffixRegExp = /\.js$/; 27 28 function hasProp(obj, prop) { 29 return hasOwn.call(obj, prop); 30 } 31 32 /** 33 * Given a relative module name, like ./something, normalize it to 34 * a real name that can be mapped to a path. 35 * @param {String} name the relative name 36 * @param {String} baseName a real name that the name arg is relative 37 * to. 38 * @returns {String} normalized name 39 */ 40 function normalize(name, baseName) { 41 var nameParts, nameSegment, mapValue, foundMap, lastIndex, 42 foundI, foundStarMap, starI, i, j, part, normalizedBaseParts, 43 baseParts = baseName && baseName.split("/"), 44 map = config.map, 45 starMap = (map && map['*']) || {}; 46 47 //Adjust any relative paths. 48 if (name) { 49 name = name.split('/'); 50 lastIndex = name.length - 1; 51 52 // If wanting node ID compatibility, strip .js from end 53 // of IDs. Have to do this here, and not in nameToUrl 54 // because node allows either .js or non .js to map 55 // to same file. 56 if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { 57 name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); 58 } 59 60 // Starts with a '.' so need the baseName 61 if (name[0].charAt(0) === '.' && baseParts) { 62 //Convert baseName to array, and lop off the last part, 63 //so that . matches that 'directory' and not name of the baseName's 64 //module. For instance, baseName of 'one/two/three', maps to 65 //'one/two/three.js', but we want the directory, 'one/two' for 66 //this normalization. 67 normalizedBaseParts = baseParts.slice(0, baseParts.length - 1); 68 name = normalizedBaseParts.concat(name); 69 } 70 71 //start trimDots 72 for (i = 0; i < name.length; i++) { 73 part = name[i]; 74 if (part === '.') { 75 name.splice(i, 1); 76 i -= 1; 77 } else if (part === '..') { 78 // If at the start, or previous value is still .., 79 // keep them so that when converted to a path it may 80 // still work when converted to a path, even though 81 // as an ID it is less than ideal. In larger point 82 // releases, may be better to just kick out an error. 83 if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') { 84 continue; 85 } else if (i > 0) { 86 name.splice(i - 1, 2); 87 i -= 2; 88 } 89 } 90 } 91 //end trimDots 92 93 name = name.join('/'); 94 } 95 96 //Apply map config if available. 97 if ((baseParts || starMap) && map) { 98 nameParts = name.split('/'); 99 100 for (i = nameParts.length; i > 0; i -= 1) { 101 nameSegment = nameParts.slice(0, i).join("/"); 102 103 if (baseParts) { 104 //Find the longest baseName segment match in the config. 105 //So, do joins on the biggest to smallest lengths of baseParts. 106 for (j = baseParts.length; j > 0; j -= 1) { 107 mapValue = map[baseParts.slice(0, j).join('/')]; 108 109 //baseName segment has config, find if it has one for 110 //this name. 111 if (mapValue) { 112 mapValue = mapValue[nameSegment]; 113 if (mapValue) { 114 //Match, update name to the new value. 115 foundMap = mapValue; 116 foundI = i; 117 break; 118 } 119 } 120 } 121 } 122 123 if (foundMap) { 124 break; 125 } 126 127 //Check for a star map match, but just hold on to it, 128 //if there is a shorter segment match later in a matching 129 //config, then favor over this star map. 130 if (!foundStarMap && starMap && starMap[nameSegment]) { 131 foundStarMap = starMap[nameSegment]; 132 starI = i; 133 } 134 } 135 136 if (!foundMap && foundStarMap) { 137 foundMap = foundStarMap; 138 foundI = starI; 139 } 140 141 if (foundMap) { 142 nameParts.splice(0, foundI, foundMap); 143 name = nameParts.join('/'); 144 } 145 } 146 147 return name; 148 } 149 150 function makeRequire(relName, forceSync) { 151 return function () { 152 //A version of a require function that passes a moduleName 153 //value for items that may need to 154 //look up paths relative to the moduleName 155 var args = aps.call(arguments, 0); 156 157 //If first arg is not require('string'), and there is only 158 //one arg, it is the array form without a callback. Insert 159 //a null so that the following concat is correct. 160 if (typeof args[0] !== 'string' && args.length === 1) { 161 args.push(null); 162 } 163 return req.apply(undef, args.concat([relName, forceSync])); 164 }; 165 } 166 167 function makeNormalize(relName) { 168 return function (name) { 169 return normalize(name, relName); 170 }; 171 } 172 173 function makeLoad(depName) { 174 return function (value) { 175 defined[depName] = value; 176 }; 177 } 178 179 function callDep(name) { 180 if (hasProp(waiting, name)) { 181 var args = waiting[name]; 182 delete waiting[name]; 183 defining[name] = true; 184 main.apply(undef, args); 185 } 186 187 if (!hasProp(defined, name) && !hasProp(defining, name)) { 188 throw new Error('No ' + name); 189 } 190 return defined[name]; 191 } 192 193 //Turns a plugin!resource to [plugin, resource] 194 //with the plugin being undefined if the name 195 //did not have a plugin prefix. 196 function splitPrefix(name) { 197 var prefix, 198 index = name ? name.indexOf('!') : -1; 199 if (index > -1) { 200 prefix = name.substring(0, index); 201 name = name.substring(index + 1, name.length); 202 } 203 return [prefix, name]; 204 } 205 206 //Creates a parts array for a relName where first part is plugin ID, 207 //second part is resource ID. Assumes relName has already been normalized. 208 function makeRelParts(relName) { 209 return relName ? splitPrefix(relName) : []; 210 } 211 212 /** 213 * Makes a name map, normalizing the name, and using a plugin 214 * for normalization if necessary. Grabs a ref to plugin 215 * too, as an optimization. 216 */ 217 makeMap = function (name, relParts) { 218 var plugin, 219 parts = splitPrefix(name), 220 prefix = parts[0], 221 relResourceName = relParts[1]; 222 223 name = parts[1]; 224 225 if (prefix) { 226 prefix = normalize(prefix, relResourceName); 227 plugin = callDep(prefix); 228 } 229 230 //Normalize according 231 if (prefix) { 232 if (plugin && plugin.normalize) { 233 name = plugin.normalize(name, makeNormalize(relResourceName)); 234 } else { 235 name = normalize(name, relResourceName); 236 } 237 } else { 238 name = normalize(name, relResourceName); 239 parts = splitPrefix(name); 240 prefix = parts[0]; 241 name = parts[1]; 242 if (prefix) { 243 plugin = callDep(prefix); 244 } 245 } 246 247 //Using ridiculous property names for space reasons 248 return { 249 f: prefix ? prefix + '!' + name : name, //fullName 250 n: name, 251 pr: prefix, 252 p: plugin 253 }; 254 }; 255 256 function makeConfig(name) { 257 return function () { 258 return (config && config.config && config.config[name]) || {}; 259 }; 260 } 261 262 handlers = { 263 require: function (name) { 264 return makeRequire(name); 265 }, 266 exports: function (name) { 267 var e = defined[name]; 268 if (typeof e !== 'undefined') { 269 return e; 270 } else { 271 return (defined[name] = {}); 272 } 273 }, 274 module: function (name) { 275 return { 276 id: name, 277 uri: '', 278 exports: defined[name], 279 config: makeConfig(name) 280 }; 281 } 282 }; 283 284 main = function (name, deps, callback, relName) { 285 var cjsModule, depName, ret, map, i, relParts, 286 args = [], 287 callbackType = typeof callback, 288 usingExports; 289 290 //Use name if no relName 291 relName = relName || name; 292 relParts = makeRelParts(relName); 293 294 //Call the callback to define the module, if necessary. 295 if (callbackType === 'undefined' || callbackType === 'function') { 296 //Pull out the defined dependencies and pass the ordered 297 //values to the callback. 298 //Default to [require, exports, module] if no deps 299 deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps; 300 for (i = 0; i < deps.length; i += 1) { 301 map = makeMap(deps[i], relParts); 302 depName = map.f; 303 304 //Fast path CommonJS standard dependencies. 305 if (depName === "require") { 306 args[i] = handlers.require(name); 307 } else if (depName === "exports") { 308 //CommonJS module spec 1.1 309 args[i] = handlers.exports(name); 310 usingExports = true; 311 } else if (depName === "module") { 312 //CommonJS module spec 1.1 313 cjsModule = args[i] = handlers.module(name); 314 } else if (hasProp(defined, depName) || 315 hasProp(waiting, depName) || 316 hasProp(defining, depName)) { 317 args[i] = callDep(depName); 318 } else if (map.p) { 319 map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {}); 320 args[i] = defined[depName]; 321 } else { 322 throw new Error(name + ' missing ' + depName); 323 } 324 } 325 326 ret = callback ? callback.apply(defined[name], args) : undefined; 327 328 if (name) { 329 //If setting exports via "module" is in play, 330 //favor that over return value and exports. After that, 331 //favor a non-undefined return value over exports use. 332 if (cjsModule && cjsModule.exports !== undef && 333 cjsModule.exports !== defined[name]) { 334 defined[name] = cjsModule.exports; 335 } else if (ret !== undef || !usingExports) { 336 //Use the return value from the function. 337 defined[name] = ret; 338 } 339 } 340 } else if (name) { 341 //May just be an object definition for the module. Only 342 //worry about defining if have a module name. 343 defined[name] = callback; 344 } 345 }; 346 347 requirejs = require = req = function (deps, callback, relName, forceSync, alt) { 348 if (typeof deps === "string") { 349 if (handlers[deps]) { 350 //callback in this case is really relName 351 return handlers[deps](callback); 352 } 353 //Just return the module wanted. In this scenario, the 354 //deps arg is the module name, and second arg (if passed) 355 //is just the relName. 356 //Normalize module name, if it contains . or .. 357 return callDep(makeMap(deps, makeRelParts(callback)).f); 358 } else if (!deps.splice) { 359 //deps is a config object, not an array. 360 config = deps; 361 if (config.deps) { 362 req(config.deps, config.callback); 363 } 364 if (!callback) { 365 return; 366 } 367 368 if (callback.splice) { 369 //callback is an array, which means it is a dependency list. 370 //Adjust args if there are dependencies 371 deps = callback; 372 callback = relName; 373 relName = null; 374 } else { 375 deps = undef; 376 } 377 } 378 379 //Support require(['a']) 380 callback = callback || function () {}; 381 382 //If relName is a function, it is an errback handler, 383 //so remove it. 384 if (typeof relName === 'function') { 385 relName = forceSync; 386 forceSync = alt; 387 } 388 389 //Simulate async callback; 390 if (forceSync) { 391 main(undef, deps, callback, relName); 392 } else { 393 //Using a non-zero value because of concern for what old browsers 394 //do, and latest browsers "upgrade" to 4 if lower value is used: 395 //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout: 396 //If want a value immediately, use require('id') instead -- something 397 //that works in almond on the global level, but not guaranteed and 398 //unlikely to work in other AMD implementations. 399 setTimeout(function () { 400 main(undef, deps, callback, relName); 401 }, 4); 402 } 403 404 return req; 405 }; 406 407 /** 408 * Just drops the config on the floor, but returns req in case 409 * the config return value is used. 410 */ 411 req.config = function (cfg) { 412 return req(cfg); 413 }; 414 415 /** 416 * Expose module registry for debugging and tooling 417 */ 418 requirejs._defined = defined; 419 420 define = function (name, deps, callback) { 421 if (typeof name !== 'string') { 422 throw new Error('See almond README: incorrect module build, no module name'); 423 } 424 425 //This module may not have dependencies 426 if (!deps.splice) { 427 //deps is not an array, so probably means 428 //an object literal or factory function for 429 //the value. Adjust args. 430 callback = deps; 431 deps = []; 432 } 433 434 if (!hasProp(defined, name) && !hasProp(waiting, name)) { 435 waiting[name] = [name, deps, callback]; 436 } 437 }; 438 439 define.amd = { 440 jQuery: true 441 }; 442}()); 443 444define("
444../../../../../node_modules/almond/almond", function(){}); 445 446define('components/TatePolyfill',[], function () { 447 448 // collection of patches for the lesser fortunate browsers... won't give any name. 449 450 function TatePolyfill(options) { 451 var me = this; 452 453 // String.startsWith not supported in IE11, Edge 454 // http://stackoverflow.com/questions/30867172/code-not-running-in-ie-11-works-fine-in-chrome 455 if (!String.prototype.startsWith) { 456 String.prototype.startsWith = function(searchString, position) { 457 position = position || 0; 458 return this.indexOf(searchString, position) === position; 459 }; 460 } 461 } 462 463 return TatePolyfill; 464}); 465 466define('components/TateWindow',[], function () { 467 468 /** 469 * @class TateWindow tells us things about the current window. 470 */ 471 function TateWindow (options) { 472 var me = this; 473 this.init(); 474 } 475 476 TateWindow.prototype = { 477 /** 478 * @private 479 * @description Initialises the TateWindow class. 480 */ 481 init: function () { 482 //TODO 483 }, 484 485 486 /* 487 * @method 488 * @desc - Discovers if device has touch capabilities 489 * @return {boolean} 490 */ 491 isTouchDevice: function (){ 492 return 'ontouchstart' in window || 'onmsgesturechange' in window; 493 }, 494 495 // Cross-browser solution taken from http://www.softcomplex.com/docs/get_window_size_and_scrollbar_position.html, with thanks! 496 width: function() { 497 return this.f_filterResults ( 498 window.innerWidth ? window.innerWidth : 0, 499 document.documentElement ? document.documentElement.clientWidth : 0, 500 document.body ? document.body.clientWidth : 0 501 ); 502 }, 503 504 height: function() { 505 return this.f_filterResults ( 506 window.innerHeight ? window.innerHeight : 0, 507 document.documentElement ? document.documentElement.clientHeight : 0, 508 document.body ? document.body.clientHeight : 0 509 ); 510 }, 511 512 f_filterResults: function(n_win, n_docel, n_body) { 513 var n_result = n_win ? n_win : 0; 514 if (n_docel && (!n_result || (n_result > n_docel))) 515 n_result = n_docel; 516 return n_body && (!n_result || (n_result > n_body)) ? n_body : n_result; 517 } 518 519 }; 520 521 return TateWindow; 522}); 523 524define('components/TateStorage',[], function () { 525 /** 526 * @class TateStorage decides whether to use localStorage or cookies. 527 */ 528 function TateStorage (options) { 529 var me = this; 530 531 /** 532 * @constant 533 */ 534 this.T_COOKIE = { 535 get: function (key) { 536 key = me.encode(key); 537 var name = key + "="; 538 var cookies = document.cookie.split(';'); 539 540 for(var i=0; i < cookies.length; i++) { 541 var cookie = cookies[i]; 542 543 while (cookie.charAt(0)==' ') { 544 cookie = cookie.substring(1); 545 } 546 547 if (cookie.indexOf(name) === 0) { 548 var value = cookie.substring(key.length, cookie.length); 549 value = value.substring(1); 550 551 return { 552 'key': me.decode(key), 553 'val': me.decode(value) 554 }; 555 } 556 } 557 558 return false; 559 }, 560 set: function (key, val) { 561 if (val === "") return false; 562 key = me.encode(key); 563 val = me.encode(val); 564 565 document.cookie = key + "=" + val + "; expires=Thu, 31 Dec 2099 23:59:59 GMT; path=/"; 566 567 if (document.cookie.indexOf(key) == -1) { 568 return false; 569 } else { 570 return this.get(me.decode(key)); 571 } 572 }, 573 patch: function (key, val) { 574 if (!this.get(key)) { 575 return false; 576 } else { 577 this.delete(key); 578 return this.set(key, val); 579 } 580 }, 581 delete: function (key) { 582 key = me.encode(key); 583 584 document.cookie = key + "=null; expires=Thu, 01 Jan 1970 00:00:00 GMT"; 585 586 if (!this.get(me.decode(key))) { 587 return true; 588 } else { 589 return false;
590 } 591 } 592 }; 593 594 /** 595 * @constant 596 */ 597 this.T_LOCALSTORE = { 598 get: function (key) { 599 var rtn = {}, 600 item; 601 602 key = me.encode(key); 603 604 try { 605 item = window.localStorage.getItem(key); 606 } catch (err) { 607 return false; 608 } 609 610 if (item === null) { 611 return false; 612 } 613 614 return { 615 'key': me.decode(key), 616 'val': me.decode(item) 617 }; 618 }, 619 set: function (key, val) { 620 var rtn = {}, 621 item; 622 623 if (this.get(key)) { 624 return false; 625 } 626 627 key = me.encode(key); 628 val = me.encode(val); 629 630 try { 631 item = window.localStorage.setItem(key, val); 632 } catch (err) { 633 return false; 634 } 635 636 return { 637 'key': key, 638 'val': val 639 }; 640 }, 641 patch: function (key, val) { 642 if (!this.get(key)) { 643 return false; 644 } else { 645 this.delete(key); 646 return this.set(key, val); 647 } 648 }, 649 delete: function (key) { 650 var item; 651 652 key = me.encode(key); 653 654 try { 655 item = window.localStorage.removeItem(key); 656 } catch (err) { 657 return false; 658 } 659 660 return true; 661 } 662 }; 663 664 if (typeof options !== 'undefined' && typeof options.useCookie !== 'undefined' && options.useCookie) { 665 this.init(true); 666 } else { 667 this.init(false); 668 } 669 } 670 671 TateStorage.prototype = { 672 /** 673 * @private 674 * @description Initialises the TateStorage class, chooses the storage type. 675 */ 676 init: function (useCookie) { 677 if ('localStorage' in window && window.localStorage !== null && !useCookie) { 678 this.storage_method = "LOCALSTORE"; 679 } else { 680 this.storage_method = "COOKIE"; 681 } 682 }, 683 684 /** 685 * @method 686 * @description Decodes a b64 encoded string 687 * @param {string} b64_string The base64 string to decode 688 * @return {string} The decoded base64 string 689 */ 690 decode: function (b64_string) { 691 return atob(b64_string); 692 }, 693 694 /** 695 * @method 696 * @description Proxy to the storage type and deletes the keyword stored 697 * @param {string} keyword to be encoded and stored 698 * @return {boolean} true or false based on the result of the delete method 699 */ 700 delete: function (keyword) { 701 return this['T_' + this.storage_method].delete(keyword); 702 }, 703 704 /** 705 * @method 706 * @description Encodes a string to base64 707 * @param {string} to_string The string to encode 708 * @return {string} The base64 encoded string 709 */ 710 encode: function (to_string) { 711 return btoa(to_string); 712 }, 713 714 /** 715 * @method 716 * @description Proxy to the storage type and find the object by keyword param 717 * @param {string} keyword to find 718 * @return {object} The object that has been found 719 */ 720 find: function (keyword) { 721 return this['T_' + this.storage_method].get(keyword); 722 }, 723 724 /** 725 * @method 726 * @description Proxy to the storage type to find and alter the object param 727 * @param {string} keyword The keyword to find 728 * @param {string} value The value to alter 729 * @return {object} The object that has been altered 730 */ 731 patch: function (keyword, value) { 732 return this['T_' + this.storage_method].patch(keyword, value); 733 }, 734 735 /** 736 * @method 737 * @description Proxy to the storage type and store the keyword and value 738 * @param {string} keyword The keyword to store 739 * @param {string} value The value to alter 740 * @return {object} The object that has been stored 741 */ 742 store: function (keyword, value) { 743 return this['T_' + this.storage_method].set(keyword, value); 744 }, 745 }; 746 747 return TateStorage; 748}); 749 750define('jquery',[],function () { 751 /* 752 * Shims jQuery in our build process. Since jQuery is used by a lot of library, 753 * we need to expose jQuery through AMD.. but since that's not really possible 754 * include the script as usual (before TateUI) and throw an error if it's not included. 755 */ 756 try { 757 return jQuery; 758 } catch (e) { 759 throw new Error("TateUI requires jQuery!"); 760 } 761}); 762define('components/TateNotification',['jquery', 'components/TateStorage'], function ($, TateStorage) { 763 var TateNotification = function (options) { 764 options = options || {}; 765 var me = this; 766 767 if ('storage_item' in options && options.storage_item !== null) { 768 this.storage_item = options.storage_item; 769 } else { 770 throw new Error('Tate Storage needs a \'storage_item\' parameter'); 771 } 772 773 this.markup = [ 774 '<div id="' + this.storage_item + '_NOTIFICATION" class="notification-banner notification-banner--p
774opup notification-banner--type__' + options.type + ' notification-banner--format__' + options.format + '">', 775 ' <div class="notification-banner__inner">' 776 ].join('\n'); 777 778 if (options.title) { 779 this.markup += [ 780 ' <h2 class="notification-banner__title">' + options.title + '</h2>' 781 ].join('\n'); 782 } else { 783 this.paragraph_style = '_no-title' 784 }; 785 786 if (options.format == 'slim') { 787 this.markup += [ 788 ' <p class="notification-banner__text">' + options.message + '', 789 ' <a class="notification-banner__anchor" href="' + options.anchor_link + '">' + options.anchor_text + '</a>', 790 ' </p>', 791 ' <div class="btn-row notification-banner__dismiss-button">', 792 ' <button id="DISMISS_' + this.storage_item + '_NOTIFICATION" class="btn btn--style__icon">', 793 ' <i class="btn__icon icon--close"></i>', 794 ' <span class="btn__text">Dismiss</span>', 795 ' </button>', 796 ' </div>', 797 ' </div>', 798 '</div>' 799 ].join('\n'); 800 } else { 801 // Can now add multiple links to a message by using the 'shortcodes' "link0, link1, link2" and having the appropriate links and text in the arrays 802 link_counter = 0; 803 $(options.anchor_link).each(function(){ 804 //new RegExp(search, 'g') 805 options.message = options.message.replace(new RegExp('Link'+link_counter, 'g'), '<a class="notification-banner__anchor" href="' + options.anchor_link[link_counter] + '">' + options.anchor_text[link_counter] + '</a>' ); 806 link_counter++; 807 }); 808 809 this.markup += [ 810 ' <p class="notification-banner__text ' + this.paragraph_style + '">' + options.message + '', 811 ' </p>', 812 ' <div class="btn-row notification-banner__dismiss-button">', 813 ' <button id="DISMISS_' + this.storage_item + '_NOTIFICATION" class="btn--type__white">', 814 ' <span class="btn__text">' + options.button_text + '</span>', 815 ' </button>', 816 ' </div>', 817 ' </div>', 818 '</div>' 819 ].join('\n'); 820 } 821 $(document).ready(function () { 822 me.init(); 823 }); 824 }; 825 826 TateNotification.prototype = { 827 init: function () { 828 this.storage = new TateStorage({ 829 useCookie: true 830 }); 831 832 if (!this.get_storage()) { 833 this.inject_markup(); 834 } 835 }, 836 837 get_storage: function () { 838 return this.storage.find(this.storage_item); 839 }, 840 841 inject_markup: function () { 842 var me = this; 843 $('#notifications-footer').append(this.markup); 844 $('#' + me.storage_item + '_NOTIFICATION').css('display', 'none').slideToggle(); 845 this.register_events(); 846 }, 847 848 register_events: function () { 849 var me = this; 850 851 $('#DISMISS_' + this.storage_item + '_NOTIFICATION').on('click', function (e) { 852 e.preventDefault(); 853 854 me.set_localstorage(); 855 $('#' + me.storage_item + '_NOTIFICATION').remove(); 856 }); 857 }, 858 859 set_localstorage: function () { 860 this.storage.store(this.storage_item, true); 861 }, 862 }; 863 864 return TateNotification; 865}); 866 867 868define('components/TateGOTO',['jquery'], function ($) { 869 /* 870 * @constructor 871 * @description Calls various methods on document ready 872 */ 873 var TateGOTO = function (options) { 874 var me = this; 875 options = options || {}; 876 this.anchors = []; 877 878 if ('bufftop' in options) { 879 this.bufftop = options.bufftop; 880 } else { 881 this.bufftop = 0; 882 } 883 884 $(document).ready(function () { 885 me.extend_easing(); 886 me.init(); 887 }); 888 }; 889 890 TateGOTO.prototype = { 891 /* 892 * @method 893 * @description Factory method for generating TateGOTO anchors 894 */ 895 init: function () { 896 var me = this; 897 898 $('[data-role="tate-goto"]').each(function (){ 899 var $anchor = $(this), 900 $destination = $('[name="' + $(this).attr('href').replace("#", "") + '"]'); 901 902 $anchor.on('click', function (e) { 903 e.preventDefault(); 904 $('html, body').stop().animate({
905 'scrollTop': $destination.offset().top - me.bufftop 906 }, function () { 907 window.anim_lock = null; 908 }); 909 }); 910 }); 911 }, 912 913 /* 914 * @method 915 * @description extends jQuery easing object 916 */ 917 extend_easing: function () { 918 /* Source taken from jQuery UI animation */ 919 if (!('easeInOutQuart' in $.easing)) { 920 $.extend($.easing, { 921 easeInOutQuart: function (x, t, b, c, d) { 922 if ((t/=d/2) < 1) return c/2*t*t*t*t + b; 923 return -c/2 * ((t-=2)*t*t*t - 2) + b; 924 } 925 }); 926 } 927 }, 928 }; 929 930 return TateGOTO; 931}); 932/* 933 _ _ _ _ 934 ___| (_) ___| | __ (_)___ 935/ __| | |/ __| |/ / | / __| 936\__ \ | | (__| < _ | \__ \ 937|___/_|_|\___|_|\_(_)/ |___/ 938 |__/ 939 940 Version: 1.8.1 941 Author: Ken Wheeler 942 Website: http://kenwheeler.github.io 943 Docs: http://kenwheeler.github.io/slick 944 Repo: http://github.com/kenwheeler/slick 945 Issues: http://github.com/kenwheeler/slick/issues 946 947 */ 948/* global window, document, define, jQuery, setInterval, clearInterval */ 949;(function(factory) { 950 'use strict'; 951 if (typeof define === 'function' && define.amd) { 952 define('vendor/slick',['jquery'], factory); 953 } else if (typeof exports !== 'undefined') { 954 module.exports = factory(require('jquery')); 955 } else { 956 factory(jQuery); 957 } 958 959}(function($) { 960 'use strict';
vendor: 29,656 bytes, lines 960-1948
960 961 var Slick = window.Slick || {}; 962 963 Slick = (function() { 964 965 var instanceUid = 0; 966 967 function Slick(element, settings) { 968 969 var _ = this, dataSettings; 970 971 _.defaults = { 972 accessibility: true, 973 adaptiveHeight: false, 974 appendArrows: $(element), 975 appendDots: $(element), 976 arrows: true, 977 asNavFor: null, 978 prevArrow: '<button class="slick-prev" aria-label="Previous" type="button">Previous</button>', 979 nextArrow: '<button class="slick-next" aria-label="Next" type="button">Next</button>', 980 autoplay: false, 981 autoplaySpeed: 3000, 982 centerMode: false, 983 centerPadding: '50px', 984 cssEase: 'ease', 985 customPaging: function(slider, i) { 986 return $('<button type="button" />').text(i + 1); 987 }, 988 dots: false, 989 dotsClass: 'slick-dots', 990 draggable: true, 991 easing: 'linear', 992 edgeFriction: 0.35, 993 fade: false, 994 focusOnSelect: false, 995 focusOnChange: false, 996 infinite: true, 997 initialSlide: 0, 998 lazyLoad: 'ondemand', 999 mobileFirst: false, 1000 pauseOnHover: true, 1001 pauseOnFocus: true, 1002 pauseOnDotsHover: false, 1003 respondTo: 'window', 1004 responsive: null, 1005 rows: 1, 1006 rtl: false, 1007 slide: '', 1008 slidesPerRow: 1, 1009 slidesToShow: 1, 1010 slidesToScroll: 1, 1011 speed: 500, 1012 swipe: true, 1013 swipeToSlide: false, 1014 touchMove: true, 1015 touchThreshold: 5, 1016 useCSS: true, 1017 useTransform: true, 1018 variableWidth: false, 1019 vertical: false, 1020 verticalSwiping: false, 1021 waitForAnimate: true, 1022 zIndex: 1000 1023 }; 1024 1025 _.initials = { 1026 animating: false, 1027 dragging: false, 1028 autoPlayTimer: null, 1029 currentDirection: 0, 1030 currentLeft: null, 1031 currentSlide: 0, 1032 direction: 1, 1033 $dots: null, 1034 listWidth: null, 1035 listHeight: null, 1036 loadIndex: 0, 1037 $nextArrow: null, 1038 $prevArrow: null, 1039 scrolling: false, 1040 slideCount: null, 1041 slideWidth: null, 1042 $slideTrack: null, 1043 $slides: null, 1044 sliding: false, 1045 slideOffset: 0, 1046 swipeLeft: null, 1047 swiping: false, 1048 $list: null, 1049 touchObject: {}, 1050 transformsEnabled: false, 1051 unslicked: false 1052 }; 1053 1054 $.extend(_, _.initials); 1055 1056 _.activeBreakpoint = null; 1057 _.animType = null; 1058 _.animProp = null; 1059 _.breakpoints = []; 1060 _.breakpointSettings = []; 1061 _.cssTransitions = false; 1062 _.focussed = false; 1063 _.interrupted = false; 1064 _.hidden = 'hidden'; 1065 _.paused = true; 1066 _.positionProp = null; 1067 _.respondTo = null; 1068 _.rowCount = 1; 1069 _.shouldClick = true; 1070 _.$slider = $(element); 1071 _.$slidesCache = null; 1072 _.transformType = null; 1073 _.transitionType = null; 1074 _.visibilityChange = 'visibilitychange'; 1075 _.windowWidth = 0; 1076 _.windowTimer = null; 1077 1078 dataSettings = $(element).data('slick') || {}; 1079 1080 _.options = $.extend({}, _.defaults, settings, dataSettings); 1081 1082 _.currentSlide = _.options.initialSlide; 1083 1084 _.originalSettings = _.options; 1085 1086 if (typeof document.mozHidden !== 'undefined') { 1087 _.hidden = 'mozHidden'; 1088 _.visibilityChange = 'mozvisibilitychange'; 1089 } else if (typeof document.webkitHidden !== 'undefined') { 1090 _.hidden = 'webkitHidden'; 1091 _.visibilityChange = 'webkitvisibilitychange'; 1092 } 1093 1094 _.autoPlay = $.proxy(_.autoPlay, _); 1095 _.autoPlayClear = $.proxy(_.autoPlayClear, _); 1096 _.autoPlayIterator = $.proxy(_.autoPlayIterator, _); 1097 _.changeSlide = $.proxy(_.changeSlide, _); 1098 _.clickHandler = $.proxy(_.clickHandler, _); 1099 _.selectHandler = $.proxy(_.selectHandler, _); 1100 _.setPosition = $.proxy(_.setPosition, _); 1101 _.swipeHandler = $.proxy(_.swipeHandler, _); 1102 _.dragHandler = $.proxy(_.dragHandler, _); 1103 _.keyHandler = $.proxy(_.keyHandler, _); 1104 1105 _.instanceUid = instanceUid++; 1106 1107 // A simple way to check for HTML strings 1108 // Strict HTML recognition (must start with <) 1109 // Extracted from jQuery v1.11 source 1110 _.htmlExpr = /^(?:\s*(<[\w\W]+>)[^>]*)$/; 1111 1112 1113 _.registerBreakpoints(); 1114 _.init(true); 1115 1116 } 1117 1118 return Slick; 1119 1120 }()); 1121 1122 Slick.prototype.activateADA = function() { 1123 var _ = this; 1124 1125 _.$slideTrack.find('.slick-active').attr({ 1126 'aria-hidden': 'false' 1127 }).find('a, input, button, select').attr({ 1128 'tabindex': '0' 1129 }); 1130 1131 }; 1132 1133 Slick.prototype.addSlide = Slick.prototype.slickAdd = function(markup, index, addBefore) { 1134 1135 var _ = this; 1136 1137 if (typeof(index) === 'boolean') { 1138 addBefore = index; 1139 index = null; 1140 } else if (index < 0 || (index >= _.slideCount)) { 1141 return false; 1142 } 1143 1144 _.unload(); 1145 1146 if (typeof(index) === 'number') { 1147 if (index === 0 && _.$slides.length === 0) { 1148 $(markup).appendTo(_.$slideTrack); 1149 } else if (addBefore) { 1150 $(markup).insertBefore(_.$slides.eq(index)); 1151 } else { 1152 $(markup).insertAfter(_.$slides.eq(index)); 1153 } 1154 } else { 1155 if (addBefore === true) { 1156 $(markup).prependTo(_.$slideTrack); 1157 } else { 1158 $(markup).appendTo(_.$slideTrack); 1159 } 1160 } 1161 1162 _.$slides = _.$slideTrack.children(this.options.slide); 1163 1164 _.$slideTrack.children(this.options.slide).detach(); 1165 1166 _.$slideTrack.append(_.$slides); 1167 1168 _.$slides.each(function(index, element) { 1169 $(element).attr('data-slick-index', index); 1170 }); 1171 1172 _.$slidesCache = _.$slides; 1173 1174 _.reinit(); 1175 1176 }; 1177 1178 Slick.prototype.animateHeight = function() { 1179 var _ = this; 1180 if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) { 1181 var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true); 1182 _.$list.animate({ 1183 height: targetHeight 1184 }, _.options.speed); 1185 } 1186 }; 1187 1188 Slick.prototype.animateSlide = function(targetLeft, callback) { 1189 1190 var animProps = {}, 1191 _ = this; 1192 1193 _.animateHeight(); 1194 1195 if (_.options.rtl === true && _.options.vertical === false) { 1196 targetLeft = -targetLeft; 1197 } 1198 if (_.transformsEnabled === false) { 1199 if (_.options.vertical === false) { 1200 _.$slideTrack.animate({ 1201 left: targetLeft 1202 }, _.options.speed, _.options.easing, callback); 1203 } else { 1204 _.$slideTrack.animate({ 1205 top: targetLeft 1206 }, _.options.speed, _.options.easing, callback); 1207 } 1208 1209 } else { 1210 1211 if (_.cssTransitions === false) { 1212 if (_.options.rtl === true) { 1213 _.currentLeft = -(_.currentLeft); 1214 } 1215 $({ 1216 animStart: _.currentLeft 1217 }).animate({ 1218 animStart: targetLeft 1219 }, { 1220 duration: _.options.speed, 1221 easing: _.options.easing, 1222 step: function(now) { 1223 now = Math.ceil(now); 1224 if (_.options.vertical === false) { 1225 animProps[_.animType] = 'translate(' + 1226 now + 'px, 0px)'; 1227 _.$slideTrack.css(animProps); 1228 } else { 1229 animProps[_.animType] = 'translate(0px,' + 1230 now + 'px)'; 1231 _.$slideTrack.css(animProps); 1232 } 1233 }, 1234 complete: function() { 1235 if (callback) { 1236 callback.call(); 1237 } 1238 } 1239 }); 1240 1241 } else { 1242 1243 _.applyTransition(); 1244 targetLeft = Math.ceil(targetLeft); 1245 1246 if (_.options.vertical === false) { 1247 animProps[_.animType] = 'translate3d(' + targetLeft + 'px, 0px, 0px)'; 1248 } else { 1249 animProps[_.animType] = 'translate3d(0px,' + targetLeft + 'px, 0px)'; 1250 } 1251 _.$slideTrack.css(animProps); 1252 1253 if (callback) { 1254 setTimeout(function() { 1255 1256 _.disableTransition(); 1257 1258 callback.call(); 1259 }, _.options.speed); 1260 } 1261 1262 } 1263 1264 } 1265 1266 }; 1267 1268 Slick.prototype.getNavTarget = function() { 1269 1270 var _ = this, 1271 asNavFor = _.options.asNavFor; 1272 1273 if ( asNavFor && asNavFor !== null ) { 1274 asNavFor = $(asNavFor).not(_.$slider); 1275 } 1276 1277 return asNavFor; 1278 1279 }; 1280 1281 Slick.prototype.asNavFor = function(index) { 1282 1283 var _ = this, 1284 asNavFor = _.getNavTarget(); 1285 1286 if ( asNavFor !== null && typeof asNavFor === 'object' ) { 1287 asNavFor.each(function() { 1288 var target = $(this).slick('getSlick'); 1289 if(!target.unslicked) { 1290 target.slideHandler(index, true); 1291 } 1292 }); 1293 } 1294 1295 }; 1296 1297 Slick.prototype.applyTransition = function(slide) { 1298 1299 var _ = this, 1300 transition = {}; 1301 1302 if (_.options.fade === false) { 1303 transition[_.transitionType] = _.transformType + ' ' + _.options.speed + 'ms ' + _.options.cssEase; 1304 } else { 1305 transition[_.transitionType] = 'opacity ' + _.options.speed + 'ms ' + _.options.cssEase; 1306 } 1307 1308 if (_.options.fade === false) { 1309 _.$slideTrack.css(transition); 1310 } else { 1311 _.$slides.eq(slide).css(transition); 1312 } 1313 1314 }; 1315 1316 Slick.prototype.autoPlay = function() { 1317 1318 var _ = this; 1319 1320 _.autoPlayClear(); 1321 1322 if ( _.slideCount > _.options.slidesToShow ) { 1323 _.autoPlayTimer = setInterval( _.autoPlayIterator, _.options.autoplaySpeed ); 1324 } 1325 1326 }; 1327 1328 Slick.prototype.autoPlayClear = function() { 1329 1330 var _ = this; 1331 1332 if (_.autoPlayTimer) { 1333 clearInterval(_.autoPlayTimer); 1334 } 1335 1336 }; 1337 1338 Slick.prototype.autoPlayIterator = function() { 1339 1340 var _ = this, 1341 slideTo = _.currentSlide + _.options.slidesToScroll; 1342 1343 if ( !_.paused && !_.interrupted && !_.focussed ) { 1344 1345 if ( _.options.infinite === false ) { 1346 1347 if ( _.direction === 1 && ( _.currentSlide + 1 ) === ( _.slideCount - 1 )) { 1348 _.direction = 0; 1349 } 1350 1351 else if ( _.direction === 0 ) { 1352 1353 slideTo = _.currentSlide - _.options.slidesToScroll; 1354 1355 if ( _.currentSlide - 1 === 0 ) { 1356 _.direction = 1; 1357 } 1358 1359 } 1360 1361 } 1362 1363 _.slideHandler( slideTo ); 1364 1365 } 1366 1367 }; 1368 1369 Slick.prototype.buildArrows = function() { 1370 1371 var _ = this; 1372 1373 if (_.options.arrows === true ) { 1374 1375 _.$prevArrow = $(_.options.prevArrow).addClass('slick-arrow'); 1376 _.$nextArrow = $(_.options.nextArrow).addClass('slick-arrow'); 1377 1378 if( _.slideCount > _.options.slidesToShow ) { 1379 1380 _.$prevArrow.removeClass('slick-hidden').removeAttr('aria-hidden tabindex'); 1381 _.$nextArrow.removeClass('slick-hidden').removeAttr('aria-hidden tabindex'); 1382 1383 if (_.htmlExpr.test(_.options.prevArrow)) { 1384 _.$prevArrow.prependTo(_.options.appendArrows); 1385 } 1386 1387 if (_.htmlExpr.test(_.options.nextArrow)) { 1388 _.$nextArrow.appendTo(_.options.appendArrows); 1389 } 1390 1391 if (_.options.infinite !== true) { 1392 _.$prevArrow 1393 .addClass('slick-disabled') 1394 .attr('aria-disabled', 'true'); 1395 } 1396 1397 } else { 1398 1399 _.$prevArrow.add( _.$nextArrow ) 1400 1401 .addClass('slick-hidden') 1402 .attr({ 1403 'aria-disabled': 'true', 1404 'tabindex': '-1' 1405 }); 1406 1407 } 1408 1409 } 1410 1411 }; 1412 1413 Slick.prototype.buildDots = function() { 1414 1415 var _ = this, 1416 i, dot; 1417 1418 if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { 1419 1420 _.$slider.addClass('slick-dotted'); 1421 1422 dot = $('<ul />').addClass(_.options.dotsClass); 1423 1424 for (i = 0; i <= _.getDotCount(); i += 1) { 1425 dot.append($('<li />').append(_.options.customPaging.call(this, _, i))); 1426 } 1427 1428 _.$dots = dot.appendTo(_.options.appendDots); 1429 1430 _.$dots.find('li').first().addClass('slick-active'); 1431 1432 } 1433 1434 }; 1435 1436 Slick.prototype.buildOut = function() { 1437 1438 var _ = this; 1439 1440 _.$slides = 1441 _.$slider 1442 .children( _.options.slide + ':not(.slick-cloned)') 1443 .addClass('slick-slide'); 1444 1445 _.slideCount = _.$slides.length; 1446 1447 _.$slides.each(function(index, element) { 1448 $(element) 1449 .attr('data-slick-index', index) 1450 .data('originalStyling', $(element).attr('style') || ''); 1451 }); 1452 1453 _.$slider.addClass('slick-slider'); 1454 1455 _.$slideTrack = (_.slideCount === 0) ? 1456 $('<div class="slick-track"/>').appendTo(_.$slider) : 1457 _.$slides.wrapAll('<div class="slick-track"/>').parent(); 1458 1459 _.$list = _.$slideTrack.wrap( 1460 '<div class="slick-list"/>').parent(); 1461 _.$slideTrack.css('opacity', 0); 1462 1463 if (_.options.centerMode === true || _.options.swipeToSlide === true) { 1464 _.options.slidesToScroll = 1; 1465 } 1466 1467 $('img[data-lazy]', _.$slider).not('[src]').addClass('slick-loading'); 1468 1469 _.setupInfinite(); 1470 1471 _.buildArrows(); 1472 1473 _.buildDots(); 1474 1475 _.updateDots(); 1476 1477 1478 _.setSlideClasses(typeof _.currentSlide === 'number' ? _.currentSlide : 0); 1479 1480 if (_.options.draggable === true) { 1481 _.$list.addClass('draggable'); 1482 } 1483 1484 }; 1485 1486 Slick.prototype.buildRows = function() { 1487 1488 var _ = this, a, b, c, newSlides, numOfSlides, originalSlides,slidesPerSection; 1489 1490 newSlides = document.createDocumentFragment(); 1491 originalSlides = _.$slider.children(); 1492 1493 if(_.options.rows > 0) { 1494 1495 slidesPerSection = _.options.slidesPerRow * _.options.rows; 1496 numOfSlides = Math.ceil( 1497 originalSlides.length / slidesPerSection 1498 ); 1499 1500 for(a = 0; a < numOfSlides; a++){ 1501 var slide = document.createElement('div'); 1502 for(b = 0; b < _.options.rows; b++) { 1503 var row = document.createElement('div'); 1504 for(c = 0; c < _.options.slidesPerRow; c++) { 1505 var target = (a * slidesPerSection + ((b * _.options.slidesPerRow) + c)); 1506 if (originalSlides.get(target)) { 1507 row.appendChild(originalSlides.get(target)); 1508 } 1509 } 1510 slide.appendChild(row); 1511 } 1512 newSlides.appendChild(slide); 1513 } 1514 1515 _.$slider.empty().append(newSlides); 1516 _.$slider.children().children().children() 1517 .css({ 1518 'width':(100 / _.options.slidesPerRow) + '%', 1519 'display': 'inline-block' 1520 }); 1521 1522 } 1523 1524 }; 1525 1526 Slick.prototype.checkResponsive = function(initial, forceUpdate) { 1527 1528 var _ = this, 1529 breakpoint, targetBreakpoint, respondToWidth, triggerBreakpoint = false; 1530 var sliderWidth = _.$slider.width(); 1531 var windowWidth = window.innerWidth || $(window).width(); 1532 1533 if (_.respondTo === 'window') { 1534 respondToWidth = windowWidth; 1535 } else if (_.respondTo === 'slider') { 1536 respondToWidth = sliderWidth; 1537 } else if (_.respondTo === 'min') { 1538 respondToWidth = Math.min(windowWidth, sliderWidth); 1539 } 1540 1541 if ( _.options.responsive && 1542 _.options.responsive.length && 1543 _.options.responsive !== null) { 1544 1545 targetBreakpoint = null; 1546 1547 for (breakpoint in _.breakpoints) { 1548 if (_.breakpoints.hasOwnProperty(breakpoint)) { 1549 if (_.originalSettings.mobileFirst === false) { 1550 if (respondToWidth < _.breakpoints[breakpoint]) { 1551 targetBreakpoint = _.breakpoints[breakpoint]; 1552 } 1553 } else { 1554 if (respondToWidth > _.breakpoints[breakpoint]) { 1555 targetBreakpoint = _.breakpoints[breakpoint]; 1556 } 1557 } 1558 } 1559 } 1560 1561 if (targetBreakpoint !== null) { 1562 if (_.activeBreakpoint !== null) { 1563 if (targetBreakpoint !== _.activeBreakpoint || forceUpdate) { 1564 _.activeBreakpoint = 1565 targetBreakpoint; 1566 if (_.breakpointSettings[targetBreakpoint] === 'unslick') { 1567 _.unslick(targetBreakpoint); 1568 } else { 1569 _.options = $.extend({}, _.originalSettings, 1570 _.breakpointSettings[ 1571 targetBreakpoint]); 1572 if (initial === true) { 1573 _.currentSlide = _.options.initialSlide; 1574 } 1575 _.refresh(initial); 1576 } 1577 triggerBreakpoint = targetBreakpoint; 1578 } 1579 } else { 1580 _.activeBreakpoint = targetBreakpoint; 1581 if (_.breakpointSettings[targetBreakpoint] === 'unslick') { 1582 _.unslick(targetBreakpoint); 1583 } else { 1584 _.options = $.extend({}, _.originalSettings, 1585 _.breakpointSettings[ 1586 targetBreakpoint]); 1587 if (initial === true) { 1588 _.currentSlide = _.options.initialSlide; 1589 } 1590 _.refresh(initial); 1591 } 1592 triggerBreakpoint = targetBreakpoint; 1593 } 1594 } else { 1595 if (_.activeBreakpoint !== null) { 1596 _.activeBreakpoint = null; 1597 _.options = _.originalSettings; 1598 if (initial === true) { 1599 _.currentSlide = _.options.initialSlide; 1600 } 1601 _.refresh(initial); 1602 triggerBreakpoint = targetBreakpoint; 1603 } 1604 } 1605 1606 // only trigger breakpoints during an actual break. not on initialize. 1607 if( !initial && triggerBreakpoint !== false ) { 1608 _.$slider.trigger('breakpoint', [_, triggerBreakpoint]); 1609 } 1610 } 1611 1612 }; 1613 1614 Slick.prototype.changeSlide = function(event, dontAnimate) { 1615 1616 var _ = this, 1617 $target = $(event.currentTarget), 1618 indexOffset, slideOffset, unevenOffset; 1619 1620 // If target is a link, prevent default action. 1621 if($target.is('a')) { 1622 event.preventDefault(); 1623 } 1624 1625 // If target is not the <li> element (ie: a child), find the <li>. 1626 if(!$target.is('li')) { 1627 $target = $target.closest('li'); 1628 } 1629 1630 unevenOffset = (_.slideCount % _.options.slidesToScroll !== 0); 1631 indexOffset = unevenOffset ? 0 : (_.slideCount - _.currentSlide) % _.options.slidesToScroll; 1632 1633 switch (event.data.message) { 1634 1635 case 'previous': 1636 slideOffset = indexOffset === 0 ? _.options.slidesToScroll : _.options.slidesToShow - indexOffset; 1637 if (_.slideCount > _.options.slidesToShow) { 1638 _.slideHandler(_.currentSlide - slideOffset, false, dontAnimate); 1639 } 1640 break; 1641 1642 case 'next': 1643 slideOffset = indexOffset === 0 ? _.options.slidesToScroll : indexOffset; 1644 if (_.slideCount > _.options.slidesToShow) { 1645 _.slideHandler(_.currentSlide + slideOffset, false, dontAnimate); 1646 } 1647 break; 1648 1649 case 'index': 1650 var index = event.data.index === 0 ? 0 : 1651 event.data.index || $target.index() * _.options.slidesToScroll; 1652 1653 _.slideHandler(_.checkNavigable(index), false, dontAnimate); 1654 $target.children().trigger('focus'); 1655 break; 1656 1657 default: 1658 return; 1659 } 1660 1661 }; 1662 1663 Slick.prototype.checkNavigable = function(index) { 1664 1665 var _ = this, 1666 navigables, prevNavigable; 1667 1668 navigables = _.getNavigableIndexes(); 1669 prevNavigable = 0; 1670 if (index > navigables[navigables.length - 1]) { 1671 index = navigables[navigables.length - 1]; 1672 } else { 1673 for (var n in navigables) { 1674 if (index < navigables[n]) { 1675 index = prevNavigable; 1676 break; 1677 } 1678 prevNavigable = navigables[n]; 1679 } 1680 } 1681 1682 return index; 1683 }; 1684 1685 Slick.prototype.cleanUpEvents = function() { 1686 1687 var _ = this; 1688 1689 if (_.options.dots && _.$dots !== null) { 1690 1691 $('li', _.$dots) 1692 .off('click.slick', _.changeSlide) 1693 .off('mouseenter.slick', $.proxy(_.interrupt, _, true)) 1694 .off('mouseleave.slick', $.proxy(_.interrupt, _, false)); 1695 1696 if (_.options.accessibility === true) { 1697 _.$dots.off('keydown.slick', _.keyHandler); 1698 } 1699 } 1700 1701 _.$slider.off('focus.slick blur.slick'); 1702 1703 if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { 1704 _.$prevArrow && _.$prevArrow.off('click.slick', _.changeSlide); 1705 _.$nextArrow && _.$nextArrow.off('click.slick', _.changeSlide); 1706 1707 if (_.options.accessibility === true) { 1708 _.$prevArrow && _.$prevArrow.off('keydown.slick', _.keyHandler); 1709 _.$nextArrow && _.$nextArrow.off('keydown.slick', _.keyHandler); 1710 } 1711 } 1712 1713 _.$list.off('touchstart.slick mousedown.slick', _.swipeHandler); 1714 _.$list.off('touchmove.slick mousemove.slick', _.swipeHandler); 1715 _.$list.off('touchend.slick mouseup.slick', _.swipeHandler); 1716 _.$list.off('touchcancel.slick mouseleave.slick', _.swipeHandler); 1717 1718 _.$list.off('click.slick', _.clickHandler); 1719 1720 $(document).off(_.visibilityChange, _.visibility); 1721 1722 _.cleanUpSlideEvents(); 1723 1724 if (_.options.accessibility === true) { 1725 _.$list.off('keydown.slick', _.keyHandler); 1726 } 1727 1728 if (_.options.focusOnSelect === true) { 1729 $(_.$slideTrack).children().off('click.slick', _.selectHandler); 1730 } 1731 1732 $(window).off('orientationchange.slick.slick-' + _.instanceUid, _.orientationChange); 1733 1734 $(window).off('resize.slick.slick-' + _.instanceUid, _.resize); 1735 1736 $('[draggable!=true]', _.$slideTrack).off('dragstart', _.preventDefault); 1737 1738 $(window).off('load.slick.slick-' + _.instanceUid, _.setPosition); 1739 1740 }; 1741 1742 Slick.prototype.cleanUpSlideEvents = function() { 1743 1744 var _ = this; 1745 1746 _.$list.off('mouseenter.slick', $.proxy(_.interrupt, _, true)); 1747 _.$list.off('mouseleave.slick', $.proxy(_.interrupt, _, false)); 1748 1749 }; 1750 1751 Slick.prototype.cleanUpRows = function() { 1752 1753 var _ = this, originalSlides; 1754 1755 if(_.options.rows > 0) { 1756 originalSlides = _.$slides.children().children(); 1757 originalSlides.removeAttr('style'); 1758 _.$slider.empty().append(originalSlides); 1759 } 1760 1761 }; 1762 1763 Slick.prototype.clickHandler = function(event) { 1764 1765 var _ = this; 1766 1767 if (_.shouldClick === false) { 1768 event.stopImmediatePropagation(); 1769 event.stopPropagation(); 1770 event.preventDefault(); 1771 } 1772 1773 }; 1774 1775 Slick.prototype.destroy = function(refresh) { 1776 1777 var _ = this; 1778 1779 _.autoPlayClear(); 1780 1781 _.touchObject = {}; 1782 1783 _.cleanUpEvents(); 1784 1785 $('.slick-cloned', _.$slider).detach(); 1786 1787 if (_.$dots) { 1788 _.$dots.remove(); 1789 } 1790 1791 if ( _.$prevArrow && _.$prevArrow.length ) { 1792 1793 _.$prevArrow 1794 .removeClass('slick-disabled slick-arrow slick-hidden') 1795 .removeAttr('aria-hidden aria-disabled tabindex') 1796 .css('display',''); 1797 1798 if ( _.htmlExpr.test( _.options.prevArrow )) { 1799 _.$prevArrow.remove(); 1800 } 1801 } 1802 1803 if ( _.$nextArrow && _.$nextArrow.length ) { 1804 1805 _.$nextArrow 1806 .removeClass('slick-disabled slick-arrow slick-hidden') 1807 .removeAttr('aria-hidden aria-disabled tabindex') 1808 .css('display',''); 1809 1810 if ( _.htmlExpr.test( _.options.nextArrow )) { 1811 _.$nextArrow.remove(); 1812 } 1813 } 1814 1815 1816 if (_.$slides) { 1817 1818 _.$slides 1819 .removeClass('slick-slide slick-active slick-center slick-visible slick-current') 1820 .removeAttr('aria-hidden') 1821 .removeAttr('data-slick-index') 1822 .each(function(){ 1823 $(this).attr('style', $(this).data('originalStyling')); 1824 }); 1825 1826 _.$slideTrack.children(this.options.slide).detach(); 1827 1828 _.$slideTrack.detach(); 1829 1830 _.$list.detach(); 1831 1832 _.$slider.append(_.$slides); 1833 } 1834 1835 _.cleanUpRows(); 1836 1837 _.$slider.removeClass('slick-slider'); 1838 _.$slider.removeClass('slick-initialized'); 1839 _.$slider.removeClass('slick-dotted'); 1840 1841 _.unslicked = true; 1842 1843 if(!refresh) { 1844 _.$slider.trigger('destroy', [_]); 1845 } 1846 1847 }; 1848 1849 Slick.prototype.disableTransition = function(slide) { 1850 1851 var _ = this, 1852 transition = {}; 1853 1854 transition[_.transitionType] = ''; 1855 1856 if (_.options.fade === false) { 1857 _.$slideTrack.css(transition); 1858 } else { 1859 _.$slides.eq(slide).css(transition); 1860 } 1861 1862 }; 1863 1864 Slick.prototype.fadeSlide = function(slideIndex, callback) { 1865 1866 var _ = this; 1867 1868 if (_.cssTransitions === false) { 1869 1870 _.$slides.eq(slideIndex).css({ 1871 zIndex: _.options.zIndex 1872 }); 1873 1874 _.$slides.eq(slideIndex).animate({ 1875 opacity: 1 1876 }, _.options.speed, _.options.easing, callback); 1877 1878 } else { 1879 1880 _.applyTransition(slideIndex); 1881 1882 _.$slides.eq(slideIndex).css({ 1883 opacity: 1, 1884 zIndex: _.options.zIndex 1885 }); 1886 1887 if (callback) { 1888 setTimeout(function() { 1889 1890 _.disableTransition(slideIndex); 1891 1892 callback.call(); 1893 }, _.options.speed); 1894 } 1895 1896 } 1897 1898 }; 1899 1900 Slick.prototype.fadeSlideOut = function(slideIndex) { 1901 1902 var _ = this; 1903 1904 if (_.cssTransitions === false) { 1905 1906 _.$slides.eq(slideIndex).animate({ 1907 opacity: 0, 1908 zIndex: _.options.zIndex - 2 1909 }, _.options.speed, _.options.easing); 1910 1911 } else { 1912 1913 _.applyTransition(slideIndex); 1914 1915 _.$slides.eq(slideIndex).css({ 1916 opacity: 0, 1917 zIndex: _.options.zIndex - 2 1918 }); 1919 1920 } 1921 1922 }; 1923 1924 Slick.prototype.filterSlides = Slick.prototype.slickFilter = function(filter) { 1925 1926 var _ = this; 1927 1928 if (filter !== null) { 1929 1930 _.$slidesCache = _.$slides; 1931 1932 _.unload(); 1933 1934 _.$slideTrack.children(this.options.slide).detach(); 1935 1936 _.$slidesCache.filter(filter).appendTo(_.$slideTrack); 1937 1938 _.reinit(); 1939 1940 } 1941 1942 }; 1943 1944 Slick.prototype.focusHandler = function() { 1945 1946 var _ = this; 1947 1948
vendor: 3,201 bytes, lines 1948-2043
1948// If any child element receives focus within the slider we need to pause the autoplay 1949 _.$slider 1950 .off('focus.slick blur.slick') 1951 .on( 1952 'focus.slick', 1953 '*', 1954 function(event) { 1955 var $sf = $(this); 1956 1957 setTimeout(function() { 1958 if( _.options.pauseOnFocus ) { 1959 if ($sf.is(':focus')) { 1960 _.focussed = true; 1961 _.autoPlay(); 1962 } 1963 } 1964 }, 0); 1965 } 1966 ).on( 1967 'blur.slick', 1968 '*', 1969 function(event) { 1970 var $sf = $(this); 1971 1972 // When a blur occurs on any elements within the slider we become unfocused 1973 if( _.options.pauseOnFocus ) { 1974 _.focussed = false; 1975 _.autoPlay(); 1976 } 1977 } 1978 ); 1979 }; 1980 1981 Slick.prototype.getCurrent = Slick.prototype.slickCurrentSlide = function() { 1982 1983 var _ = this; 1984 return _.currentSlide; 1985 1986 }; 1987 1988 Slick.prototype.getDotCount = function() { 1989 1990 var _ = this; 1991 1992 var breakPoint = 0; 1993 var counter = 0; 1994 var pagerQty = 0; 1995 1996 if (_.options.infinite === true) { 1997 if (_.slideCount <= _.options.slidesToShow) { 1998 ++pagerQty; 1999 } else { 2000 while (breakPoint < _.slideCount) { 2001 ++pagerQty; 2002 breakPoint = counter + _.options.slidesToScroll; 2003 counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow; 2004 } 2005 } 2006 } else if (_.options.centerMode === true) { 2007 pagerQty = _.slideCount; 2008 } else if(!_.options.asNavFor) { 2009 pagerQty = 1 + Math.ceil((_.slideCount - _.options.slidesToShow) / _.options.slidesToScroll); 2010 }else { 2011 while (breakPoint < _.slideCount) { 2012 ++pagerQty; 2013 breakPoint = counter + _.options.slidesToScroll; 2014 counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow; 2015 } 2016 } 2017 2018 return pagerQty - 1; 2019 2020 }; 2021 2022 Slick.prototype.getLeft = function(slideIndex) { 2023 2024 var _ = this, 2025 targetLeft, 2026 verticalHeight, 2027 verticalOffset = 0, 2028 targetSlide, 2029 coef; 2030 2031 _.slideOffset = 0; 2032 verticalHeight = _.$slides.first().outerHeight(true); 2033 2034 if (_.options.infinite === true) { 2035 if (_.slideCount > _.options.slidesToShow) { 2036 _.slideOffset = (_.slideWidth * _.options.slidesToShow) * -1; 2037 coef = -1 2038 2039 if (_.options.vertical === true && _.options.centerMode === true) { 2040 if (_.options.slidesToShow === 2) { 2041 coef = -1.5; 2042 } else if (_.options.slidesToShow === 1) { 2043 coef = -2
vendor: 4,950 bytes, lines 2043-2172
2043 2044 } 2045 } 2046 verticalOffset = (verticalHeight * _.options.slidesToShow) * coef; 2047 } 2048 if (_.slideCount % _.options.slidesToScroll !== 0) { 2049 if (slideIndex + _.options.slidesToScroll > _.slideCount && _.slideCount > _.options.slidesToShow) { 2050 if (slideIndex > _.slideCount) { 2051 _.slideOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * _.slideWidth) * -1; 2052 verticalOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * verticalHeight) * -1; 2053 } else { 2054 _.slideOffset = ((_.slideCount % _.options.slidesToScroll) * _.slideWidth) * -1; 2055 verticalOffset = ((_.slideCount % _.options.slidesToScroll) * verticalHeight) * -1; 2056 } 2057 } 2058 } 2059 } else { 2060 if (slideIndex + _.options.slidesToShow > _.slideCount) { 2061 _.slideOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * _.slideWidth; 2062 verticalOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * verticalHeight; 2063 } 2064 } 2065 2066 if (_.slideCount <= _.options.slidesToShow) { 2067 _.slideOffset = 0; 2068 verticalOffset = 0; 2069 } 2070 2071 if (_.options.centerMode === true && _.slideCount <= _.options.slidesToShow) { 2072 _.slideOffset = ((_.slideWidth * Math.floor(_.options.slidesToShow)) / 2) - ((_.slideWidth * _.slideCount) / 2); 2073 } else if (_.options.centerMode === true && _.options.infinite === true) { 2074 _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2) - _.slideWidth; 2075 } else if (_.options.centerMode === true) { 2076 _.slideOffset = 0; 2077 _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2); 2078 } 2079 2080 if (_.options.vertical === false) { 2081 targetLeft = ((slideIndex * _.slideWidth) * -1) + _.slideOffset; 2082 } else { 2083 targetLeft = ((slideIndex * verticalHeight) * -1) + verticalOffset; 2084 } 2085 2086 if (_.options.variableWidth === true) { 2087 2088 if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) { 2089 targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex); 2090 } else { 2091 targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow); 2092 } 2093 2094 if (_.options.rtl === true) { 2095 if (targetSlide[0]) { 2096 targetLeft = (_.$slideTrack.width() - targetSlide[0].offsetLeft - targetSlide.width()) * -1; 2097 } else { 2098 targetLeft = 0; 2099 } 2100 } else { 2101 targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0; 2102 } 2103 2104 if (_.options.centerMode === true) { 2105 if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) { 2106 targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex); 2107 } else { 2108 targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow + 1); 2109 } 2110 2111 if (_.options.rtl === true) { 2112 if (targetSlide[0]) { 2113 targetLeft = (_.$slideTrack.width() - targetSlide[0].offsetLeft - targetSlide.width()) * -1; 2114 } else { 2115 targetLeft = 0; 2116 } 2117 } else { 2118 targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0; 2119 } 2120 2121 targetLeft += (_.$list.width() - targetSlide.outerWidth()) / 2; 2122 } 2123 } 2124 2125 return targetLeft; 2126 2127 }; 2128 2129 Slick.prototype.getOption = Slick.prototype.slickGetOption = function(option) { 2130 2131 var _ = this; 2132 2133 return _.options[option]; 2134 2135 }; 2136 2137 Slick.prototype.getNavigableIndexes = function() { 2138 2139 var _ = this, 2140 breakPoint = 0, 2141 counter = 0, 2142 indexes = [], 2143 max; 2144 2145 if (_.options.infinite === false) { 2146 max = _.slideCount; 2147 } else { 2148 breakPoint = _.options.slidesToScroll * -1; 2149 counter = _.options.slidesToScroll * -1; 2150 max = _.slideCount * 2; 2151 } 2152 2153 while (breakPoint < max) { 2154 indexes.push(breakPoint); 2155 breakPoint = counter + _.options.slidesToScroll; 2156 counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow; 2157 } 2158 2159 return indexes; 2160 2161 }; 2162 2163 Slick.prototype.getSlick = function() { 2164 2165 return this; 2166 2167 }; 2168 2169 Slick.prototype.getSlideCount = function() { 2170 2171 var _ = this, 2172 slidesTraversed, swipedSlide,
2172swipeTarget, centerOffset; 2173 2174 centerOffset = _.options.centerMode === true ? Math.floor(_.$list.width() / 2) : 0; 2175 swipeTarget = (_.swipeLeft * -1) + centerOffset; 2176 2177 if (_.options.swipeToSlide === true) { 2178 2179 _.$slideTrack.find('.slick-slide').each(function(index, slide) { 2180 2181 var slideOuterWidth, slideOffset, slideRightBoundary; 2182 slideOuterWidth = $(slide).outerWidth(); 2183 slideOffset = slide.offsetLeft; 2184 if (_.options.centerMode !== true) { 2185 slideOffset += (slideOuterWidth / 2); 2186 } 2187 2188 slideRightBoundary = slideOffset + (slideOuterWidth); 2189 2190 if (swipeTarget < slideRightBoundary) { 2191 swipedSlide = slide; 2192 return false; 2193 } 2194 }); 2195 2196 slidesTraversed = Math.abs($(swipedSlide).attr('data-slick-index') - _.currentSlide) || 1; 2197 2198 return slidesTraversed; 2199 2200 } else { 2201 return _.options.slidesToScroll; 2202 } 2203 2204 }; 2205 2206 Slick.prototype.goTo = Slick.prototype.slickGoTo = function(slide, dontAnimate) { 2207 2208 var _ = this; 2209 2210 _.changeSlide({ 2211 data: { 2212 message: 'index', 2213 index: parseInt(slide) 2214 } 2215 }, dontAnimate); 2216 2217 }; 2218 2219 Slick.prototype.init = function(creation) { 2220 2221 var _ = this; 2222 2223 if (!$(_.$slider).hasClass('slick-initialized')) { 2224 2225 $(_.$slider).addClass('slick-initialized'); 2226 2227 _.buildRows(); 2228 _.buildOut(); 2229 _.setProps(); 2230 _.startLoad(); 2231 _.loadSlider(); 2232 _.initializeEvents(); 2233 _.updateArrows(); 2234 _.updateDots(); 2235 _.checkResponsive(true); 2236 _.focusHandler(); 2237 2238 } 2239 2240 if (creation) { 2241 _.$slider.trigger('init', [_]); 2242 } 2243 2244 if (_.options.accessibility === true) { 2245 _.initADA(); 2246 } 2247 2248 if ( _.options.autoplay ) { 2249 2250 _.paused = false;
vendor: 1,103 bytes, lines 2251-2282
2251 _.autoPlay(); 2252 2253 } 2254 2255 }; 2256 2257 Slick.prototype.initADA = function() { 2258 var _ = this, 2259 numDotGroups = Math.ceil(_.slideCount / _.options.slidesToShow), 2260 tabControlIndexes = _.getNavigableIndexes().filter(function(val) { 2261 return (val >= 0) && (val < _.slideCount); 2262 }); 2263 2264 _.$slides.add(_.$slideTrack.find('.slick-cloned')).attr({ 2265 'aria-hidden': 'true', 2266 'tabindex': '-1' 2267 }).find('a, input, button, select').attr({ 2268 'tabindex': '-1' 2269 }); 2270 2271 if (_.$dots !== null) { 2272 _.$slides.not(_.$slideTrack.find('.slick-cloned')).each(function(i) { 2273 var slideControlIndex = tabControlIndexes.indexOf(i); 2274 2275 $(this).attr({ 2276 'role': 'tabpanel', 2277 'id': 'slick-slide' + _.instanceUid + i, 2278 'tabindex': -1 2279 }); 2280 2281 if (slideControlIndex !== -1) { 2282 var ariaButtonControl = 'slick-slide-control' + _.instanceUid + slideControlIndex
vendor: 29,020 bytes, lines 2282-3288
2282 2283 if ($('#' + ariaButtonControl).length) { 2284 $(this).attr({ 2285 'aria-describedby': ariaButtonControl 2286 }); 2287 } 2288 } 2289 }); 2290 2291 _.$dots.attr('role', 'tablist').find('li').each(function(i) { 2292 var mappedSlideIndex = tabControlIndexes[i]; 2293 2294 $(this).attr({ 2295 'role': 'presentation' 2296 }); 2297 2298 $(this).find('button').first().attr({ 2299 'role': 'tab', 2300 'id': 'slick-slide-control' + _.instanceUid + i, 2301 'aria-controls': 'slick-slide' + _.instanceUid + mappedSlideIndex, 2302 'aria-label': (i + 1) + ' of ' + numDotGroups, 2303 'aria-selected': null, 2304 'tabindex': '-1' 2305 }); 2306 2307 }).eq(_.currentSlide).find('button').attr({ 2308 'aria-selected': 'true', 2309 'tabindex': '0' 2310 }).end(); 2311 } 2312 2313 for (var i=_.currentSlide, max=i+_.options.slidesToShow; i < max; i++) { 2314 if (_.options.focusOnChange) { 2315 _.$slides.eq(i).attr({'tabindex': '0'}); 2316 } else { 2317 _.$slides.eq(i).removeAttr('tabindex'); 2318 } 2319 } 2320 2321 _.activateADA(); 2322 2323 }; 2324 2325 Slick.prototype.initArrowEvents = function() { 2326 2327 var _ = this; 2328 2329 if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { 2330 _.$prevArrow 2331 .off('click.slick') 2332 .on('click.slick', { 2333 message: 'previous' 2334 }, _.changeSlide); 2335 _.$nextArrow 2336 .off('click.slick') 2337 .on('click.slick', { 2338 message: 'next' 2339 }, _.changeSlide); 2340 2341 if (_.options.accessibility === true) { 2342 _.$prevArrow.on('keydown.slick', _.keyHandler); 2343 _.$nextArrow.on('keydown.slick', _.keyHandler); 2344 } 2345 } 2346 2347 }; 2348 2349 Slick.prototype.initDotEvents = function() { 2350 2351 var _ = this; 2352 2353 if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { 2354 $('li', _.$dots).on('click.slick', { 2355 message: 'index' 2356 }, _.changeSlide); 2357 2358 if (_.options.accessibility === true) { 2359 _.$dots.on('keydown.slick', _.keyHandler); 2360 } 2361 } 2362 2363 if (_.options.dots === true && _.options.pauseOnDotsHover === true && _.slideCount > _.options.slidesToShow) { 2364 2365 $('li', _.$dots) 2366 .on('mouseenter.slick', $.proxy(_.interrupt, _, true)) 2367 .on('mouseleave.slick', $.proxy(_.interrupt, _, false)); 2368 2369 } 2370 2371 }; 2372 2373 Slick.prototype.initSlideEvents = function() { 2374 2375 var _ = this; 2376 2377 if ( _.options.pauseOnHover ) { 2378 2379 _.$list.on('mouseenter.slick', $.proxy(_.interrupt, _, true)); 2380 _.$list.on('mouseleave.slick', $.proxy(_.interrupt, _, false)); 2381 2382 } 2383 2384 }; 2385 2386 Slick.prototype.initializeEvents = function() { 2387 2388 var _ = this; 2389 2390 _.initArrowEvents(); 2391 2392 _.initDotEvents(); 2393 _.initSlideEvents(); 2394 2395 _.$list.on('touchstart.slick mousedown.slick', { 2396 action: 'start' 2397 }, _.swipeHandler); 2398 _.$list.on('touchmove.slick mousemove.slick', { 2399 action: 'move' 2400 }, _.swipeHandler); 2401 _.$list.on('touchend.slick mouseup.slick', { 2402 action: 'end' 2403 }, _.swipeHandler); 2404 _.$list.on('touchcancel.slick mouseleave.slick', { 2405 action: 'end' 2406 }, _.swipeHandler); 2407 2408 _.$list.on('click.slick', _.clickHandler); 2409 2410 $(document).on(_.visibilityChange, $.proxy(_.visibility, _)); 2411 2412 if (_.options.accessibility === true) { 2413 _.$list.on('keydown.slick', _.keyHandler); 2414 } 2415 2416 if (_.options.focusOnSelect === true) { 2417 $(_.$slideTrack).children().on('click.slick', _.selectHandler); 2418 } 2419 2420 $(window).on('orientationchange.slick.slick-' + _.instanceUid, $.proxy(_.orientationChange, _)); 2421 2422 $(window).on('resize.slick.slick-' + _.instanceUid, $.proxy(_.resize, _)); 2423 2424 $('[draggable!=true]', _.$slideTrack).on('dragstart', _.preventDefault); 2425 2426 $(window).on('load.slick.slick-' + _.instanceUid, _.setPosition); 2427 $(_.setPosition); 2428 2429 }; 2430 2431 Slick.prototype.initUI = function() { 2432 2433 var _ = this; 2434 2435 if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { 2436 2437 _.$prevArrow.show(); 2438 _.$nextArrow.show(); 2439 2440 } 2441 2442 if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { 2443 2444 _.$dots.show(); 2445 2446 } 2447 2448 }; 2449 2450 Slick.prototype.keyHandler = function(event) { 2451 2452 var _ = this; 2453 //Dont slide if the cursor is inside the form fields and arrow keys are pressed 2454 if(!event.target.tagName.match('TEXTAREA|INPUT|SELECT')) { 2455 if (event.keyCode === 37 && _.options.accessibility === true) { 2456 _.changeSlide({ 2457 data: { 2458 message: _.options.rtl === true ? 'next' : 'previous' 2459 } 2460 }); 2461 } else if (event.keyCode === 39 && _.options.accessibility === true) { 2462 _.changeSlide({ 2463 data: { 2464 message: _.options.rtl === true ? 'previous' : 'next' 2465 } 2466 }); 2467 } 2468 } 2469 2470 }; 2471 2472 Slick.prototype.lazyLoad = function() { 2473 2474 var _ = this, 2475 loadRange, cloneRange, rangeStart, rangeEnd; 2476 2477 function loadImages(imagesScope) { 2478 2479 $('img[data-lazy]', imagesScope).each(function() { 2480 2481 var image = $(this), 2482 imageSource = $(this).attr('data-lazy'), 2483 imageSrcSet = $(this).attr('data-srcset'), 2484 imageSizes = $(this).attr('data-sizes') || _.$slider.attr('data-sizes'), 2485 imageToLoad = document.createElement('img'); 2486 2487 imageToLoad.onload = function() { 2488 2489 image 2490 .animate({ opacity: 0 }, 100, function() { 2491 2492 if (imageSrcSet) { 2493 image 2494 .attr('srcset', imageSrcSet ); 2495 2496 if (imageSizes) { 2497 image 2498 .attr('sizes', imageSizes ); 2499 } 2500 } 2501 2502 image 2503 .attr('src', imageSource) 2504 .animate({ opacity: 1 }, 200, function() { 2505 image 2506 .removeAttr('data-lazy data-srcset data-sizes') 2507 .removeClass('slick-loading'); 2508 }); 2509 _.$slider.trigger('lazyLoaded', [_, image, imageSource]); 2510 }); 2511 2512 }; 2513 2514 imageToLoad.onerror = function() { 2515 2516 image 2517 .removeAttr( 'data-lazy' ) 2518 .removeClass( 'slick-loading' ) 2519 .addClass( 'slick-lazyload-error' ); 2520 2521 _.$slider.trigger('lazyLoadError', [ _, image, imageSource ]); 2522 2523 }; 2524 2525 imageToLoad.src = imageSource; 2526 2527 }); 2528 2529 } 2530 2531 if (_.options.centerMode === true) { 2532 if (_.options.infinite === true) { 2533 rangeStart = _.currentSlide + (_.options.slidesToShow / 2 + 1); 2534 rangeEnd = rangeStart + _.options.slidesToShow + 2; 2535 } else { 2536 rangeStart = Math.max(0, _.currentSlide - (_.options.slidesToShow / 2 + 1)); 2537 rangeEnd = 2 + (_.options.slidesToShow / 2 + 1) + _.currentSlide; 2538 } 2539 } else { 2540 rangeStart = _.options.infinite ? _.options.slidesToShow + _.currentSlide : _.currentSlide; 2541 rangeEnd = Math.ceil(rangeStart + _.options.slidesToShow); 2542 if (_.options.fade === true) { 2543 if (rangeStart > 0) rangeStart--; 2544 if (rangeEnd <= _.slideCount) rangeEnd++; 2545 } 2546 } 2547 2548 loadRange = _.$slider.find('.slick-slide').slice(rangeStart, rangeEnd); 2549 2550 if (_.options.lazyLoad === 'anticipated') { 2551 var prevSlide = rangeStart - 1, 2552 nextSlide = rangeEnd, 2553 $slides = _.$slider.find('.slick-slide'); 2554 2555 for (var i = 0; i < _.options.slidesToScroll; i++) { 2556 if (prevSlide < 0) prevSlide = _.slideCount - 1; 2557 loadRange = loadRange.add($slides.eq(prevSlide)); 2558 loadRange = loadRange.add($slides.eq(nextSlide)); 2559 prevSlide--; 2560 nextSlide++; 2561 } 2562 } 2563 2564 loadImages(loadRange); 2565 2566 if (_.slideCount <= _.options.slidesToShow) { 2567 cloneRange = _.$slider.find('.slick-slide'); 2568 loadImages(cloneRange); 2569 } else 2570 if (_.currentSlide >= _.slideCount - _.options.slidesToShow) { 2571 cloneRange = _.$slider.find('.slick-cloned').slice(0, _.options.slidesToShow); 2572 loadImages(cloneRange); 2573 } else if (_.currentSlide === 0) { 2574 cloneRange = _.$slider.find('.slick-cloned').slice(_.options.slidesToShow * -1); 2575 loadImages(cloneRange); 2576 } 2577 2578 }; 2579 2580 Slick.prototype.loadSlider = function() { 2581 2582 var _ = this; 2583 2584 _.setPosition(); 2585 2586 _.$slideTrack.css({ 2587 opacity: 1 2588 }); 2589 2590 _.$slider.removeClass('slick-loading'); 2591 2592 _.initUI(); 2593 2594 if (_.options.lazyLoad === 'progressive') { 2595 _.progressiveLazyLoad(); 2596 } 2597 2598 }; 2599 2600 Slick.prototype.next = Slick.prototype.slickNext = function() { 2601 2602 var _ = this; 2603 2604 _.changeSlide({ 2605 data: { 2606 message: 'next' 2607 } 2608 }); 2609 2610 }; 2611 2612 Slick.prototype.orientationChange = function() { 2613 2614 var _ = this; 2615 2616 _.checkResponsive(); 2617 _.setPosition(); 2618 2619 }; 2620 2621 Slick.prototype.pause = Slick.prototype.slickPause = function() { 2622 2623 var _ = this; 2624 2625 _.autoPlayClear(); 2626 _.paused = true; 2627 2628 }; 2629 2630 Slick.prototype.play = Slick.prototype.slickPlay = function() { 2631 2632 var _ = this; 2633 2634 _.autoPlay(); 2635 _.options.autoplay = true; 2636 _.paused = false; 2637 _.focussed = false; 2638 _.interrupted = false; 2639 2640 }; 2641 2642 Slick.prototype.postSlide = function(index) { 2643 2644 var _ = this; 2645 2646 if( !_.unslicked ) { 2647 2648 _.$slider.trigger('afterChange', [_, index]); 2649 2650 _.animating = false; 2651 2652 if (_.slideCount > _.options.slidesToShow) { 2653 _.setPosition(); 2654 } 2655 2656 _.swipeLeft = null; 2657 2658 if ( _.options.autoplay ) { 2659 _.autoPlay(); 2660 } 2661 2662 if (_.options.accessibility === true) { 2663 _.initADA(); 2664 2665 if (_.options.focusOnChange) { 2666 var $currentSlide = $(_.$slides.get(_.currentSlide)); 2667 $currentSlide.attr('tabindex', 0).focus(); 2668 } 2669 } 2670 2671 } 2672 2673 }; 2674 2675 Slick.prototype.prev = Slick.prototype.slickPrev = function() { 2676 2677 var _ = this; 2678 2679 _.changeSlide({ 2680 data: { 2681 message: 'previous' 2682 } 2683 }); 2684 2685 }; 2686 2687 Slick.prototype.preventDefault = function(event) { 2688 2689 event.preventDefault(); 2690 2691 }; 2692 2693 Slick.prototype.progressiveLazyLoad = function( tryCount ) { 2694 2695 tryCount = tryCount || 1; 2696 2697 var _ = this, 2698 $imgsToLoad = $( 'img[data-lazy]', _.$slider ), 2699 image, 2700 imageSource, 2701 imageSrcSet, 2702 imageSizes, 2703 imageToLoad; 2704 2705 if ( $imgsToLoad.length ) { 2706 2707 image = $imgsToLoad.first(); 2708 imageSource = image.attr('data-lazy'); 2709 imageSrcSet = image.attr('data-srcset'); 2710 imageSizes = image.attr('data-sizes') || _.$slider.attr('data-sizes'); 2711 imageToLoad = document.createElement('img'); 2712 2713 imageToLoad.onload = function() { 2714 2715 if (imageSrcSet) { 2716 image 2717 .attr('srcset', imageSrcSet ); 2718 2719 if (imageSizes) { 2720 image 2721 .attr('sizes', imageSizes ); 2722 } 2723 } 2724 2725 image 2726 .attr( 'src', imageSource ) 2727 .removeAttr('data-lazy data-srcset data-sizes') 2728 .removeClass('slick-loading'); 2729 2730 if ( _.options.adaptiveHeight === true ) { 2731 _.setPosition(); 2732 } 2733 2734 _.$slider.trigger('lazyLoaded', [ _, image, imageSource ]); 2735 _.progressiveLazyLoad(); 2736 2737 }; 2738 2739 imageToLoad.onerror = function() { 2740 2741 if ( tryCount < 3 ) { 2742 2743 /** 2744 * try to load the image 3 times, 2745 * leave a slight delay so we don't get 2746 * servers blocking the request. 2747 */ 2748 setTimeout( function() { 2749 _.progressiveLazyLoad( tryCount + 1 ); 2750 }, 500 ); 2751 2752 } else { 2753 2754 image 2755 .removeAttr( 'data-lazy' ) 2756 .removeClass( 'slick-loading' ) 2757 .addClass( 'slick-lazyload-error' ); 2758 2759 _.$slider.trigger('lazyLoadError', [ _, image, imageSource ]); 2760 2761 _.progressiveLazyLoad(); 2762 2763 } 2764 2765 }; 2766 2767 imageToLoad.src = imageSource; 2768 2769 } else { 2770 2771 _.$slider.trigger('allImagesLoaded', [ _ ]); 2772 2773 } 2774 2775 }; 2776 2777 Slick.prototype.refresh = function( initializing ) { 2778 2779 var _ = this, currentSlide, lastVisibleIndex; 2780 2781 lastVisibleIndex = _.slideCount - _.options.slidesToShow; 2782 2783 // in non-infinite sliders, we don't want to go past the 2784 // last visible index. 2785 if( !_.options.infinite && ( _.currentSlide > lastVisibleIndex )) { 2786 _.currentSlide = lastVisibleIndex; 2787 } 2788 2789 // if less slides than to show, go to start. 2790 if ( _.slideCount <= _.options.slidesToShow ) { 2791 _.currentSlide = 0; 2792 2793 } 2794 2795 currentSlide = _.currentSlide; 2796 2797 _.destroy(true); 2798 2799 $.extend(_, _.initials, { currentSlide: currentSlide }); 2800 2801 _.init(); 2802 2803 if( !initializing ) { 2804 2805 _.changeSlide({ 2806 data: { 2807 message: 'index', 2808 index: currentSlide 2809 } 2810 }, false); 2811 2812 } 2813 2814 }; 2815 2816 Slick.prototype.registerBreakpoints = function() { 2817 2818 var _ = this, breakpoint, currentBreakpoint, l, 2819 responsiveSettings = _.options.responsive || null; 2820 2821 if ( $.type(responsiveSettings) === 'array' && responsiveSettings.length ) { 2822 2823 _.respondTo = _.options.respondTo || 'window'; 2824 2825 for ( breakpoint in responsiveSettings ) { 2826 2827 l = _.breakpoints.length-1; 2828 2829 if (responsiveSettings.hasOwnProperty(breakpoint)) { 2830 currentBreakpoint = responsiveSettings[breakpoint].breakpoint; 2831 2832 // loop through the breakpoints and cut out any existing 2833 // ones with the same breakpoint number, we don't want dupes. 2834 while( l >= 0 ) { 2835 if( _.breakpoints[l] && _.breakpoints[l] === currentBreakpoint ) { 2836 _.breakpoints.splice(l,1); 2837 } 2838 l--; 2839 } 2840 2841 _.breakpoints.push(currentBreakpoint); 2842 _.breakpointSettings[currentBreakpoint] = responsiveSettings[breakpoint].settings; 2843 2844 } 2845 2846 } 2847 2848 _.breakpoints.sort(function(a, b) { 2849 return ( _.options.mobileFirst ) ? a-b : b-a; 2850 }); 2851 2852 } 2853 2854 }; 2855 2856 Slick.prototype.reinit = function() { 2857 2858 var _ = this; 2859 2860 _.$slides = 2861 _.$slideTrack 2862 .children(_.options.slide) 2863 .addClass('slick-slide'); 2864 2865 _.slideCount = _.$slides.length; 2866 2867 if (_.currentSlide >= _.slideCount && _.currentSlide !== 0) { 2868 _.currentSlide = _.currentSlide - _.options.slidesToScroll; 2869 } 2870 2871 if (_.slideCount <= _.options.slidesToShow) { 2872 _.currentSlide = 0; 2873 } 2874 2875 _.registerBreakpoints(); 2876 2877 _.setProps(); 2878 _.setupInfinite(); 2879 _.buildArrows(); 2880 _.updateArrows(); 2881 _.initArrowEvents(); 2882 _.buildDots(); 2883 _.updateDots(); 2884 _.initDotEvents(); 2885 _.cleanUpSlideEvents(); 2886 _.initSlideEvents(); 2887 2888 _.checkResponsive(false, true); 2889 2890 if (_.options.focusOnSelect === true) { 2891 $(_.$slideTrack).children().on('click.slick', _.selectHandler); 2892 } 2893 2894 _.setSlideClasses(typeof _.currentSlide === 'number' ? _.currentSlide : 0); 2895 2896 _.setPosition(); 2897 _.focusHandler(); 2898 2899 _.paused = !_.options.autoplay; 2900 _.autoPlay(); 2901 2902 _.$slider.trigger('reInit', [_]); 2903 2904 }; 2905 2906 Slick.prototype.resize = function() { 2907 2908 var _ = this; 2909 2910 if ($(window).width() !== _.windowWidth) { 2911 clearTimeout(_.windowDelay); 2912 _.windowDelay = window.setTimeout(function() { 2913 _.windowWidth = $(window).width(); 2914 _.checkResponsive(); 2915 if( !_.unslicked ) { _.setPosition(); } 2916 }, 50); 2917 } 2918 }; 2919 2920 Slick.prototype.removeSlide = Slick.prototype.slickRemove = function(index, removeBefore, removeAll) { 2921 2922 var _ = this; 2923 2924 if (typeof(index) === 'boolean') { 2925 removeBefore = index; 2926 index = removeBefore === true ? 0 : _.slideCount - 1; 2927 } else { 2928 index = removeBefore === true ? --index : index; 2929 } 2930 2931 if (_.slideCount < 1 || index < 0 || index > _.slideCount - 1) { 2932 return false; 2933 } 2934 2935 _.unload(); 2936 2937 if (removeAll === true) { 2938 _.$slideTrack.children().remove(); 2939 } else { 2940 _.$slideTrack.children(this.options.slide).eq(index).remove(); 2941 } 2942 2943 _.$slides = _.$slideTrack.children(this.options.slide); 2944 2945 _.$slideTrack.children(this.options.slide).detach(); 2946 2947 _.$slideTrack.append(_.$slides); 2948 2949 _.$slidesCache = _.$slides; 2950 2951 _.reinit(); 2952 2953 }; 2954 2955 Slick.prototype.setCSS = function(position) { 2956 2957 var _ = this, 2958 positionProps = {}, 2959 x, y; 2960 2961 if (_.options.rtl === true) { 2962 position = -position; 2963 } 2964 x = _.positionProp == 'left' ? Math.ceil(position) + 'px' : '0px'; 2965 y = _.positionProp == 'top' ? Math.ceil(position) + 'px' : '0px'; 2966 2967 positionProps[_.positionProp] = position; 2968 2969 if (_.transformsEnabled === false) { 2970 _.$slideTrack.css(positionProps); 2971 } else { 2972 positionProps = {}; 2973 if (_.cssTransitions === false) { 2974 positionProps[_.animType] = 'translate(' + x + ', ' + y + ')'; 2975 _.$slideTrack.css(positionProps); 2976 } else { 2977 positionProps[_.animType] = 'translate3d(' + x + ', ' + y + ', 0px)'; 2978 _.$slideTrack.css(positionProps); 2979 } 2980 } 2981 2982 }; 2983 2984 Slick.prototype.setDimensions = function() { 2985 2986 var _ = this; 2987 2988 if (_.options.vertical === false) { 2989 if (_.options.centerMode === true) { 2990 _.$list.css({ 2991 padding: ('0px ' + _.options.centerPadding) 2992 }); 2993 } 2994 } else { 2995 _.$list.height(_.$slides.first().outerHeight(true) * _.options.slidesToShow); 2996 if (_.options.centerMode === true) { 2997 _.$list.css({ 2998 padding: (_.options.centerPadding + ' 0px') 2999 }); 3000 } 3001 } 3002 3003 _.listWidth = _.$list.width(); 3004 _.listHeight = _.$list.height(); 3005 3006 3007 if (_.options.vertical === false && _.options.variableWidth === false) { 3008 _.slideWidth = Math.ceil(_.listWidth / _.options.slidesToShow); 3009 _.$slideTrack.width(Math.ceil((_.slideWidth * _.$slideTrack.children('.slick-slide').length))); 3010 3011 } else if (_.options.variableWidth === true) { 3012 _.$slideTrack.width(5000 * _.slideCount); 3013 } else { 3014 _.slideWidth = Math.ceil(_.listWidth); 3015 _.$slideTrack.height(Math.ceil((_.$slides.first().outerHeight(true) * _.$slideTrack.children('.slick-slide').length))); 3016 } 3017 3018 var offset = _.$slides.first().outerWidth(true) - _.$slides.first().width(); 3019 if (_.options.variableWidth === false) _.$slideTrack.children('.slick-slide').width(_.slideWidth - offset); 3020 3021 }; 3022 3023 Slick.prototype.setFade = function() { 3024 3025 var _ = this, 3026 targetLeft; 3027 3028 _.$slides.each(function(index, element) { 3029 targetLeft = (_.slideWidth * index) * -1; 3030 if (_.options.rtl === true) { 3031 $(element).css({ 3032 position: 'relative', 3033 right: targetLeft, 3034 top: 0, 3035 zIndex: _.options.zIndex - 2, 3036 opacity: 0 3037 }); 3038 } else { 3039 $(element).css({ 3040 position: 'relative', 3041 left: targetLeft, 3042 top: 0, 3043 zIndex: _.options.zIndex - 2, 3044 opacity: 0 3045 }); 3046 } 3047 }); 3048 3049 _.$slides.eq(_.currentSlide).css({ 3050 zIndex: _.options.zIndex - 1, 3051 opacity: 1 3052 }); 3053 3054 }; 3055 3056 Slick.prototype.setHeight = function() { 3057 3058 var _ = this; 3059 3060 if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) { 3061 var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true); 3062 _.$list.css('height', targetHeight); 3063 } 3064 3065 }; 3066 3067 Slick.prototype.setOption = 3068 Slick.prototype.slickSetOption = function() { 3069 3070 /** 3071 * accepts arguments in format of: 3072 * 3073 * - for changing a single option's value: 3074 * .slick("setOption", option, value, refresh ) 3075 * 3076 * - for changing a set of responsive options: 3077 * .slick("setOption", 'responsive', [{}, ...], refresh ) 3078 * 3079 * - for updating multiple values at once (not responsive) 3080 * .slick("setOption", { 'option': value, ... }, refresh ) 3081 */ 3082 3083 var _ = this, l, item, option, value, refresh = false, type; 3084 3085 if( $.type( arguments[0] ) === 'object' ) { 3086 3087 option = arguments[0]; 3088 refresh = arguments[1]; 3089 type = 'multiple'; 3090 3091 } else if ( $.type( arguments[0] ) === 'string' ) { 3092 3093 option = arguments[0]; 3094 value = arguments[1]; 3095 refresh = arguments[2]; 3096 3097 if ( arguments[0] === 'responsive' && $.type( arguments[1] ) === 'array' ) { 3098 3099 type = 'responsive'; 3100 3101 } else if ( typeof arguments[1] !== 'undefined' ) { 3102 3103 type = 'single'; 3104 3105 } 3106 3107 } 3108 3109 if ( type === 'single' ) { 3110 3111 _.options[option] = value; 3112 3113 3114 } else if ( type === 'multiple' ) { 3115 3116 $.each( option , function( opt, val ) { 3117 3118 _.options[opt] = val; 3119 3120 }); 3121 3122 3123 } else if ( type === 'responsive' ) { 3124 3125 for ( item in value ) { 3126 3127 if( $.type( _.options.responsive ) !== 'array' ) { 3128 3129 _.options.responsive = [ value[item] ]; 3130 3131 } else { 3132 3133 l = _.options.responsive.length-1; 3134 3135 // loop through the responsive object and splice out duplicates. 3136 while( l >= 0 ) { 3137 3138 if( _.options.responsive[l].breakpoint === value[item].breakpoint ) { 3139 3140 _.options.responsive.splice(l,1); 3141 3142 } 3143 3144 l--; 3145 3146 } 3147 3148 _.options.responsive.push( value[item] ); 3149 3150 } 3151 3152 } 3153 3154 } 3155 3156 if ( refresh ) { 3157 3158 _.unload(); 3159 _.reinit(); 3160 3161 } 3162 3163 }; 3164 3165 Slick.prototype.setPosition = function() { 3166 3167 var _ = this; 3168 3169 _.setDimensions(); 3170 3171 _.setHeight(); 3172 3173 if (_.options.fade === false) { 3174 _.setCSS(_.getLeft(_.currentSlide)); 3175 } else { 3176 _.setFade(); 3177 } 3178 3179 _.$slider.trigger('setPosition', [_]); 3180 3181 }; 3182 3183 Slick.prototype.setProps = function() { 3184 3185 var _ = this, 3186 bodyStyle = document.body.style; 3187 3188 _.positionProp = _.options.vertical === true ? 'top' : 'left'; 3189 3190 if (_.positionProp === 'top') { 3191 _.$slider.addClass('slick-vertical'); 3192 } else { 3193 _.$slider.removeClass('slick-vertical'); 3194 } 3195 3196 if (bodyStyle.WebkitTransition !== undefined || 3197 bodyStyle.MozTransition !== undefined || 3198 bodyStyle.msTransition !== undefined) { 3199 if (_.options.useCSS === true) { 3200 _.cssTransitions = true; 3201 } 3202 } 3203 3204 if ( _.options.fade ) { 3205 if ( typeof _.options.zIndex === 'number' ) { 3206 if( _.options.zIndex < 3 ) { 3207 _.options.zIndex = 3; 3208 } 3209 } else { 3210 _.options.zIndex = _.defaults.zIndex; 3211 } 3212 } 3213 3214 if (bodyStyle.OTransform !== undefined) { 3215 _.animType = 'OTransform'; 3216 _.transformType = '-o-transform'; 3217 _.transitionType = 'OTransition'; 3218 if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false; 3219 } 3220 if (bodyStyle.MozTransform !== undefined) { 3221 _.animType = 'MozTransform'; 3222 _.transformType = '-moz-transform'; 3223 _.transitionType = 'MozTransition'; 3224 if (bodyStyle.perspectiveProperty === undefined && bodyStyle.MozPerspective === undefined) _.animType = false; 3225 } 3226 if (bodyStyle.webkitTransform !== undefined) { 3227 _.animType = 'webkitTransform'; 3228 _.transformType = '-webkit-transform'; 3229 _.transitionType = 'webkitTransition'; 3230 if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false; 3231 } 3232 if (bodyStyle.msTransform !== undefined) { 3233 _.animType = 'msTransform'; 3234 _.transformType = '-ms-transform'; 3235 _.transitionType = 'msTransition'; 3236 if (bodyStyle.msTransform === undefined) _.animType = false; 3237 } 3238 if (bodyStyle.transform !== undefined && _.animType !== false) { 3239 _.animType = 'transform'; 3240 _.transformType = 'transform'; 3241 _.transitionType = 'transition'; 3242 } 3243 _.transformsEnabled = _.options.useTransform && (_.animType !== null && _.animType !== false); 3244 }; 3245 3246 3247 Slick.prototype.setSlideClasses = function(index) { 3248 3249 var _ = this, 3250 centerOffset, allSlides, indexOffset, remainder; 3251 3252 allSlides = _.$slider 3253 .find('.slick-slide') 3254 .removeClass('slick-active slick-center slick-current') 3255 .attr('aria-hidden', 'true'); 3256 3257 _.$slides 3258 .eq(index) 3259 .addClass('slick-current'); 3260 3261 if (_.options.centerMode === true) { 3262 3263 var evenCoef = _.options.slidesToShow % 2 === 0 ? 1 : 0; 3264 3265 centerOffset = Math.floor(_.options.slidesToShow / 2); 3266 3267 if (_.options.infinite === true) { 3268 3269 if (index >= centerOffset && index <= (_.slideCount - 1) - centerOffset) { 3270 _.$slides 3271 .slice(index - centerOffset + evenCoef, index + centerOffset + 1) 3272 .addClass('slick-active') 3273 .attr('aria-hidden', 'false'); 3274 3275 } else { 3276 3277 indexOffset = _.options.slidesToShow + index; 3278 allSlides 3279 .slice(indexOffset - centerOffset + 1 + evenCoef, indexOffset + centerOffset + 2) 3280 .addClass('slick-active') 3281 .attr('aria-hidden', 'false'); 3282 3283 } 3284 3285 if (index === 0) { 3286 3287 allSlides 3288 .eq(
3288 _.options.slidesToShow + _.slideCount + 1
vendor: 10,708 bytes, lines 3288-3658
3288) 3289 .addClass('slick-center'); 3290 3291 } else if (index === _.slideCount - 1) { 3292 3293 allSlides 3294 .eq(_.options.slidesToShow) 3295 .addClass('slick-center'); 3296 3297 } 3298 3299 } 3300 3301 _.$slides 3302 .eq(index) 3303 .addClass('slick-center'); 3304 3305 } else { 3306 3307 if (index >= 0 && index <= (_.slideCount - _.options.slidesToShow)) { 3308 3309 _.$slides 3310 .slice(index, index + _.options.slidesToShow) 3311 .addClass('slick-active') 3312 .attr('aria-hidden', 'false'); 3313 3314 } else if (allSlides.length <= _.options.slidesToShow) { 3315 3316 allSlides 3317 .addClass('slick-active') 3318 .attr('aria-hidden', 'false'); 3319 3320 } else { 3321 3322 remainder = _.slideCount % _.options.slidesToShow; 3323 indexOffset = _.options.infinite === true ? _.options.slidesToShow + index : index; 3324 3325 if (_.options.slidesToShow == _.options.slidesToScroll && (_.slideCount - index) < _.options.slidesToShow) { 3326 3327 allSlides 3328 .slice(indexOffset - (_.options.slidesToShow - remainder), indexOffset + remainder) 3329 .addClass('slick-active') 3330 .attr('aria-hidden', 'false'); 3331 3332 } else { 3333 3334 allSlides 3335 .slice(indexOffset, indexOffset + _.options.slidesToShow) 3336 .addClass('slick-active') 3337 .attr('aria-hidden', 'false'); 3338 3339 } 3340 3341 } 3342 3343 } 3344 3345 if (_.options.lazyLoad === 'ondemand' || _.options.lazyLoad === 'anticipated') { 3346 _.lazyLoad(); 3347 } 3348 }; 3349 3350 Slick.prototype.setupInfinite = function() { 3351 3352 var _ = this, 3353 i, slideIndex, infiniteCount; 3354 3355 if (_.options.fade === true) { 3356 _.options.centerMode = false; 3357 } 3358 3359 if (_.options.infinite === true && _.options.fade === false) { 3360 3361 slideIndex = null; 3362 3363 if (_.slideCount > _.options.slidesToShow) { 3364 3365 if (_.options.centerMode === true) { 3366 infiniteCount = _.options.slidesToShow + 1; 3367 } else { 3368 infiniteCount = _.options.slidesToShow; 3369 } 3370 3371 for (i = _.slideCount; i > (_.slideCount - 3372 infiniteCount); i -= 1) { 3373 slideIndex = i - 1; 3374 $(_.$slides[slideIndex]).clone(true).attr('id', '') 3375 .attr('data-slick-index', slideIndex - _.slideCount) 3376 .prependTo(_.$slideTrack).addClass('slick-cloned'); 3377 } 3378 for (i = 0; i < infiniteCount + _.slideCount; i += 1) { 3379 slideIndex = i; 3380 $(_.$slides[slideIndex]).clone(true).attr('id', '') 3381 .attr('data-slick-index', slideIndex + _.slideCount) 3382 .appendTo(_.$slideTrack).addClass('slick-cloned'); 3383 } 3384 _.$slideTrack.find('.slick-cloned').find('[id]').each(function() { 3385 $(this).attr('id', ''); 3386 }); 3387 3388 } 3389 3390 } 3391 3392 }; 3393 3394 Slick.prototype.interrupt = function( toggle ) { 3395 3396 var _ = this; 3397 3398 if( !toggle ) { 3399 _.autoPlay(); 3400 } 3401 _.interrupted = toggle; 3402 3403 }; 3404 3405 Slick.prototype.selectHandler = function(event) { 3406 3407 var _ = this; 3408 3409 var targetElement = 3410 $(event.target).is('.slick-slide') ? 3411 $(event.target) : 3412 $(event.target).parents('.slick-slide'); 3413 3414 var index = parseInt(targetElement.attr('data-slick-index')); 3415 3416 if (!index) index = 0; 3417 3418 if (_.slideCount <= _.options.slidesToShow) { 3419 3420 _.slideHandler(index, false, true); 3421 return; 3422 3423 } 3424 3425 _.slideHandler(index); 3426 3427 }; 3428 3429 Slick.prototype.slideHandler = function(index, sync, dontAnimate) { 3430 3431 var targetSlide, animSlide, oldSlide, slideLeft, targetLeft = null, 3432 _ = this, navTarget; 3433 3434 sync = sync || false; 3435 3436 if (_.animating === true && _.options.waitForAnimate === true) { 3437 return; 3438 } 3439 3440 if (_.options.fade === true && _.currentSlide === index) { 3441 return; 3442 } 3443 3444 if (sync === false) { 3445 _.asNavFor(index); 3446 } 3447 3448 targetSlide = index; 3449 targetLeft = _.getLeft(targetSlide); 3450 slideLeft = _.getLeft(_.currentSlide); 3451 3452 _.currentLeft = _.swipeLeft === null ? slideLeft : _.swipeLeft; 3453 3454 if (_.options.infinite === false && _.options.centerMode === false && (index < 0 || index > _.getDotCount() * _.options.slidesToScroll)) { 3455 if (_.options.fade === false) { 3456 targetSlide = _.currentSlide; 3457 if (dontAnimate !== true && _.slideCount > _.options.slidesToShow) { 3458 _.animateSlide(slideLeft, function() { 3459 _.postSlide(targetSlide); 3460 }); 3461 } else { 3462 _.postSlide(targetSlide); 3463 } 3464 } 3465 return; 3466 } else if (_.options.infinite === false && _.options.centerMode === true && (index < 0 || index > (_.slideCount - _.options.slidesToScroll))) { 3467 if (_.options.fade === false) { 3468 targetSlide = _.currentSlide; 3469 if (dontAnimate !== true && _.slideCount > _.options.slidesToShow) { 3470 _.animateSlide(slideLeft, function() { 3471 _.postSlide(targetSlide); 3472 }); 3473 } else { 3474 _.postSlide(targetSlide); 3475 } 3476 } 3477 return; 3478 } 3479 3480 if ( _.options.autoplay ) { 3481 clearInterval(_.autoPlayTimer); 3482 } 3483 3484 if (targetSlide < 0) { 3485 if (_.slideCount % _.options.slidesToScroll !== 0) { 3486 animSlide = _.slideCount - (_.slideCount % _.options.slidesToScroll); 3487 } else { 3488 animSlide = _.slideCount + targetSlide; 3489 } 3490 } else if (targetSlide >= _.slideCount) { 3491 if (_.slideCount % _.options.slidesToScroll !== 0) { 3492 animSlide = 0; 3493 } else { 3494 animSlide = targetSlide - _.slideCount; 3495 } 3496 } else { 3497 animSlide = targetSlide; 3498 } 3499 3500 _.animating = true; 3501 3502 _.$slider.trigger('beforeChange', [_, _.currentSlide, animSlide]); 3503 3504 oldSlide = _.currentSlide; 3505 _.currentSlide = animSlide; 3506 3507 _.setSlideClasses(_.currentSlide); 3508 3509 if ( _.options.asNavFor ) { 3510 3511 navTarget = _.getNavTarget(); 3512 navTarget = navTarget.slick('getSlick'); 3513 3514 if ( navTarget.slideCount <= navTarget.options.slidesToShow ) { 3515 navTarget.setSlideClasses(_.currentSlide); 3516 } 3517 3518 } 3519 3520 _.updateDots(); 3521 _.updateArrows(); 3522 3523 if (_.options.fade === true) { 3524 if (dontAnimate !== true) { 3525 3526 _.fadeSlideOut(oldSlide); 3527 3528 _.fadeSlide(animSlide, function() { 3529 _.postSlide(animSlide); 3530 }); 3531 3532 } else { 3533 _.postSlide(animSlide); 3534 } 3535 _.animateHeight(); 3536 return; 3537 } 3538 3539 if (dontAnimate !== true && _.slideCount > _.options.slidesToShow) { 3540 _.animateSlide(targetLeft, function() { 3541 _.postSlide(animSlide); 3542 }); 3543 } else { 3544 _.postSlide(animSlide); 3545 } 3546 3547 }; 3548 3549 Slick.prototype.startLoad = function() { 3550 3551 var _ = this; 3552 3553 if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { 3554 3555 _.$prevArrow.hide(); 3556 _.$nextArrow.hide(); 3557 3558 } 3559 3560 if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { 3561 3562 _.$dots.hide(); 3563 3564 } 3565 3566 _.$slider.addClass('slick-loading'); 3567 3568 }; 3569 3570 Slick.prototype.swipeDirection = function() { 3571 3572 var xDist, yDist, r, swipeAngle, _ = this; 3573 3574 xDist = _.touchObject.startX - _.touchObject.curX; 3575 yDist = _.touchObject.startY - _.touchObject.curY; 3576 r = Math.atan2(yDist, xDist); 3577 3578 swipeAngle = Math.round(r * 180 / Math.PI); 3579 if (swipeAngle < 0) { 3580 swipeAngle = 360 - Math.abs(swipeAngle); 3581 } 3582 3583 if ((swipeAngle <= 45) && (swipeAngle >= 0)) { 3584 return (_.options.rtl === false ? 'left' : 'right'); 3585 } 3586 if ((swipeAngle <= 360) && (swipeAngle >= 315)) { 3587 return (_.options.rtl === false ? 'left' : 'right'); 3588 } 3589 if ((swipeAngle >= 135) && (swipeAngle <= 225)) { 3590 return (_.options.rtl === false ? 'right' : 'left'); 3591 } 3592 if (_.options.verticalSwiping === true) { 3593 if ((swipeAngle >= 35) && (swipeAngle <= 135)) { 3594 return 'down'; 3595 } else { 3596 return 'up'; 3597 } 3598 } 3599 3600 return 'vertical'; 3601 3602 }; 3603 3604 Slick.prototype.swipeEnd = function(event) { 3605 3606 var _ = this, 3607 slideCount, 3608 direction; 3609 3610 _.dragging = false; 3611 _.swiping = false; 3612 3613 if (_.scrolling) { 3614 _.scrolling = false; 3615 return false; 3616 } 3617 3618 _.interrupted = false; 3619 _.shouldClick = ( _.touchObject.swipeLength > 10 ) ? false : true; 3620 3621 if ( _.touchObject.curX === undefined ) { 3622 return false; 3623 } 3624 3625 if ( _.touchObject.edgeHit === true ) { 3626 _.$slider.trigger('edge', [_, _.swipeDirection() ]); 3627 } 3628 3629 if ( _.touchObject.swipeLength >= _.touchObject.minSwipe ) { 3630 3631 direction = _.swipeDirection(); 3632 3633 switch ( direction ) { 3634 3635 case 'left': 3636 case 'down': 3637 3638 slideCount = 3639 _.options.swipeToSlide ? 3640 _.checkNavigable( _.currentSlide + _.getSlideCount() ) : 3641 _.currentSlide + _.getSlideCount(); 3642 3643 _.currentDirection = 0; 3644 3645 break; 3646 3647 case 'right': 3648 case 'up': 3649 3650 slideCount = 3651 _.options.swipeToSlide ? 3652 _.checkNavigable( _.currentSlide - _.getSlideCount() ) : 3653 _.currentSlide - _.getSlideCount(); 3654 3655 _.currentDirection = 1; 3656 3657 break; 3658
vendor: 3,992 bytes, lines 3659-3790
3659 default: 3660 3661 3662 } 3663 3664 if( direction != 'vertical' ) { 3665 3666 _.slideHandler( slideCount ); 3667 _.touchObject = {}; 3668 _.$slider.trigger('swipe', [_, direction ]); 3669 3670 } 3671 3672 } else { 3673 3674 if ( _.touchObject.startX !== _.touchObject.curX ) { 3675 3676 _.slideHandler( _.currentSlide ); 3677 _.touchObject = {}; 3678 3679 } 3680 3681 } 3682 3683 }; 3684 3685 Slick.prototype.swipeHandler = function(event) { 3686 3687 var _ = this; 3688 3689 if ((_.options.swipe === false) || ('ontouchend' in document && _.options.swipe === false)) { 3690 return; 3691 } else if (_.options.draggable === false && event.type.indexOf('mouse') !== -1) { 3692 return; 3693 } 3694 3695 _.touchObject.fingerCount = event.originalEvent && event.originalEvent.touches !== undefined ? 3696 event.originalEvent.touches.length : 1; 3697 3698 _.touchObject.minSwipe = _.listWidth / _.options 3699 .touchThreshold; 3700 3701 if (_.options.verticalSwiping === true) { 3702 _.touchObject.minSwipe = _.listHeight / _.options 3703 .touchThreshold; 3704 } 3705 3706 switch (event.data.action) { 3707 3708 case 'start': 3709 _.swipeStart(event); 3710 break; 3711 3712 case 'move': 3713 _.swipeMove(event); 3714 break; 3715 3716 case 'end': 3717 _.swipeEnd(event); 3718 break; 3719 3720 } 3721 3722 }; 3723 3724 Slick.prototype.swipeMove = function(event) { 3725 3726 var _ = this, 3727 edgeWasHit = false, 3728 curLeft, swipeDirection, swipeLength, positionOffset, touches, verticalSwipeLength; 3729 3730 touches = event.originalEvent !== undefined ? event.originalEvent.touches : null; 3731 3732 if (!_.dragging || _.scrolling || touches && touches.length !== 1) { 3733 return false; 3734 } 3735 3736 curLeft = _.getLeft(_.currentSlide); 3737 3738 _.touchObject.curX = touches !== undefined ? touches[0].pageX : event.clientX; 3739 _.touchObject.curY = touches !== undefined ? touches[0].pageY : event.clientY; 3740 3741 _.touchObject.swipeLength = Math.round(Math.sqrt( 3742 Math.pow(_.touchObject.curX - _.touchObject.startX, 2))); 3743 3744 verticalSwipeLength = Math.round(Math.sqrt( 3745 Math.pow(_.touchObject.curY - _.touchObject.startY, 2))); 3746 3747 if (!_.options.verticalSwiping && !_.swiping && verticalSwipeLength > 4) { 3748 _.scrolling = true; 3749 return false; 3750 } 3751 3752 if (_.options.verticalSwiping === true) { 3753 _.touchObject.swipeLength = verticalSwipeLength; 3754 } 3755 3756 swipeDirection = _.swipeDirection(); 3757 3758 if (event.originalEvent !== undefined && _.touchObject.swipeLength > 4) { 3759 _.swiping = true; 3760 event.preventDefault(); 3761 } 3762 3763 positionOffset = (_.options.rtl === false ? 1 : -1) * (_.touchObject.curX > _.touchObject.startX ? 1 : -1); 3764 if (_.options.verticalSwiping === true) { 3765 positionOffset = _.touchObject.curY > _.touchObject.startY ? 1 : -1; 3766 } 3767 3768 3769 swipeLength = _.touchObject.swipeLength; 3770 3771 _.touchObject.edgeHit = false; 3772 3773 if (_.options.infinite === false) { 3774 if ((_.currentSlide === 0 && swipeDirection === 'right') || (_.currentSlide >= _.getDotCount() && swipeDirection === 'left')) { 3775 swipeLength = _.touchObject.swipeLength * _.options.edgeFriction; 3776 _.touchObject.edgeHit = true; 3777 } 3778 } 3779 3780 if (_.options.vertical === false) { 3781 _.swipeLeft = curLeft + swipeLength * positionOffset; 3782 } else { 3783 _.swipeLeft = curLeft + (swipeLength * (_.$list.height() / _.listWidth)) * positionOffset; 3784 } 3785 if (_.options.verticalSwiping === true) { 3786 _.swipeLeft = curLeft + swipeLength * positionOffset; 3787 } 3788 3789 if (_.options.fade === true || _.options.touchMove === false) { 3790 return false;
3791 } 3792 3793 if (_.animating === true) { 3794 _.swipeLeft = null; 3795 return false; 3796 } 3797 3798 _.setCSS(_.swipeLeft); 3799 3800 }; 3801 3802 Slick.prototype.swipeStart = function(event) { 3803 3804 var _ = this, 3805 touches; 3806 3807 _.interrupted = true; 3808 3809 if (_.touchObject.fingerCount !== 1 || _.slideCount <= _.options.slidesToShow) { 3810 _.touchObject = {}; 3811 return false; 3812 } 3813 3814 if (event.originalEvent !== undefined && event.originalEvent.touches !== undefined) { 3815 touches = event.originalEvent.touches[0]; 3816 } 3817 3818 _.touchObject.startX = _.touchObject.curX = touches !== undefined ? touches.pageX : event.clientX; 3819 _.touchObject.startY = _.touchObject.curY = touches !== undefined ? touches.pageY : event.clientY; 3820 3821 _.dragging = true; 3822 3823 }; 3824 3825 Slick.prototype.unfilterSlides = Slick.prototype.slickUnfilter = function() { 3826 3827 var _ = this; 3828 3829 if (_.$slidesCache !== null) { 3830 3831 _.unload(); 3832 3833 _.$slideTrack.children(this.options.slide).detach(); 3834 3835 _.$slidesCache.appendTo(_.$slideTrack); 3836 3837 _.reinit(); 3838 3839 } 3840 3841 }; 3842 3843 Slick.prototype.unload = function() { 3844 3845 var _ = this; 3846 3847 $('.slick-cloned', _.$slider).remove(); 3848 3849 if (_.$dots) { 3850 _.$dots.remove(); 3851 } 3852 3853 if (_.$prevArrow && _.htmlExpr.test(_.options.prevArrow)) { 3854 _.$prevArrow.remove(); 3855 } 3856 3857 if (_.$nextArrow && _.htmlExpr.test(_.options.nextArrow)) { 3858 _.$nextArrow.remove(); 3859 } 3860 3861 _.$slides 3862 .removeClass('slick-slide slick-active slick-visible slick-current') 3863 .attr('aria-hidden', 'true') 3864 .css('width', ''); 3865 3866 }; 3867 3868 Slick.prototype.unslick = function(fromBreakpoint) { 3869 3870 var _ = this; 3871 _.$slider.trigger('unslick', [_, fromBreakpoint]); 3872 _.destroy(); 3873 3874 }; 3875 3876 Slick.prototype.updateArrows = function() { 3877 3878 var _ = this, 3879 centerOffset; 3880 3881 centerOffset = Math.floor(_.options.slidesToShow / 2); 3882 3883 if ( _.options.arrows === true && 3884 _.slideCount > _.options.slidesToShow && 3885 !_.options.infinite ) { 3886 3887 _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false'); 3888 _.$nextArrow.removeClass('slick-disabled').attr('aria-disabled', 'false'); 3889 3890 if (_.currentSlide === 0) { 3891 3892 _.$prevArrow.addClass('slick-disabled').attr('aria-disabled', 'true'); 3893 _.$nextArrow.removeClass('slick-disabled').attr('aria-disabled', 'false'); 3894 3895 } else if (_.currentSlide >= _.slideCount - _.options.slidesToShow && _.options.centerMode === false) { 3896 3897 _.$nextArrow.addClass('slick-disabled').attr('aria-disabled', 'true'); 3898 _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false'); 3899 3900 } else if (_.currentSlide >= _.slideCount - 1 && _.options.centerMode === true) { 3901 3902 _.$nextArrow.addClass('slick-disabled').attr('aria-disabled', 'true'); 3903 _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false'); 3904 3905 } 3906 3907 } 3908 3909 }; 3910 3911 Slick.prototype.updateDots = function() { 3912 3913 var _ = this; 3914 3915 if (_.$dots !== null) { 3916 3917 _.$dots 3918 .find('li') 3919 .removeClass('slick-active') 3920 .end(); 3921 3922 _.$dots 3923 .find('li') 3924 .eq(Math.floor(_.currentSlide / _.options.slidesToScroll)) 3925 .addClass('slick-active'); 3926 3927 } 3928 3929 }; 3930 3931 Slick.prototype.visibility = function() { 3932 3933 var _ = this; 3934 3935 if ( _.options.autoplay ) { 3936 3937 if ( document[_.hidden] ) { 3938 3939 _.interrupted = true; 3940 3941 } else { 3942 3943 _.interrupted = false; 3944 3945 } 3946 3947 } 3948 3949 }; 3950 3951 $.fn.slick = function() { 3952 var _ = this, 3953 opt = arguments[0], 3954 args = Array.prototype.slice.call(arguments, 1), 3955 l = _.length, 3956 i, 3957 ret; 3958 for (i = 0; i < l; i++) { 3959 if (typeof opt == 'object' || typeof opt == 'undefined') 3960 _[i].slick = new Slick(_[i], opt); 3961 else 3962 ret = _[i].slick[opt].apply(_[i].slick, args); 3963 if (typeof ret != 'undefined') return ret; 3964 } 3965 return _; 3966 }; 3967 3968})); 3969 3970define('components/TateReady',['jquery', 'vendor/slick', 'components/TateGOTO', 'components/TateNotification'], function ($, Slick, TateGOTO, TateNotification) { 3971 var TateReady = function () { 3972 this.init(); 3973 }; 3974 3975 TateReady.prototype = { 3976 init: function () { 3977 /** LOCAL CONFIGURATION OBJECTS **/ 3978 var slick_options = { 3979 slidesToShow: 4, slidesToScroll: 1, infinite: false, 3980 responsive: [{ 3981 breakpoint: 1024, 3982 settings: { slidesToShow: 3, slidesToScroll: 1, infinite: false} 3983 }, { 3984 breakpoint: 720, 3985 settings: { slidesToShow: 2, slidesToScroll: 1, infinite: false} 3986 }, { 3987 breakpoint: 480, 3988 settings: { slidesToShow: 1, slidesToScroll: 1, infinite: false} 3989 }] 3990 }; 3991 3992 /** DOM READY SCRIPTS **/ 3993 $(document).ready(function () { 3994 $('body').removeClass('no-js'); 3995 3996 $('.img-display__slideshow').each(function () { 3997 var $me = $(this); 3998 $me.find('.slideshow--slides').slick({ 3999 infinite: false, 4000 prevArrow: $me.find('.carousel--left'), 4001 nextArrow: $me.find('.carousel--right') 4002 }); 4003 4004 $me.find('.slideshow--slides').on('afterChange', function (event, slick, currentslide) { 4005 $me.trigger('lazyload:slideshow'); 4006 }); 4007 }); 4008 4009 var bufftop = 0 4010 if ($('header').length) { bufftop += $('header').height(); } 4011 if ($('#breadcrumb').length) { bufftop += $('#breadcrumb').height(); }
4012 var goto_links = new TateGOTO({'bufftop': bufftop}); 4013 4014 $('.card--carousel').each(function () { 4015 var $me = $(this); 4016 4017 slick_options.prevArrow = $me.find('.carousel--left'); 4018 slick_options.nextArrow = $me.find('.carousel--right'); 4019 4020 $me.find('.card-list').slick(slick_options); 4021 4022 $me.find('.card-list').on('afterChange', function (event, slick, currentSlide) { 4023 $me.trigger('lazyload:carousel'); 4024 }); 4025 }); 4026 4027 // Initialises brightcove videos 4028 $('.brightcove-player').each(function() { 4029 var el = $(this); 4030 var vid = el.attr('data-video-id'); 4031 if (!vid || typeof(vid) === 'undefined') { 4032 el.remove(); 4033 return; 4034 } 4035 el.removeAttr('data-video-id'); 4036 brightcode = '<video data-vi
4036deo-id=' + vid + ' data-account="1854890877" data-player="4811b2e3-75b4-4489-b1a5-21a18a61075e" data-embed="default" class="video-js" controls="" style="width: 100%; height: 100%; position: absolute; top: 0px; left: 0px;"></video>'; 4037 el.html(brightcode); 4038 return; 4039 }); 4040 4041 if ($('.brightcove-player')[0]) { 4042 $('body').append('<script src="//players.brightcove.net/1854890877/4811b2e3-75b4-4489-b1a5-21a18a61075e_default/index.min.js"></script>'); 4043 } 4044 4045 // Show/hide details in slideshows for archive items and Turner sketchbooks 4046 $('.piece-meta__trigger').on('click', function(e){ 4047 e.preventDefault(); 4048 var list = $(this).siblings('.piece-meta__list'); 4049 if (list.hasClass('h-e--mobile')) { 4050 list.removeClass('h-e--mobile'); 4051 $(this).text('Resources.HIDE_DETAILS'); 4052 } else { 4053 list.addClass('h-e--mobile'); 4054 $(this).text('Resources.SHOW_DETAILS'); 4055 } 4056 }); 4057 4058 }); 4059 } 4060 }; 4061 4062 return TateReady; 4063}); 4064 4065define('components/TateBTT',["jquery"], function ($) { 4066 4067 var TateBTT = function() { 4068 // Global vars and constants. 4069 var limit_height = window.innerHeight * 2; 4070 // jQuery selector for the anchor (REMEMBER TO CHANGE THE MARKUP!) 4071 var data_tag = "a[data-role='btt']"; 4072 var animation_speed = 750; // MS 4073 // Change the markup here. 4074 var markup = [ 4075 '<a href="#" class="page--back-to-top" data-role="btt">', 4076 'Back to top', 4077 '</a>', 4078 ].join("\n"); 4079 4080 var scroll_callback = function () { 4081 // Write your callback code in here. 4082 }; 4083 4084 var init = function () { 4085 // Extend jQuery easing.. We should probably find if this exists already? (Other modules do this...) 4086 if (!('easeInOutQuart' in $.easing)) { 4087 $.extend($.easing, { 4088 easeInOutQuart: function (x, t, b, c, d) { 4089 if ((t/=d/2) < 1) return c/2*t*t*t*t + b; 4090 return -c/2 * ((t-=2)*t*t*t - 2) + b; 4091 } 4092 }); 4093 } 4094 4095 // DOM injection 4096 if ($(data_tag).length === 0) { 4097 $('body').append(markup); 4098 } 4099 4100 // Events 4101 $(window).on('scroll', window_scroll); 4102 $(data_tag).on('click', scrollToTop); 4103 4104 // Just in case we're loading half way down the page 4105 window_scroll(); 4106 }; 4107 4108 var scrollToTop = function (e) { 4109 e.preventDefault(); 4110 4111 $('html, body').stop().animate({ 4112 'scrollTop': 0, 4113 }, animation_speed, 'easeInOutQuart', scroll_callback); 4114 }; 4115 4116 var hide_dom_element = function () { 4117 var $dom_element = $(data_tag); 4118 if ($dom_element.is(":visible")) { 4119 $dom_element.removeClass("page--back-to-top__active"); 4120 } 4121 }; 4122 4123 var show_dom_element = function () { 4124 var $dom_element = $(data_tag); 4125 if (!$dom_element.is(":visible")) { 4126 $dom_element.addClass("page--back-to-top__active"); 4127 } 4128 }; 4129 4130 var window_scroll = function () { 4131 var body_scrolltop = $(document).scrollTop(), 4132 $dom_element = $(data_tag); 4133 4134 if (body_scrolltop >= limit_height) { 4135 show_dom_element(); 4136 } else { 4137 hide_dom_element(); 4138 } 4139 }; 4140 4141 init(); 4142 }; 4143 4144 return TateBTT; 4145 4146}); 4147 4148define('components/TateLazyLoad',["jquery", "components/TateWindow"], function ($, TateWindow) { 4149 4150 var CONTAINER_SELECTOR = '.responsive-container', 4151 SRC_DATA_ATTRIBUTE = 'data-original', 4152 lazyLoad_throttle; 4153 4154 $.fn.tateResponsiveImage = function(options) { 4155 4156 var settings = $.extend({ 4157 selector: CONTAINER_SELECTOR, 4158 srcDataAttribute: SRC_DATA_ATTRIBUTE, 4159 forceVisible: false, 4160 resize: false 4161 }, options ); 4162 4163 var tateWindow = new TateWindow(), 4164 window_width = tateWindow.width(), 4165 window_height = tateWindow.height(), 4166 max_height = Math.max(405, Math.round(0.9 * window_height)); 4167 4168 var setup_attributes = function(el){ 4169 var target_width = el.width(); 4170 var banner = el.hasClass('splash-header__media--inner'); 4171 4172 el.find('img').each(function () { 4173 var sizes = []; 4174 var image = $(this);
4175 if (image.attr('data-visible') && !settings.resize) { return; } 4176 $(image[0].attributes).each(function(){ 4177 var name = this.name; 4178 if (name.indexOf("data-src-") === 0) { 4179 var dims = (name.substr(9)).split("-"), 4180 w = parseInt(dims[0]), 4181 h = (dims[1]) ? parseInt(dims[1]) : 0; 4182 sizes.push({"width": w, "height": h, "attrName": name}); 4183 } 4184 }); 4185 sizes.sort(function(a,b){ 4186 return a.width - b.width; 4187 }); 4188 var selected_size = {"width": 0, "height": 0, "attrName": settings.srcDataAttribute}; 4189 for (var i = 0; i < sizes.length; i++) { 4190 selected_size = sizes[i]; 4191 if (selected_size.width >= target_width || (!banner && selected_size.height && selected_size.height >= max_height)) { break; } 4192 } 4193 var current_size = $(this).attr('data-current-size'), 4194 current_width = (current_size) ? (current_size.split("-"))[0] : 0, 4195 new_size = selected_size.width + "-" + selected_size.height; 4196 4197 if (!current_width || current_width < selected_size.width) { 4198 image.attr(settings.srcDataAttribute, image.attr(selected_size.attrName)).attr('data-current-size', new_size).attr('data-visible', ''); 4199 } 4200 4201 if (el.closest('.image-canvas').length) { // We need to add a lightbox attribute 4202 max_w = window_width - 64; 4203 max_h = window_height - 64; 4204 for (var i = 0; i < sizes.length; i++) { 4205 selected_size = sizes[i]; 4206 if (selected_size.width >= max_w || (selected_size.width != selected_size.height && selected_size.height >= max_h)) { break; } 4207 } 4208 image.attr('data-lightbox', image.attr(selected_size.attrName)); 4209 } 4210 }); 4211 }; 4212 4213 return this.each(function(){ 4214 var $img_containers; 4215 if ($(this).is(settings.selector)) { 4216 $img_containers = $(this); 4217 } else { 4218 $img_containers = $(this).find(settings.selector); 4219 } 4220 if ($img_containers) { 4221 $img_containers.each(function(){ 4222 if ($(this).is(':visible')) { 4223 setup_attributes($(this), false); 4224 } 4225 }); 4226 } 4227 }); 4228 4229 }; 4230 4231 $.fn.tateLazyLoad = function(options) { 4232 4233 var settings = $.extend({ 4234 selector: CONTAINER_SELECTOR, 4235 srcDataAttribute: SRC_DATA_ATTRIBUTE, 4236 forceVisible: false 4237 }, options ); 4238 4239 var tateWindow = new TateWindow(), 4240 window_width = tateWindow.width(), 4241 window_height = tateWindow.height(), 4242 max_height = Math.max(405, Math.round(0.9 * window_height)); 4243 4244 var check_if_image_in_viewport = function (el) { 4245 if (typeof jQuery === "function" && el instanceof jQuery) { 4246 el = el[0]; 4247 } 4248 4249 var rect = el.getBoundingClientRect(); 4250 4251 return ( 4252 rect.top >= 0 - window_height && 4253 rect.left >= 0 && 4254 rect.bottom <= 2 * window_height && 4255 rect.left <= window_width 4256 ); 4257 }; 4258 4259 var check_if_image_should_load = function (el) { 4260 // Handle awkward case of slideshows, where all the slides are 'visible' and 4261 // stacked in the same XY position, but the current slide has a higher z-index. 4262 if (el.parent().is('.slide')) { 4263 var slide = el.closest('.slick-slide'); 4264 if (slide.length && !slide.hasClass('.slick-current')) 4265 return false; 4266 } 4267 return check_if_image_in_viewport(el); 4268 }; 4269 4270 var show_image = function(image) { 4271 if (image.attr(settings.srcDataAttribute) && ( 4272 !image.attr('data-visible') || image.attr('src') != image.attr(settings.srcDataAttribute) 4273 )) { 4274 if (settings.forceVisible || check_if_image_should_load(image)) { 4275 image.attr('src', image.attr(settings.srcDataAttribute)); 4276 image.attr('data-visible', true); 4277 } 4278 } 4279 }; 4280 4281 return this.each(function(){ 4282 var $images; 4283 if ($(this).is('img')) { 4284 $images = $(this); 4285 } else if ($(this).is(settings.selector)) { 4286 $images = $(this).find('img'); 4287 } else { 4288 $images = $(this).find(settings.selector + ' img'); 4289 } 4290 if ($images) { 4291 $images.each(function(){ 4292 show_image($(this)); 4293 }); 4294 } 4295 }); 4296 4297 }; 4298 4299 4300 var TateLazyLoad = function () { 4301 4302 // Custom event registered on card carousels, so that we can apply the lazy loading to the cards 4303 // coming into view as the user scrolls through the carousel. 4304 $('.card--carousel').on('lazyload:carousel', function(evt){ 4305 $(this).tateLazyLoad(); 4306 }); 4307 // Custom event registered on image containers, so that we can apply the attribute setup 4308 // to the splash header image from outside this function. 4309 $('.splash-header__media--inner').on('lazyload:setup', function(evt){ 4310 $(this).tateResponsiveImage(); 4311 }); 4312 // Custom event registered on slideshow, so that we can apply the lazy loading to the cards 4313 // coming into view as the user scrolls through the carousel. 4314 $('.img-display__slideshow').on('lazyload:slideshow', function(evt){ 4315 $(this).tateLazyLoad(); 4316 }); 4317 4318 var resize_throttle = function(delay) { 4319 var me = this;
4320 delay = delay || 100; 4321 clearTimeout(lazyLoad_throttle); 4322 lazyLoad_throttle = setTimeout(function(){ 4323 $('body').tateResponsiveImage({resize: true}).tateLazyLoad(); 4324 }, delay); 4325 }; 4326 4327 var setup_events = function () { 4328 $(window).on("resize", resize_throttle); 4329 $(window).on('DOMContentLoaded load scroll', function(){ 4330 $('body').tateLazyLoad(); 4331 }); 4332 }; 4333 4334 var init = function () { 4335 setup_events(); 4336 $('body').tateResponsiveImage().tateLazyLoad(); 4337 }; 4338 4339 $(document).ready(init); 4340 }; 4341 4342 return TateLazyLoad; 4343}); 4344define('components/TateOpenTimes',['jquery'], function ($) { 4345 var TateOpenTimes = function () { 4346 var me = this; 4347 4348 $(document).ready(function () { 4349 me.init(); 4350 }); 4351 }; 4352 4353 TateOpenTimes.prototype = { 4354 init: function () { 4355 4356 var today = null; 4357 var getToday = function(){ 4358 var days = ["sun", "mon", "tue", "wed", "thu", "fri", "sat"]; 4359 var now = new Date(), 4360 date = (now.getDate() < 10) ? '0' + now.getDate() : now.getDate(), 4361 month_index = now.getMonth() + 1, 4362 month = (month_index < 10) ? '0' + month_index : month_index, 4363 year = now.getFullYear(); 4364 return { 4365 dateString: (year + "-" + month + "-" + date), 4366 day: days[now.getDay()] 4367 } 4368 } 4369 4370 var getCurrentOpenTimes = function(open_times, closed_dates, default_text){ 4371 if (!today) { today = getToday(); } 4372 if (closed_dates) { 4373 var dates = closed_dates.split(","); 4374 for (var i = 0; i < dates.length; i++) { 4375 var date = dates[i]; 4376 if (date == today.dateString) { 4377 return "Closed today"; 4378 } 4379 } 4380 } 4381 if (open_times) { 4382 var times = open_times.split(","); 4383 for (var i = 0; i < times.length; i++) { 4384 var dayTime = times[i].split(":"); 4385 if (dayTime[0] == today.day) { 4386 return "Open today " + dayTime[1]; 4387 } 4388 } 4389 } 4390 return default_text; 4391 }; 4392 4393 $('.current-open-times').each(function(){ 4394 var newText = getCurrentOpenTimes($(this).attr("data-open-times"), $(this).attr("data-closed-dates"), $(this).text()); 4395 $(this).text(newText); 4396 }); 4397 } 4398 }; 4399 4400 return TateOpenTimes; 4401}); 4402 4403define('components/TateLogin',["jquery"], function ($) { 4404 4405 var TateLogin = function () { 4406 4407 var init = function() { 4408 4409 var dest = window.location.pathname; 4410 if(!dest) { 4411 dest = "/"; 4412 } 4413 4414 // remove pesky leading slash as login redirects to 'http://host/' + dest 4415 dest = dest.replace(/^\//,''); 4416 4417 var login_link = function() { 4418 var html_string = []; 4419 html_string.push('<a href="javascript:;" data-href="/user?destination=' + dest + '" class="btn btn--type__no-bg btn--size__small bt
4419n--style__text" data-gtm-name="Navigation-header">'); 4420 html_string.push('<i class="btn__icon icon--user"></i>'); 4421 html_string.push('<span class="btn__text">Login<sup>ui</sup></span>'); 4422 html_string.push('</a>'); 4423 4424 $("#tate-login").html(html_string.join("\n")); 4425 $(".site-menu--handheld").append('<li class="site-menu__item site-menu--handheld__item">' + html_string.join("\n") + '</li>'); 4426 4427 // use anon links as we don't have a user 4428 $("a[data-anon-href]").each(function() { 4429 var anon_url = $(this).attr('data-anon-href'); 4430 if(typeof(anon_url) != 'undefined' && anon_url) { 4431 $(this).attr('href', anon_url); 4432 } 4433 }); 4434 }; 4435 4436 var user_link = function(data) { 4437 var html_string = []; 4438 /* 4439 if(data.user.thumbnail_url) { 4440 html_string.push('<img src="'+data.user.thumbnail_url+'" style="max-width:50px;height:auto;"></img>'); 4441 } 4442 */ 4443 4444 // when on www.tate we want admin/editor links to point at auth.tate 4445 base_url = ""; 4446 if (window.location.host == "www.tate.org.uk") { 4447 base_url = "http://auth.tate.org.uk"; 4448 } 4449 4450 // note base_url not used 4451 html_string.push('<a href="/user/' + data.user.uid + '" class="btn btn--type__no-bg btn--size__small bt
4451n--style__text" data-gtm-name="Navigation-header">'); 4452 html_string.push('<i class="btn__icon icon--user"></i>'); 4453 html_string.push('<span class="btn__text">' + data.user.username + '</span>'); 4454 html_string.push('</a>'); 4455 html_string.push('<ul class="list list--links">'); 4456 4457 var links = data.links; 4458 4459 while(l = links.pop()) { 4460 // user profile should go to www 4461 if( l.url.startsWith("/user/")) { 4462 html_string.push('<li class="list__item"><a href="' + l.url + '" class="btn btn--type__no-bg btn--size__small btn--style__text" data-gtm-name="Navigation-header"><span class="btn__text">' + l.label + '</span></a></li>'); 4463 } else { 4464 html_string.push('<li class="list__item"><a href="' + base_url + l.url + '" class="btn btn--type__no-bg btn--size__small btn--style__text" data-gtm-name="Navigation-header"><span class="btn__text">' + l.label + '</span></a></li>'); 4465 } 4466 } 4467 4468 // e.g. /node/1234 4469 var current_page = null; 4470 $("link[rel=shortlink]").each(function() { current_page = $(this).attr('href') }); 4471 4472 if (!current_page) { 4473 current_page = dest; 4474 } 4475 4476 if (current_page.indexOf("/node/") == 0 && 4477 data.user.roles && (data.user.roles.admin || data.user.roles.editor )) { 4478 // doesn't guarantee user can actually edit the page 4479 html_string.push('<li class="list__item"><a href="' + base_url + current_page + '/edit" class="btn btn--type__no-bg btn--size__small bt
4479n--style__text" data-gtm-name="Navigation-header"><span class="btn__text">Edit page</span></a></li>'); 4480 } 4481 4482 // note base_url not used 4483 html_string.push('<li class="list__item"><a href="/user/logout" class="btn btn--type__no-bg btn--size__small btn--style__text" data-gtm-name="Navigation-header"><i class="btn__icon icon--user"></i><span class="btn__text">Sign out</span></a></li>'); 4484 html_string.push('</ul>'); 4485 4486 $("#tate-login").html(html_string.join('\n')); 4487 $(".site-menu--handheld").append('<li class="site-menu__item site-menu--handheld__item">' + html_string.join("\n") + '</li>'); 4488 }; 4489 4490 $.ajax({ 4491 url: '/ajax/user', 4492 method: 'GET', 4493 success: function(data, textStatus, xhr) { 4494 if (xhr.status >= 200 && xhr.status <= 300 && data && data.user) { 4495 user_link(data); 4496 } else { 4497 login_link(); 4498 } 4499 }, 4500 error: function(data, textStatus, xhr) { 4501 login_link(); 4502 } 4503 }); 4504 }; 4505 4506 $(document).ready(function () { 4507 // temporary suspended 4508 // init(); 4509 }); 4510 }; 4511 4512 return TateLogin; 4513}); 4514 4515define('components/TateNav',["jquery"], function ($) { 4516 var TateNav = function() { 4517 var $search_overlay_shadow = '<div class="site-search--overlay-shadow" style="z-index: 35; position: fixed; bottom: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.8)"></div>'; 4518 var defaultSearchPlaceholder = $('#navigation-search').attr('placeholder'); 4519 var setup_sticky_nav = function () { 4520 var nav_height = $('#nav').height(); 4521 4522 //var nav_handle_html = '<span class="nav--handle" data-gtm-name="Navigation-burger">Menu</span>'; 4523 4524 /** 4525 * Icons classes 4526 * nav--handle__search_burger - search with burger 4527 * nav--handle__lock - show locked in secured pages 4528 * nav--handle__card - show basket 4529 * nav--handle__add - show add icon 4530 * 4531 * more information and icon css classes you can locate 4532 * in _nav-patch.scss 4533 */ 4534 var nav_handle_html = '<a href="javascript:void(0)" tabindex="0" class="nav--handle nav--handle__search_burger" data-gtm-name="Navigation-burger">Menu</a>'; 4535 var $body = $('body'); 4536 $body.prepend(nav_handle_html); 4537 4538 var hide_show_nav = function () { 4539 $('.nav--handle').toggleClass('nav--active'); 4540 $('#nav').toggleClass('nav--open'); 4541 $('.nav--shadow').unbind().remove(); 4542 }; 4543 4544 var window_scrolling = function () { 4545 var scroll_top = $(window).scrollTop(), 4546 $site_menu = $('.site-menu'), 4547 $nav = $("#nav"), 4548 nav_height = $nav.height(), 4549 $nav_handle = $(".nav--handle"); 4550 4551 if ($nav.hasClass('tickets-nav')) { 4552 return; 4553 } 4554 4555 if ($(window).width() < 840) { // Ignore the scroll event on mobile devices 4556 return; 4557 } 4558 4559 if (scroll_top > (0 + $site_menu.height())) { 4560 if (!$('.header-menu-close .icon--close').is(':visible')) { 4561 4562 $nav.removeClass('nav--relaxed'); 4563 $('.member-discount-info').addClass('hidden'); 4564 $nav_handle.removeClass('nav--handle__hidden'); 4565 $('.header-menu .icon--menu').show(); 4566 4567 if ($('.expanded-menu').is(':visible')) { 4568 $('.expanded-menu').addClass('expanded-menu-up'); 4569 } 4570 } 4571 } else { 4572 $nav.addClass('nav--relaxed'); 4573 $('.member-discount-info').removeClass('hidden'); 4574 $nav_handle.addClass('nav--handle__hidden'); 4575 $('.header-menu .icon--menu').hide(); 4576 4577 if (scroll_top == 0) { 4578 $('.header-menu-close .icon--close').hide(); 4579 } 4580 4581 $('.expanded-menu').removeClass('expanded-menu-up'); 4582 } 4583 }; 4584 4585 $('.nav--handle').on('click', function () { 4586 hide_show_nav(); 4587 //If nav is active add a shadow and onclick handler 4588 if ($(this).hasClass('nav--active')) { 4589 $('body').prepend("<div class='nav--shadow'></div>"); 4590 $('.nav--shadow').on('click', function () { 4591 hide_show_nav(); 4592 }); 4593 } 4594 }); 4595 4596 $(window).on('scroll', window_scrolling); 4597 window_scrolling(); 4598 4599 $(document).ready(function() { 4600 if(navigator.platform == "iPad") { 4601 // workaround for hover menus not closing on click 4602 $('body').css('cursor', 'pointer'); 4603 } 4604 }); 4605 4606 $('.mobile-expand-btn').on('click', function() { 4607 4608 if ($(this).find('.icon--chevron-down').is(':visible')) { 4609 4610 $(this).find('.icon--chevron-down').hide(); 4611 $(this).find('.icon--chevron-up').show(); 4612 4613 var menuWrapper = $(this).parents('.menu-item-wrapper'); 4614 menuWrapper.find('.expanded-menu').show(); 4615 menuWrapper.find('.site-menu__item').addClass('selected-menu-item'); 4616 } else { 4617 4618 $(this).find('.icon--chevron-down').show(); 4619 $(this).find('.icon--chevron-up').hide(); 4620 4621 var menuWrapper = $(this).parents('.menu-item-wrapper'); 4622 menuWrapper.find('.expanded-menu').hide(); 4623 menuWrapper.find('.site-menu__item').removeClass('selected-menu-item'); 4624 } 4625 }); 4626 4627 $( window ).on('resize', function() { 4628 var windowWidth = $( window ).width(); 4629 if (windowWidth < 840) { 4630 $('.header-menu .icon--menu').show(); 4631 } 4632 }); 4633 }; 4634 4635 var setup_pager_navigation = function () { 4636 if ($('.artist-letter').length > 0) { //ensuring that the function is running on art prints page 4637 $('.pager__item').on('click', function (e) { 4638 e.preventDefault(); 4639 var anchorId = $(e.target).attr('href'); 4640 4641 if (typeof anchorId !== 'undefined' && anchorId.trim().length > 0) { 4642 var anchorOffset = $('.page__header').height() + $('.artist-letter').height(), //total height of fixed properties on top of page and the letter itself 4643 top = $(anchorId)[0].offsetTop - anchorOffset; 4644 4645 window.scrollTo(0, top); 4646 } 4647 }); 4648 } 4649 }; 4650 4651 var setup_search = function () { 4652 4653 var $search_block_form = $('#search-block-form'), $navigation_search = $('#navigation-search'); 4654 4655 $search_block_form.on('submit', function(e) { 4656 if (!$navigation_search.val()) { 4657 e.preventDefault(); 4658 } 4659 }); 4660
4661 var close_overlay = function (e) { 4662 $('.site-search--overlay-shadow').unbind().remove(); 4663 $search_block_form.css('margin-top' , '-' + $search_block_form.height() + 'px'); 4664 $search_block_form.removeClass('site-search--overlay__open'); 4665 $search_block_form.attr('aria-hidden','true'); 4666 $search_block_form.find('button, input, span[role="button"]').attr('tabindex','-1'); 4667 }; 4668 4669 var inject_markup_and_style = function () { 4670 var first_span = [ 4671 '<span class="btn btn--style__icon site-search--overlay__close-button" data-gtm-name="Navigation-search-close">', 4672 ' <i class="btn__icon icon--close"></i>', 4673 ' <span class="btn__text">Close</span>', 4674 '</span>' 4675 ].join("\n"); 4676 4677 var second_span = [ 4678 '<span class="btn btn--type__no-bg btn--size__small btn--style__text site-search--overlay__open-button" data-gtm-name="Navigation-header">', 4679 ' <i class="btn__icon icon--search"></i>', 4680 ' <span class="btn__text">Search<sup>ui</sup></span>', 4681 '</span>' 4682 ].join("\n"); 4683 4684 $search_block_form.addClass('site-search--overlay').css('margin-top' , '-' + $search_block_form.height() + 'px').prepend(first_span); 4685 }; 4686 4687 var register_events = function () { 4688 var me = this; 4689 4690 $('.site-search--overlay__close-button').on('click', function (e) { 4691 close_overlay(e); 4692 }); 4693 4694 $('.site-search--overlay__open-button, .member__patron__header .icon--search, .header-search-icon').on('click', function (e) { 4695 $('body').prepend($search_overlay_shadow); 4696 4697 /* Is unbound inside close_overlay() */ 4698 $('.site-search--overlay-shadow').on('click', function (e) { 4699 close_overlay(e); 4700 }); 4701 4702 $search_block_form.css('margin-top' , '0px'); 4703 $search_block_form.addClass('site-search--overlay__open'); 4704 $search_block_form.attr('aria-hidden','false'); 4705 $search_block_form.find('button, input, span[role="button"]').attr('tabindex','0'); 4706 $('#navigation-search').focus(); 4707 }); 4708 }; 4709 4710 inject_markup_and_style(); 4711 register_events(); 4712 }; 4713 4714 setup_sticky_nav(); 4715 setup_search(); 4716 setup_pager_navigation(); 4717 }; 4718 4719 return TateNav; 4720}); 4721 4722define('components/TateBreadcrumbs',["jquery"], function ($) { 4723 4724 var TateBreadcrumbs = function() { 4725 4726 var expandHandle = null, 4727 isExpanded = false, 4728 resizeTimeout; 4729 4730 var setup = function() { 4731 4732 if(typeof(window.$) == 'undefined') 4733 return; 4734 4735 var breadcrumbWidth = function() { 4736 var breadcrumbs = $("#breadcrumb"); 4737 if(!breadcrumbs || typeof(breadcrumbs) == 'undefined' || breadcrumbs.length < 1) { 4738 return; 4739 } 4740 var breadcrumb = $(breadcrumbs[0]), 4741 expandTrigger = breadcrumb.find('.breadcrumb__handle'), 4742 container = breadcrumb.find('.breadcrumb__container'), 4743 bcListWrapper = breadcrumb.find('.breadcrumb__list-outer'), 4744 bcList = breadcrumb.find('.breadcrumb__list'), 4745 bcItems = breadcrumb.find('.breadcrumb__item'); 4746 4747 // Keep a copy of the expandTrigger as we may remove it and then need it back again 4748 if (!expandHandle && expandTrigger.length) { 4749 expandHandle = $($('<div>').append(expandTrigger.clone(false)).html()); 4750 } 4751 4752 // Quick test of how wide the list really is 4753 container.removeClass('breadcrumb--expanded'); 4754 bcItems.css('max-width', 'none'); 4755 bcListWidth = bcList.outerWidth(); 4756 bcItems.removeAttr('style'); 4757 4758 if (bcListWidth > bcListWrapper.width()) { 4759 if (!expandTrigger.length && expandHandle) { 4760 expandTrigger = bcListWrapper.before(expandHandle); 4761 } 4762 expandTrigger.off('click').on('click', toggleBreadcrumbHeight); 4763 } else if (expandTrigger.length) { 4764 expandTrigger.remove(); 4765 } 4766 if (bcListWidth <= bcListWrapper.width() || isExpanded) { 4767 container.addClass('breadcrumb--expanded'); 4768 } 4769 }; 4770 4771 var toggleBreadcrumbHeight = function(event) { 4772 var trigger = event.target,
4773 container = $(trigger).closest('.breadcrumb__container'), 4774 text = container.find('.breadcrumb__handle .btn__text'), 4775 icon = container.find('.breadcrumb__handle .btn__icon'); 4776 if (text.text() == 'Expand') { 4777 text.text('Collapse'); 4778 icon.addClass('icon--chevron-up').removeClass('icon--chevron-down'); 4779 container.addClass('breadcrumb--expanded'); 4780 isExpanded = true; 4781 } else if (text.text() == 'Collapse') { 4782 text.text('Expand'); 4783 icon.addClass('icon--chevron-down').removeClass('icon--chevron-up'); 4784 container.removeClass('breadcrumb--expanded'); 4785 isExpanded = false; 4786 } 4787 }; 4788 4789 var toggleBreadcrumbs = function() { 4790 var triggers = $('.site-menu'); 4791 4792 if(!triggers || typeof(triggers) == 'undefined' || triggers.length < 1) { 4793 $(window).off("scroll", toggleBreadcrumbs); 4794 return; 4795 } 4796 var trigger = $(triggers[0]); 4797 4798 var breadcrumbs = $("#breadcrumb"); 4799 if(!breadcrumbs || typeof(breadcrumbs) == 'undefined' || breadcrumbs.length < 1) { 4800 $(window).off("scroll", toggleBreadcrumbs); 4801 return; 4802 } 4803 var breadcrumb = $(breadcrumbs[0]); 4804 if(typeof(trigger.offset()) == 'undefined') { 4805 $(window).off("scroll", toggleBreadcrumbs); 4806 return; 4807 } 4808 4809 var relative_pos = trigger.height(); 4810 4811 if($(window).scrollTop() > relative_pos) { 4812 breadcrumb.css({'top': '66px'}); 4813 } 4814 else { 4815 breadcrumb.css({'top': '0px'}); 4816 } 4817 }; 4818 4819 var bc_resize_throttle = function(callback, delay){ 4820 delay = delay || 100; 4821 clearTimeout(resizeTimeout); 4822 resizeTimeout = setTimeout(callback, delay); 4823 }; 4824 4825 $(window).on('resize', function(){ 4826 bc_resize_throttle(breadcrumbWidth, 100); 4827 }); 4828 breadcrumbWidth(); 4829 4830 $(window).on("scroll", toggleBreadcrumbs); 4831 toggleBreadcrumbs(); 4832 4833 }; 4834 4835 setup(); 4836 }; 4837 4838 return TateBreadcrumbs; 4839}); 4840 4841define('components/TateShareIcons',['jquery', 'components/TateWindow'], function ($, TateWindow) { 4842 4843 var TateShareIcons = function (options) { 4844 options = options || {}; 4845 var me = this; 4846 4847 $(document).ready(function () { 4848 me.init(); 4849 }); 4850 }; 4851 4852 TateShareIcons.prototype = { 4853 init: function () { 4854 4855 var tateWindow = new TateWindow(), 4856 shareTimeout = null, 4857 icons = $('.image-strip__share-rollover'), 4858 disableHover = false; 4859 4860 var showIcons = function(){ 4861 icons.stop(true, false).fadeIn(150); 4862 }; 4863 4864 var hideIcons = function() { 4865 icons.stop(true, false).fadeOut(150); 4866 }; 4867 4868 $('.image-strip .rollover-button').on('mouseover', function() { 4869 clearTimeout(shareTimeout); 4870 if (!disableHover) { 4871 shareTimeout = setTimeout(showIcons, 200); 4872 } 4873 }).on('mouseleave', function(){ 4874 disableHover = false; 4875 clearTimeout(shareTimeout); 4876 }).on('click', showIcons); 4877 4878 $('.image-strip .rollover-close').on('click', function(){ 4879 // Prevent the icons popping up again as soon as the user moves their mouse 4880 disableHover = true; 4881 hideIcons(); 4882 }); 4883 $('.image-strip__share-rollover').on('mouseleave', function() { 4884 setTimeout(hideIcons, 100); 4885 }); 4886 4887 // TODO: Touchscreen users might click outside of the strip of icons to get rid of it 4888 // This will depend on listening for a tap event, which is not yet generally supported 4889 // within TateUI (see TateSlideshow for example of local support) 4890 /* 4891 if (icons.length) { 4892 $(window).on('tap', function(e){ 4893 // Touchscreen users might click outside of the strip of icons to get rid of it 4894 if (!$.contains(icons[0], e.target)) { 4895 hideIcons(); 4896 } 4897 }); 4898 } 4899 */ 4900 4901 // Make the social share functions open in a new window 4902 $('.image-strip__share-rollover .list--social a').on('click', function(e){ 4903 if (tateWindow.width() < 700 || tateWindow.height() < 700) 4904 return; // Don't try to force a pop-up on a small window. 4905 var href = $(this).attr('href'); 4906 if (href.substring(0, 4) != 'http') 4907 return; // Don't interfere with default behaviour of the 'share by email' link 4908 e.preventDefault(); 4909 window.open(href, 'targetWindow', "toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width="
4909+ 500 + ",height=" + 500); 4910 return false; 4911 }); 4912 4913 } 4914 }; 4915 4916 return TateShareIcons; 4917}); 4918 4919define('components/TateSplash',['jquery'], function ($) { 4920 var TateSplash = function () { 4921 var me = this; 4922 4923 $(document).ready(function () { 4924 me.init(); 4925 }); 4926 }; 4927 4928 TateSplash.prototype = { 4929 init: function () { 4930 var breakpoint = {}; 4931 breakpoint.refreshValue = function () { 4932 this.value = window.getComputedStyle(document.querySelector('body'), ':before').getPropertyValue('content').replace(/\"/g, ''); 4933 }; 4934 4935 var renderSplash = function(){ 4936 breakpoint.refreshValue(); 4937 4938 if (breakpoint.value == 'screen-wide' || 4939 breakpoint.value == 'screen-default' || 4940 breakpoint.value == 'screen-narrow' || 4941 breakpoint.value == 'tablet' ) { 4942 4943 $('.splash-header--style__splash-image').each(function(){ 4944 var splashImg; 4945 $(this).find('.splash-header__media--inner').trigger('lazyload:setup'); 4946 splashImg = $(this).find('.splash-header__media img').attr('data-original'); 4947 4948 if (!$(this).find('.splash-header__media--background').length) { 4949 $(this).find('.splash-header__media').prepend('<div class="splash-header__media--background"></div>'); 4950 } 4951 $(this).find('.splash-header__media--background').css({ 4952 backgroundImage: 'url("' + splashImg + '")' 4953 }); 4954 }); 4955 } 4956 }; 4957 4958 renderSplash(); 4959 4960 var resize_throttle = function(callback, delay) { 4961 var me = this; 4962 delay = delay || 100; 4963 clearTimeout(me.timeout); 4964 me.timeout = setTimeout(callback, delay); 4965 }; 4966 4967 $(window).on('resize', function(){ 4968 resize_throttle(renderSplash, 100); 4969 }); 4970 4971 } 4972 }; 4973 4974 // ************************************************************* 4975 // WHAT'S ON SPLASH: load random artwork image on What's On page 4976 4977 var TateWhatsOnSplash = function () { 4978 var me = this; 4979 4980 $(document).ready(function () { 4981 me.init(); 4982 }); 4983 4984 }; 4985 4986 TateWhatsOnSplash.prototype = { 4987 init: function () { 4988 var images = [ 4989 'http://www.tate.org.uk/art/images/work/N/N01/N01615_10.jpg', 4990 'http://www.tate.org.uk/art/images/work/N/N01/N01506_10.jpg', 4991 'http://www.tate.org.uk/art/images/work/N/N01/N01981_10.jpg', 4992 'http://www.tate.org.uk/art/images/work/T/T01/T01571_10.jpg', 4993 'http://www.tate.org.uk/art/images/work/N/N01/N01543_10.jpg' 4994 ]; 4995 4996 $('.container--whats-on__landing.background--image-canvas').css({ 4997 'background-image': 'url(' + images[Math.floor(Math.random() * images.length)] + ')' 4998 }); 4999 } 5000 }; 5001 5002 new TateWhatsOnSplash(); 5003 5004 return TateSplash; 5005}); 5006 5007define('components/TateAdvancedFilters',['jquery'], function ($) { 5008 5009 var TateAdvancedFilters = function () { 5010 var me = this; 5011 5012 $(document).ready(function () { 5013 me.init(); 5014 }); 5015 }; 5016 5017 TateAdvancedFilters.prototype = { 5018 init: function () { 5019 5020 // Recreate the what's on form to remove junk values that will pollute the URL. 5021 $('form.advanced-filters').on('submit', function(e){ 5022 e.preventDefault(); 5023 var orig = $(this); 5024 var form = $("<form id=\"dummy-advanced-filters-form\"></form>"); 5025 form.attr("action", orig.attr("action")); 5026 form.attr("method", "get"); 5027 orig.find('input[type=hidden]').each(function() { 5028 var value = $(this).attr('value'); 5029 var name = $(this).attr('name'); 5030 if (value === "" || !value || name === "" || !name) { 5031 return; 5032 } 5033 var input = $("<input type=\"hidden\" />"); 5034 input.attr("name", name); 5035 input.attr("value", value); 5036 form.append(input); 5037 }); 5038 orig.find('select').each(function(){ 5039 var value = $(this).find('option:selected').attr('value'); 5040 if (value === "" || !value) { 5041 return; 5042 } 5043 var input = $("<input type=\"hidden\" />"); 5044 input.attr("name", $(this).attr("name")); 5045 input.attr("value", $(this).find('option:selected').attr('value')); 5046 form.append(input); 5047 }); 5048 checkedValues = {}; 5049 orig.find('input:checked').each(function(){ 5050 var name = $(this).attr("name").replace("[]", ""); 5051 var valueList = checkedValues[name] || []; 5052 valueList.push($(this).attr("value")); 5053 checkedValues[name] = valueList; 5054 }); 5055 for (name in checkedValues) { 5056 var input = $("<input type=\"hidden\" />"); 5057 input.attr("name", name); 5058 input.attr("value", checkedValues[name].join(',')); 5059 form.append(input); 5060 } 5061 //TODO: add the values from the advanced filter checkboxes 5062 $("body").append(form); 5063 $("#dummy-advanced-filters-form").submit(); 5064 return false;
5065 }); 5066 5067 // Show/hide the advanced filter options 5068 $('.form-section--expand h3').on('click', function(){ 5069 var section = $(this).closest('.form-section--expand'); 5070 var holder = section.find('.form-section__content'); 5071 var content = holder.find('.fieldset-grid'); 5072 if (section.hasClass('form-section--expand__open')) { 5073 section.removeClass('form-section--expand__open'); 5074 holder.stop(false, false).animate({'max-height': '0px'}, 200); 5075 } else { 5076 section.addClass('form-section--expand__open'); 5077 holder.stop(false, false).animate({'max-height': content.height() + 'px'}, 200); 5078 } 5079 }); 5080 5081 } 5082 }; 5083 5084 return TateAdvancedFilters; 5085}); 5086 5087define('components/TateTabs',['jquery'], function($) { 5088 5089 var TateTabs = function() { 5090 5091 /** 5092 * Rewrite any local anchor links in a preview of an external text. 5093 */ 5094 var fixResearchText = function(text){ 5095 var researchLink = text.find('.research-text__canonical-link'); 5096 if (!researchLink.length || !researchLink.attr('href')) { return; } 5097 var researchPath = researchLink.attr('href'); 5098 text.find('a').each(function(){ 5099 var link = $(this); 5100 var href = link.attr('href'); 5101 if (href && href.length > 1 && href.substring(0,1) == "#") { 5102 link.attr('href', researchPath + href); 5103 } 5104 }); 5105 }; 5106 5107 /** 5108 Truncates the texts on artist and artwork pages, but only if it's worth it. 5109 Ensures that the text is never cut off before the bottom of the artwork tombstone 5110 or the artist portrait image. 5111 Needs to run on page load, when a research text is loaded via AJAX or when a user clicks on a different tab. 5112 */ 5113 var fixTruncation = function(){ 5114 var container = $('.content-truncate-container'), 5115 texts = $('.artwork__text').add('.artist__text'), 5116 must_be_visible = $('.content-block--details'); 5117 5118 var imageOK = function(img){ 5119 return (img.complete && img.naturalWidth != 0); 5120 } 5121 5122 if (container.length && texts.length) { 5123 5124 if (must_be_visible.length && must_be_visible.find('img').length) { 5125 // Check that any sidebar image has loaded as this affects our calculations 5126 var awaitingImage = false; 5127 must_be_visible.find('img').each(function(){ 5128 if (!$(this).attr('src') || $(this).attr('src').indexOf('placeholder') > 0 || !imageOK($(this)[0])) { 5129 awaitingImage = true; 5130 return; 5131 } 5132 }); 5133 if (awaitingImage) { 5134 // Defer truncation until we know the image height 5135 window.setTimeout(fixTruncation, 250); 5136 return; 5137 } 5138 } 5139 5140 // Find which text is visible 5141 var visible_text = texts.eq(0); 5142 if (texts.length > 1) { 5143 texts.each(function(){ 5144 if ($(this).hasClass('tab-section--active')) { 5145 visible_text = $(this); 5146 } 5147 }) 5148 } 5149 if (visible_text.attr('data-ajax-url')) { 5150 // Exit here if the text has not loaded yet. 5151 return; 5152 } 5153 5154 var max_h = 600; 5155 var text_xy = visible_text.offset(), 5156 container_xy = container.offset(), 5157 text_top = text_xy.top - container_xy.top, 5158 text_h = visible_text.outerHeight() + text_top; 5159 if (must_be_visible.length) { 5160 var must_be_visible_xy = must_be_visible.eq(0).offset(), 5161 must_be_visible_h = must_be_visible.eq(0).outerHeight() + must_be_visible_xy.top - container_xy.top; 5162 if (text_xy.top - must_be_visible_xy.top > 50) { // Mobile layout 5163 max_h = must_be_visible_h + 500; 5164 } else { // Desktop layout 5165 max_h = Math.max(max_h, (must_be_visible_h + 65)); 5166 } 5167 } 5168 5169 // Only apply truncation if there is enough surplus text to warrant hiding it. 5170 if ((text_h - max_h) > 100) { 5171 container.addClass('content-truncate-container--active').css({'max-height': max_h + 'px'}); 5172 visible_text.find('.text__read-more').show(); 5173 } else { 5174 container.removeClass('content-truncate-container--active').css({'max-height': 'none'}); 5175 if (!visible_text.hasClass('research-text')) { 5176 visible_text.find('.text__read-more').hide(); 5177 } 5178 } 5179 } 5180 }; 5181 5182 var init = function() { 5183 5184 /** 5185 * Enable tabbing between panels within a list of tabs. 5186 */ 5187 $('.tabs').each(function() { 5188 var $tab = $(this); 5189 if (!$(this).hasClass('tabs--rendered')) { 5190 $tab.addClass('tabs--rendered'); 5191 // click functionality for each tab link 5192 $tab.find('.tabs-menu__item a').on('click', function(e) { 5193 e.preventDefault(); 5194 var aID = $(this).attr('href'), 5195 tabBody = $(aID); 5196 $tab.find('.tabs-menu__item--active').removeClass('tabs-menu__item--active'); 5197 $tab.find('.tab-section--active').removeClass('tab-section--active'); 5198 $(this).parent().addClass('tabs-menu__item--active'); 5199 tabBody.addClass('tab-section--active'); 5200 // Expose a custom event so we can listen for the change 5201 $tab.trigger('tatetabs:tabchange'); 5202 }); 5203 } 5204 $tab.find(".tabs--back-to-menu").on('click', function(e) { 5205 e.preventDefault(); 5206 $('body').animate({ 5207 'scrollTop': ($tab.offset().top - $('header').height()) + 'px' 5208 }); 5209 }); 5210 }); 5211 5212 /**
5213 * Display the vertical tab menu on a mobile device 5214 */ 5215 $('.tabs--rendered').find('.tabs-menu__item').on('click', function(){ 5216 if ($(this).parent('li').hasClass('tabs-menu__item--active')) { 5217 e.preventDefault(); 5218 $(this).closest('ul').toggleClass("tabs-menu__list--mobile-active"); 5219 } 5220 else { 5221 $(this).closest('ul').toggleClass("tabs-menu__list--mobile-active"); 5222 } 5223 }); 5224 5225 $('.research-text').each(function(){ 5226 fixResearchText($(this)); 5227 }); 5228 5229 fixTruncation(); 5230 5231 /** 5232 * Very simple bit of Ajax code that does an ajax call for the URL in the 5233 * data-ajax-url attribute and fills that element with the HTML that 5234 * is returned. 5235 */ 5236 $('div[data-ajax-url]').each(function(index) { 5237 var el = $(this), 5238 container = el.find('.content-truncate-container'); 5239 el.load(el.attr('data-ajax-url'), function(){ 5240 el.removeAttr('data-ajax-url'); 5241 if (el.hasClass('research-text')) { 5242 fixResearchText(el); 5243 fixTruncation(); 5244 } 5245 }); 5246 }); 5247 5248 /** 5249 * Show the full text when user clicks 'Read more' button. 5250 */ 5251 $('.content-truncate-container').on('click', '.text__read-more a', function(e){ 5252 if ($(this).attr('href') != '#') { return; } 5253 e.preventDefault(); 5254 var container = $(this).closest('.content-truncate-container'), 5255 readMore = $(this).closest('.text__read-more'); 5256 if ($(this).find('.btn__text').text() === 'Read more') { 5257 container.css({'max-height': 'none'}); 5258 readMore.fadeOut(400); 5259 $('.content-truncate-container').removeClass('content-truncate-container--active'); 5260 } 5261 return false; 5262 }); 5263 5264 // Listen for a change in the active tab 5265 $('.content-truncate-container .tabs').on('tatetabs:tabchange', function(e){ 5266 fixTruncation(); 5267 }); 5268 5269 }; 5270 5271 $(document).ready(init); 5272 5273 }; 5274 5275 return TateTabs; 5276}); 5277 5278define('components/TateReviews',['jquery'], function ($) { 5279 var TateReviews = function () { 5280 var me = this; 5281 5282 $(document).ready(function () { 5283 me.init(); 5284 }); 5285 }; 5286 5287 TateReviews.prototype = { 5288 init: function () { 5289 5290 var reviewSwitcher = null, 5291 fadeDelay = 4000; 5292 5293 var switchReview = function(){ 5294 $('.review-block').each(function(){ 5295 var block = $(this), 5296 list = block.children('.review'); 5297 if (block.hasClass('review-block--paused')) { 5298 return; // Precaution against some odd browser behaviour 5299 } 5300 var length = list.length, 5301 current = list.filter('.active'); 5302 if (current.length == 1) { 5303 var i = list.index(current), 5304 next = (i == length -1) ? list.eq(0) : list.eq(i + 1); 5305 next.css({'z-index': 2, 'display': 'block'}); 5306 var read_time = next.attr('data-timeout'); 5307 if (!read_time) { 5308 var review_length = next.text().replace(/\W/g, '').length; 5309 read_time = Math.max(review_length * 50, 2000); 5310 next.attr('data-timeout', read_time); 5311 } 5312 current.stop(false, false).fadeOut(800, function(){ 5313 current.removeClass('active').css({'z-index': 1}); 5314 next.addClass('active').css({'z-index': 3}); 5315 start_switching(read_time); 5316 }); 5317 } 5318 }); 5319 }; 5320 5321 var sizeBlocks = function(){ 5322 $('.review-block').each(function(){ 5323 var block = $(this), 5324 list = block.children('.review'); 5325 var tallest = 0; 5326 list.each(function(){ 5327 tallest = Math.max(tallest, $(this).outerHeight()); 5328 }); 5329 block.css({'position': 'relative', 'height': tallest + 'px'}); 5330 }); 5331 }; 5332 5333 var resize_throttle = function(delay) { 5334 var me = this; 5335 delay = delay || 100; 5336 clearTimeout(me.timeout); 5337 stop_switching(); 5338 me.timeout = setTimeout(function(){ 5339 sizeBlocks(); 5340 start_switching(); 5341 }, delay); 5342 }; 5343 5344 var start_switching = function(delay){
5345 delay = delay || fadeDelay; 5346 reviewSwitcher = setTimeout(switchReview, delay); 5347 } 5348 5349 var stop_switching = function(){ 5350 clearTimeout(reviewSwitcher); 5351 reviewSwitcher = null; 5352 } 5353 5354 $(document).ready(function(){ 5355 5356 $('.review-block').each(function(){ 5357 var block = $(this), 5358 list = block.children('.review'); 5359 5360 if (list.length < 2) { return; } 5361 5362 // Prepare styles 5363 sizeBlocks(); 5364 list.css({ 5365 'position': 'absolute', 5366 'display': 'block', 5367 'z-index': 1, 5368 'width': '100%', 5369 'height': '100%', 5370 'box-sizing': 'border-box' 5371 }); 5372 list.eq(0).addClass('active').css({'z-index': 3}); 5373 5374 // Pause on current review if user hovers 5375 block.on({ 5376 mouseenter: function(){ 5377 if (list.length > 1) { 5378 stop_switching(); 5379 block.addClass('review-block--paused'); 5380 } 5381 }, 5382 mouseleave: function(){ 5383 if (list.length > 1) { 5384 start_switching(1000); 5385 block.removeClass('review-block--paused'); 5386 } 5387 } 5388 }); 5389 5390 }); 5391 5392 if ($('.review-block .active').length) { 5393 $(window).on("resize", resize_throttle); 5394 5395 // Get this show on the road! 5396 start_switching(); 5397 } 5398 5399 }); 5400 5401 } 5402 }; 5403 5404 return TateReviews; 5405}); 5406define('components/TateJPlayer',['jquery'], function ($) { 5407 var TateJPlayer = function () { 5408 var me = this; 5409 5410 $(document).ready(function () { 5411 me.init(); 5412 }); 5413 }; 5414 5415 TateJPlayer.prototype = { 5416 init: function () { 5417 5418 // is there at least one jplayer on this page? 5419 if ($('.jp-jplayer')[0]) { 5420 // create a <script> element to load jplayer library 5421 var jp = document.createElement('script'); 5422 $('body').append(jp); 5423 jp.onload = function() { 5424 // when the jplayer library has loaded, initialise the jplayers on this page 5425 $(".jp-jplayer").each(function(i) { 5426 var el = $(this); 5427 var audio_url = el.attr('data-audio-url'); 5428 if (!audio_url || typeof(audio_url) == 'undefined') { 5429 console.log("Missing parameter 'data-audio-url'"); 5430 el.remove(); 5431 return; 5432 } 5433 el.removeAttr('data-audio-url'); 5434 var title = el.attr('data-title'); 5435 el.removeAttr('data-title'); 5436 5437 var duration = el.attr('data-media-length'); 5438 if (!isNaN(duration)) // if numeric 5439 { 5440 // duration seconds to mm:ss 5441 var minutes = "0" + Math.floor(duration / 60); 5442 var seconds = "0" + (duration - minutes * 60); 5443 duration = minutes.substr(-2) + ":" + seconds.substr(-2); 5444 5445 el.removeAttr('data-media-length'); 5446 } 5447 5448 // assign unique id to audio wrapper 5449 el.attr('id','jquery_jplayer_'+i); 5450 // assign unique id to interface 5451 el.next('div').attr('id','jp_container_'+i); 5452 5453 el.jPlayer({ 5454 ready: function () { 5455 $(this).jPlayer("setMedia", { 5456 title: title, 5457 mp3: audio_url, 5458 duration: (duration == '00:00' || duration == null) ? null : duration, 5459 }); 5460 }, 5461 play: function() { 5462 $(".jp-jplayer").not(this).jPlayer("pause"); 5463 }, 5464 cssSelectorAncestor: "#jp_container_"+i, // link audio to interface 5465 swfPath: "//cdnjs.cloudflare.com/ajax/libs/jplayer/2.9.2/jplayer/", 5466 useStateClassSkin: true, 5467 autoBlur: false, 5468 smoothPlayBar: true, 5469 keyEnabled: true, 5470 remainingDuration: false, 5471 toggleDuration: true, 5472 preload: "none", 5473 }); 5474 }); 5475 }; 5476 jp.src = "//cdnjs.cloudflare.com/ajax/libs/jplayer/2.9.2/jplayer/jquery.jplayer.min.js"; 5477 } 5478 5479 } 5480 }; 5481 5482 return TateJPlayer; 5483}); 5484 5485define('components/TateInfiniteScroll',["jquery"], function ($) { 5486 5487 var TateInfiniteScroll = function() { 5488 5489 var init = function () { 5490 5491 var lockAjaxCall = false; // generate a single ajax call from many scroll events 5492 var chillOutScroller = 5; // avoid processing doInfiniteScroll too many times - a tiny scroll on the wheel of a mouse 5493 // generates tons of scroll events 5494 5495 var doInfiniteScroll = function(force) { 5496
5497 if(lockAjaxCall) 5498 return; 5499 5500 if(typeof(force) == 'undefined' || !force) { 5501 if(chillOutScroller-- > 1) 5502 return; 5503 chillOutScroller = 5; 5504 } 5505 5506 var triggers = $("span[data-ajax-type=infinite-scroll]"); 5507 if(!triggers || typeof(triggers) == 'undefined' || triggers.length < 1) { 5508 $(window).off("scroll", doInfiniteScroll); 5509 return; 5510 } 5511 5512 trigger = $(triggers[0]); 5513 5514 var ajax_url = trigger.attr("data-ajax-url"); 5515 if(!ajax_url) { 5516 $(window).off("scroll", doInfiniteScroll); 5517 return; 5518 } 5519 5520 var target = trigger.parent("div.card-list"); 5521 if(!target || target.length < 1) { 5522 $(window).off("scroll", doInfiniteScroll); 5523 return; 5524 } 5525 5526 if(typeof(trigger.offset()) == 'undefined') { 5527 $(window).off("scroll", doInfiniteScroll); 5528 return; 5529 } 5530 5531 relative_pos = trigger.offset().top - 300; // add 300 to fire the loading earlier 5532 5533 if($(window).scrollTop() >= relative_pos - $(window).height()) { 5534 lockAjaxCall = true; 5535 $.ajax(ajax_url) 5536 .done(function(data) { 5537 if(data) { 5538 target.append(data); 5539 trigger.remove(); 5540 if(typeof(TateUI) != 'undefined') 5541 TateUI.LazyLoad(); // need to re-active LazyLoad in case some new images were loaded into the DOM 5542 lockAjaxCall = false; 5543 } 5544 }); 5545 } 5546 }; 5547 5548 $(window).on("scroll", doInfiniteScroll); 5549 doInfiniteScroll(true); // also fire on page load 5550 }; 5551 5552 init(); 5553 }; 5554 5555 return TateInfiniteScroll; 5556}); 5557 5558define('components/BannerSlider',['jquery', 'vendor/slick'], function ($, Slick) { 5559 var BannerSlider = function () { 5560 this.init(); 5561 }; 5562 5563 BannerSlider.prototype = { 5564 init: function () { 5565 /** LOCAL CONFIGURATION OBJECTS **/ 5566 5567 /** DOM READY SCRIPTS **/ 5568 $(document).ready(function () { 5569 $('.main-banner').slick({ 5570 dots: true, 5571 arrows: false, 5572 infinite: true, 5573 autoplay: true, 5574 autoplaySpeed: 10000, 5575 pauseOnHover: true, 5576 pauseOnDotsHover: true, 5577 slidesToShow: 1, 5578 slidesToScroll: 1, 5579 draggable: false, 5580 lazyLoad: 'ondemand' 5581 }); 5582 }); 5583 } 5584 }; 5585 5586 return BannerSlider; 5587}); 5588 5589define('components/TateModalManager',['jquery'], function ($) { 5590 5591 "use strict"; 5592 5593 var TateModalManager = function () { 5594 5595 var self = this; 5596 5597 $(document).ready(function () { 5598 var config = typeof TateModalManagerConfig !== "undefined" ? TateModalManagerConfig : {}; 5599 self.init(config); 5600 }); 5601 }; 5602 5603 5604 TateModalManager.prototype = { 5605 5606 /** 5607 * Tate Modal Manager ping -> pong game 5608 */ 5609 ping: function () { 5610 return 'pong'; 5611 }, 5612 5613 loadModal: function (event) { 5614 event.preventDefault(); 5615 5616 if (typeof $(this).data('event') !== 'undefined') { 5617 // Push dataLayer for googleTagManager 5618 var $event = $(this).data('event'), 5619 $label = typeof $(this).data('label') === 'undefined' ? "" : $(this).data('label'); 5620 5621 dataLayer.push({ 5622 event : $event, 5623 label : $label 5624 }); 5625 } 5626 5627 // only show modal if user is logged-in - else use default href behaviour 5628 if ($(this).attr('href').indexOf("/user?destination=") !== -1) { 5629 window.location.href = $(this).attr('href'); 5630 return true; 5631 } 5632 5633 // need to have either the connected element or the AJAX url callback 5634 if (typeof(event.data) == 'undefined' || (typeof(event.data.ajax_url) == 'undefined' && typeof(event.data.html_element) == 'undefined')) { 5635 return false;
5636 } 5637 5638 var params = { 5639 className: typeof $(this).attr('data-class') !== null ? $(this).attr('data-class') : '', 5640 scrolling: false, 5641 maxWidth: '624px', 5642 width: '90%', 5643 onComplete: function () { 5644 $.fn.colorbox.resize(); 5645 } 5646 }; 5647 5648 if (event.data.ajax_url) { 5649 var ajax_url = $(this).attr('data-ajax-url'); // data-ajax-url may have been updated by a script 5650 $ 5651 .ajax(ajax_url) 5652 .done(function(data) { 5653 params['html'] = data; 5654 $.colorbox(params); 5655 TateUI.Tabs(); 5656 }); 5657 } 5658 else if (event.data.html_element) { 5659 var content = $("#" + event.data.html_element); 5660 if (content) { 5661 params['html'] = content.prop('innerHTML'); 5662 $.colorbox(params); 5663 } 5664 } 5665 return false; 5666 }, 5667 5668 /** 5669 * Init function 5670 */ 5671 init: function (config) { 5672 var self = this; 5673 5674 $.extend(self, { 5675 config: config 5676 }); 5677 5678 // observers for modal events 5679 $(window).on("CalendarOnModalAppear", function (event, inst) { 5680 $("a[data-ajax-type=modal]").each(function() { 5681 // test href is set and != data-anon-href 5682 // test data-ajax-url is set, if so, on click: ajax callback, shows the returned HTML in a modal box 5683 var el = $(this); 5684 var href = el.attr('href'); 5685 var anon_href = el.attr('data-anon-href'); 5686 5687 // hmmm no guarantee that the above (done by TateLogin.js) would be processed before this code hmm hmm 5688 // perhaps it could check that the 'href' doesn't start in /user...? 5689 if (typeof(anon_href) !== 'undefined' && href === anon_href) { 5690 return; // user not logged-in - don't need to show the modal 5691 } 5692 5693 var params = {} 5694 var ajax_url = el.attr('data-ajax-url'); // ajax callback to get the content 5695 var html_element = el.attr('data-ajax-element'); // content is already in the DOM 5696 if (!ajax_url || typeof(ajax_url) === 'undefined') { 5697 if (!html_element || typeof(html_element) === 'undefined') { // ajax_url has priority over html_element 5698 return; 5699 } else { 5700 params['html_element'] = html_element; 5701 } 5702 } else { 5703 params['ajax_url'] = ajax_url; 5704 } 5705 5706 el.off('click').on("click", null, params, self.loadModal); 5707 }); 5708 }); 5709 } 5710 }; 5711 5712 return TateModalManager; 5713}); 5714 5715define('components/TateAccordionManager',['jquery'], function ($) { 5716 5717 "use strict"; 5718 5719 var TateAccordionManager = function () { 5720 5721 var self = this; 5722 5723 $(document).ready(function () { 5724 var config = typeof TateAccordionManagerConfig !== "undefined" ? TateAccordionManagerConfig : {}; 5725 self.init(config); 5726 }); 5727 }; 5728 5729 TateAccordionManager.prototype = { 5730 /** 5731 * Init function 5732 */ 5733 init: function (config) { 5734 var self = this; 5735 5736 $(window).on("TateAccordionCatch", function (event) { 5737 var $elements = $('.accordion'); 5738 if ($elements.length > 0) { 5739 $.each($elements, function (index, item) { 5740 $(item).accordion({ 5741 heightStyle: "content" 5742 }); 5743 }); 5744 } 5745 }); 5746 5747 $(window).trigger("TateAccordionCatch"); 5748 } 5749 }; 5750 5751 return TateAccordionManager; 5752}); 5753 5754define('components/TateAccordionPanelManager',['jquery'], function ($) { 5755 5756 "use strict"; 5757 5758 var TateAccordionPanelManager = function () { 5759 5760 var self = this; 5761 5762 $(document).ready(function () { 5763 var config = typeof TateAccordionPanelManagerConfig !== "undefined" ? TateAccordionPanelManagerConfig : {}; 5764 self.init(config); 5765 }); 5766 }; 5767 5768 TateAccordionPanelManager.prototype = { 5769 /** 5770 * Init function 5771 */ 5772 init: function (config) { 5773 var self = this; 5774 5775 $(window).on("TateAccordionPanelCatch", function (event) { 5776 var $elements = $('.banner-panel--accordion'); 5777 if ($elements.length > 0 && $elements.size() > 0) { 5778 $.each($elements, function (index, item) { 5779 var id = $(item).data('id'); 5780 $('a[data-id=handle]').off('click').on('click', function (e) { 5781 e.preventDefault(); 5782 var state = $(item).data('state'); 5783 if (state === 'closed') { 5784 $('.icon--chevron-down', $(item)).hide(); 5785 $('.icon--chevron-up', $(item)).show(); 5786 $(item).data('state', 'opened'); 5787 $('#' + id).slideDown(); 5788 } else { 5789 $('.icon--chevron-down', $(item)).show(); 5790 $('.icon--chevron-up', $(item)).hide(); 5791 $(item).data('state', 'closed'); 5792 $('#' + id).slideUp(); 5793 } 5794 }); 5795 }); 5796 } 5797 }); 5798 } 5799 }; 5800 5801 return TateAccordionPanelManager; 5802}); 5803 5804define('components/TateUtil',['jquery'], function ($) { 5805 5806 "use strict"; 5807 5808 var TateUtil = { 5809 appendParamToURL: function (url, name, value) { 5810 if (url.indexOf(name + '=') !== -1) { 5811 return url; 5812 } 5813 var separator = url.indexOf('?') !== -1 ? '&' : '?'; 5814 return url + separator + name + '=' + encodeURIComponent(value); 5815 }, 5816 appendParamsToUrl: function (url, params) { 5817 var _url = url; 5818 $.each(params, function (name, value) { 5819 _url = this.appendParamToURL(_url, name, value); 5820 }.bind(this)); 5821 return _url; 5822 }, 5823 ajaxUrl: function (path) { 5824 return this.appendParamToURL(path, 'format', 'ajax'); 5825 }, 5826 getDayNumberSuffix: function (day) { 5827 if (day >= 11 && day <= 13) { 5828 return "th"; 5829 } 5830 switch (day % 10) { 5831 case 1: 5832 return "st"; 5833 case 2: 5834 return "nd"; 5835 case 3: 5836 return "rd"; 5837 default: 5838 return "th"; 5839 } 5840 }, 5841 /** 5842 * @function
5843 * @description remove the parameter and its value from the given url and returns the changed url 5844 * @param {String} url the url from which the parameter will be removed 5845 * @param {String} name the name of parameter that will be removed from url 5846 */ 5847 removeParamFromURL: function (url, name) { 5848 if (url.indexOf('?') === -1 || url.indexOf(name + '=') === -1) { 5849 return url; 5850 } 5851 var hash; 5852 var params; 5853 var domain = url.split('?')[0]; 5854 var paramUrl = url.split('?')[1]; 5855 var newParams = []; 5856 // if there is a hash at the end, store the hash 5857 if (paramUrl.indexOf('#') > -1) { 5858 hash = paramUrl.split('#')[1] || ''; 5859 paramUrl = paramUrl.split('#')[0]; 5860 } 5861 params = paramUrl.split('&'); 5862 for (var i = 0; i < params.length; i++) { 5863 // put back param to newParams array if it is not the one to be removed 5864 if (params[i].split('=')[0] !== name) { 5865 newParams.push(params[i]); 5866 } 5867 } 5868 return domain + '?' + newParams.join('&') + (hash ? '#' + hash : ''); 5869 } 5870 }; 5871 return TateUtil; 5872}); 5873 5874 5875 5876define('components/TatePushStatePageManager',['jquery', 'components/TateUtil'], function ($, TateUtil) { 5877 5878 var TatePushStatePageManager = function () { 5879 5880 var self = this; 5881 5882 $(document).ready(function () { 5883 var config = typeof TatePushStatePageManagerConfig !== "undefined" ? TatePushStatePageManagerConfig : {}; 5884 self.init(config); 5885 }.bind(this)); 5886 }; 5887 5888 TatePushStatePageManager.prototype = { 5889 continuebtn: '.go-continue', 5890 stickyContinueBtnn: '.go-continue-sticky', 5891 continueBtnHiddenClass: 'go-continue-hidden', 5892 stickyContinueInactiveClass: 'go-continue-sticky-inactive', 5893 backbtn: '.go-back', 5894 backBtnHiddenClass: 'go-back-hidden', 5895 stickyBottomCard: '.sticky-bottom-card', 5896 inactiveClass: 'inactive', 5897 tabletBreakpoint: 839, 5898 5899 /** 5900 * Hides prev button 5901 */ 5902 hidePrev: function () { 5903 $(this.backbtn).addClass(this.backBtnHiddenClass); 5904 }, 5905 /** 5906 * Hides next button 5907 */ 5908 hideNext: function () { 5909 $(this.continuebtn).addClass(this.continueBtnHiddenClass); 5910 $(this.stickyContinueBtnn).addClass(this.stickyContinueInactiveClass); 5911 $(this.stickyBottomCard).addClass(this.inactiveClass); 5912 // Add for ticketing sticky continue 5913 $(this.saveAndContinueStickyBtn).addClass(this.saveAndContinueStickyInactiveClass); 5914 }, 5915 /** 5916 * Show next button 5917 */ 5918 showNext: function () { 5919 // Only show the desktop continue button if the window width is greater than the tablet breakpoint 5920 if ($(window).width() > this.tabletBreakpoint) { 5921 $(this.continuebtn).removeClass(this.continueBtnHiddenClass); 5922 } 5923 $(this.stickyContinueBtnn).removeClass(this.stickyContinueInactiveClass); 5924 $(this.stickyBottomCard).removeClass(this.inactiveClass); 5925 // Remove for ticketing sticky continue 5926 $(this.saveAndContinueStickyBtn).removeClass(this.saveAndContinueStickyInactiveClass); 5927 }, 5928 /** 5929 * Show prev button 5930 */ 5931 showPrev: function () { 5932 $(this.backbtn).removeClass(this.backBtnHiddenClass); 5933 }, 5934 /** 5935 * Go to alias location 5936 * @param {string} where destination alias 5937 */ 5938 goTO: function(where) { 5939 var self = this; 5940 $.each(this.config.steps, function (index, value) { 5941 if (value.slug === where) { 5942 var conf = value; 5943 history.pushState({page: conf.slug}, conf.title, conf.url); 5944 this.config.currentIndex = index; 5945 this.load(conf.url); 5946 return false; 5947 } 5948 }.bind(this)); 5949 }, 5950 /** 5951 * Return prev url object or null 5952 * @return {object} 5953 */ 5954 getPrevURL: function () { 5955 if (this.config.currentIndex === 0) { 5956 return null; 5957 } 5958 return this.config.steps[this.config.currentIndex - 1]; 5959 }, 5960 /** 5961 * Returns next url object or null 5962 * @return {object} 5963 */ 5964 getNextURL: function () { 5965 if ((this.config.currentIndex + 1) === this.config.steps.length) { 5966 return null; 5967 } 5968 return this.config.steps[this.config.currentIndex + 1]; 5969 }, 5970 prevURL: function () { 5971 if (this.config.currentIndex === 0) { 5972 if (typeof this.config.prevURL !== "undefined" && this.config.prevURL !== null) { 5973 document.location = this.config.prevURL; 5974 } else { 5975 window.history.go(-1); 5976 } 5977 } else { 5978 this.config.currentIndex--; 5979 var conf = this.config.steps[this.config.currentIndex]; 5980 /** Does it have a prevURL config */ 5981 if (this.config.redirectURL !== 'null' 5982 && this.config.steps[this.config.currentIndex - 1].url.length > 0) { 5983 document.location = this.config.steps[this.config.currentIndex - 1].url; 5984 } else { 5985 if (this.config.steps[this.config.currentIndex + 1].backURL !== false) { 5986 document.location = this.config.steps[this.config.currentIndex + 1].backURL; 5987 } 5988 /** is it disabled */ 5989 else if (conf.disabled === false) { 5990 history.pushState({page: conf.slug}, conf.title, conf.url); 5991 this.load(conf.url); 5992 } 5993 } 5994 } 5995 }, 5996 nextURL: function (shouldContinue) { 5997 var self = this; 5998 if (shouldContinue) { 5999 if ((this.config.currentIndex + 1) === this.config.steps.length) { 6000 if (typeof this.config.nextURL !== "undefined" && this.config.nextURL !== null) { 6001 document.location = this.config.nextURL; 6002 } else { 6003 window.history.go(1); 6004 } 6005 } else { 6006 this.config.currentIndex++; 6007 var conf = this.config.steps[this.config.currentIndex]; 6008 history.pushState({page: conf.slug}, conf.title, conf.url); 6009 this.load(conf.url); 6010 } 6011 } 6012 }, 6013 events: function () { 6014 var self = this; 6015 6016 $(this.backbtn).off('click').on('click', function (e) { 6017 e.preventDefault(); 6018 if (window.history.length > 1) { 6019 window.history.back(); 6020 } else { 6021 self.prevURL(); 6022 } 6023 }); 6024 6025 $(this.continuebtn).off('click').on('click', function (e) { 6026 e.preventDefault(); 6027 6028 // if ($(this).hasClass('members-only-no-go')) { 6029 // return; 6030 // } 6031 6032 // Check if there is a form that should be submitted on the page
6033 // and prevent going to next step if form is not valid 6034 var $form = $(this).parents('form.validateStep:not(.suppress)'), 6035 shouldContinue = $form.length ? $form.validate().form() : true; 6036 self.nextURL(shouldContinue); 6037 }); 6038 6039 // Add handler for sticky continue button 6040 $(this.stickyContinueBtnn).off('click').on('click', function (e) { 6041 e.preventDefault(); 6042 var $form = $(this).parents('form.validateStep:not(.suppress)'), 6043 shouldContinue = $form.length ? $form.validate().form() : true; 6044 self.nextURL(shouldContinue); 6045 }); 6046 6047 $(window).off('popstate').on('popstate', function(e) { 6048 self.prevURL(); 6049 }); 6050 6051 $(window).off('TatePushStatePageReplace').on('TatePushStatePageReplace', function(e, id, url) { 6052 $.each(self.config.steps, function (index, value) { 6053 if (value.slug == id) { 6054 value.url = url; 6055 } 6056 }); 6057 }); 6058 6059 $(window).off('TatePushStateNeedReload').on('TatePushStateNeedReload', function(e) { 6060 self.collectSteps(); 6061 self.events(); 6062 }); 6063 6064 $(window).off('cardHolders').on('cardHolders', function(e) { 6065 self.continuebtn = '.go-continue'; 6066 self.events(); 6067 }); 6068 6069 /** 6070 * Hides back buttons 6071 * @return void 6072 */ 6073 $(window).off('TatePushStateManagerHideBackButton').on('TatePushStateManagerHideBackButton', function(e) { 6074 self.hidePrev(); 6075 }); 6076 6077 /** 6078 * Check whatever we need to show or hide back buttons 6079 * @return void 6080 */ 6081 $(window).off('TatePushStateManagerBackButtonCheckState').on('TatePushStateManagerBackButtonCheckState', function(e) { 6082 var prevURL = self.getPrevURL(); 6083 if (prevURL !== null && prevURL.disabled === true) { 6084 $(window).trigger('TatePushStateManagerHideBackButton'); 6085 } 6086 }); 6087 }, 6088 /** 6089 * Load a URL with ajax format 6090 */ 6091 load: function (url) { 6092 var self = this; 6093 6094 $(window).trigger('GTMVirtualPageView', [url]); 6095 6096 $.ajax(TateUtil.ajaxUrl(url)).done(function(data) { 6097 $('.' + self.config.contentClass).html(data); 6098 if (typeof TatePushStatePageManagerConfig !== "undefined") { 6099 $.extend(self.config, TatePushStatePageManagerConfig); 6100 } 6101 6102 if (typeof TatePushStatePageManagerConfig !== 'undefined' && self.config.redirectURL !== 'null') { 6103 window.location.href = self.config.redirectURL; 6104 } else { 6105 self.collectSteps(); 6106 self.events(); 6107 $(window).trigger('PushStatePageOnLoadComplete', [url, typeof self.config.meta !== "undefined" ? self.config.meta.title : null]); 6108 } 6109 }); 6110 }, 6111 6112 /** 6113 * 6114 */ 6115 collectSteps: function () { 6116 var self = this; 6117 this.config.steps = []; 6118 $('.select-steps li[data-href]:not(.skip)').each(function(index, value) { 6119 var o = { 6120 slug: $(this).data('slug'), 6121 url: $(this).data('href'), 6122 disabled: typeof $(this).data('disabled') !== "undefined" ? $(this).data('disabled') : false, 6123 backURL: typeof $(this).data('back-url') !== "undefined" ? $(this).data('back-url') : false 6124 }; 6125 $(this).off('click').on('click', 'a', function (e) { 6126 e.preventDefault(); 6127 self.goTO($(this).parent().data('slug')); 6128 }); 6129 if (o.slug === self.config.currentLocation) { 6130 self.config.currentIndex = index; 6131 } 6132 self.config.steps.push(o); 6133 }); 6134 }, 6135 6136 init: function (config) { 6137 var self = this; 6138 6139 // deactivate if config not found 6140 if (typeof config.currentLocation === "undefined") { 6141 return; 6142 } 6143 this.config = config; 6144 this.collectSteps(); 6145 this.events(); 6146 } 6147 }; 6148 6149 return TatePushStatePageManager; 6150 6151}); 6152define('components/TateCalendarManager',['jquery', 'components/TatePushStatePageManager', 'components/TateUtil'], function ($, TatePushStatePageManager, TateUtil) { 6153 6154 "use strict"; 6155 6156 /** 6157 * Replace brief text 6158 * @param {String} text replacement target 6159 * @return {String} replaced text 6160 */ 6161 var replaceBrief = function (text) { 6162 return text.replace('(', '<span class="brief">').replace(')', '</span>'); 6163 }; 6164 6165 var TateCalendarManager = function () { 6166 6167 var self = this; 6168 6169 $(document).ready(function () { 6170 var config = typeof TateCalendarManagerConfig !== "undefined" ? TateCalendarManagerConfig : {}; 6171 self.init(config); 6172 }); 6173 6174 // Listen for push state page load complete (AJAX navigation) 6175 $(window).on('PushStatePageOnLoadComplete', function (e, inst) { 6176 var config = typeof TateCalendarManagerConfig !== "undefined" ? TateCalendarManagerConfig : {}; 6177 self.init(config); 6178 }); 6179 }; 6180 6181 TateCalendarManager.prototype = { 6182 toString: function (date) { 6183 return moment(date).format('YYYYMMDD'); 6184 }, 6185 6186 toDate: function (date) {
6187 return date !== null && date !== "null" ? moment(date, 'YYYYMMDD').toDate() : null; 6188 }, 6189 6190 getStartDate: function () { 6191 return this.RecordFilter.startdate; 6192 }, 6193 6194 setStartDate: function (year, month, day) { 6195 var month = month + 1; 6196 var date = year + '' + (month < 10 ? "0" + month : month) + '' + day; 6197 this.RecordFilter.startdate = Math.max(this.toDate(date), this.config.today); 6198 this.RecordFilter.enddate = this.toDate(moment(this.RecordFilter.startdate).add(2, 'months')); 6199 }, 6200 6201 getEndDate: function () { 6202 return this.RecordFilter.enddate; 6203 }, 6204 6205 getToday: function () { 6206 return this.config.today; 6207 }, 6208 6209 getOffset: function () { 6210 return this.config.offset; 6211 }, 6212 6213 getCount: function () { 6214 if (this.config.isMobileScreen()) { 6215 return this.config.count / 2; 6216 } 6217 return this.config.count; 6218 }, 6219 6220 /** 6221 * Get category id 6222 */ 6223 getCGID: function () { 6224 return this.config.cgid; 6225 }, 6226 6227 /** 6228 * Get product id 6229 */ 6230 getPID: function () { 6231 return this.config.pid; 6232 }, 6233 6234 /** 6235 * Get variant id 6236 */ 6237 getVID: function () { 6238 return this.config.vid; 6239 }, 6240 6241 getTimeSlotID: function () { 6242 return this.config.selected.timeSlotId; 6243 }, 6244 6245 splitTime: function (time) { 6246 return time.split(':'); 6247 }, 6248 6249 /** 6250 * Returns current selected variant 6251 * stock qty 6252 */ 6253 getCurrentVariantStockQty: function () { 6254 var self = this, 6255 qty = 0; 6256 $.each(self.config.times, function (index, value) { 6257 if (value.timeslot === self.config.selected.time) { 6258 qty = value.stock; 6259 return false; 6260 } 6261 }); 6262 if (qty === 0 && !!self.config.selected.vats) { 6263 qty = self.config.selected.vats; 6264 } 6265 return qty; 6266 }, 6267 6268 /** 6269 * Check whatever we need to show the 6270 * selected tickets pannel 6271 * @param {String} location current location 6272 */ 6273 showSelectedTickets: function (location) { 6274 return ['Donations', 'DonationsGiftAid'].indexOf(location) !== -1; 6275 }, 6276 6277 /** 6278 * Single validation function 6279 * validation routing by its param 6280 */ 6281 validate: function (what) { 6282 var $time = $('.card-footer-selected-time'), 6283 $date = $('.card-footer-selected-date'), 6284 $tickets = $('.card-footer-selected-tickets'); 6285 6286 if (!this.showSelectedTickets(this.config.currentLocation)) { 6287 $tickets.hide(); 6288 } 6289 6290 if (what === 'date') { 6291 if (this.config.selected.date === "null") { 6292 this.TatePushStatePageManager.hideNext(); 6293 $('.display-selected-date', $date).text(''); 6294 $('.display-selected-date-date').text(''); 6295 $('.display-selected-date-time').text(''); 6296 } else { 6297 $('.display-selected-date', $date).text(moment(this.toDate(this.config.selected.date)).format("ddd DD MMM YYYY")); 6298 $('.display-selected-date-date').text(moment(this.toDate(this.config.selected.date)).format("ddd DD MMMM YYYY")); 6299 this.TatePushStatePageManager.showNext(); 6300 } 6301 } 6302 6303 else if (what === 'time') { 6304 if (this.config.selected.time === "null") { 6305 this.TatePushStatePageManager.hideNext(); 6306 } else { 6307 this.TatePushStatePageManager.showNext(); 6308 } 6309 if (this.config.selected.time !== "null") { 6310 var selectedTime = this.splitTime(this.config.selected.time); 6311 6312 if (selectedTime[0] === Resources.ALL_DAY) { 6313 $('.display-selected-time', $time).text(selectedTime[0]); 6314 $('.display-selected-date-time').text(selectedTime[0]); 6315 } else { 6316 $('.display-selected-time', $time).text(moment(new Date(2017, 11, 8, selectedTime[0], selectedTime[1], 0)).format("H:mm")); 6317 $('.display-selected-date-time').text(" " + moment(new Date(2017, 11, 8, selectedTime[0], selectedTime[1], 0)).format("H:mm").toLowerCase()); 6318 } 6319 6320 6321 $time.slideDown(); 6322 } else { 6323 $time.slideUp(function () { 6324 $('.display-selected-time', $time).text(''); 6325 $('.display-selected-date-time').text(''); 6326 }); 6327 } 6328 } 6329 6330 else if (what === 'tickets') { 6331 6332 var self = this, reachedSlotLimit = false, slotLimit; 6333 6334 if ('tickets' in this.config.selected && Object.keys(this.config.selected.tickets).length > 0) { 6335 6336 $.each(this.config.selected.tickets, function (index, value) { 6337 6338 slotLimit = self.config.tickets[index] && self.config.tickets[index].ticketPurchaseLimit; 6339 6340 if (slotLimit && value > slotLimit) { 6341 reachedSlotLimit = true; 6342 $('input[data-id="' + index + '"]').addClass('item--qty__border--red'); 6343 } else { 6344 $('input[data-id="' + index + '"]').removeClass('item--qty__border--red'); 6345 } 6346 }); 6347 } 6348 6349 if (reachedSlotLimit) { 6350 $('.privileged-ticket-purchase-limit-warn-wrap').show(); 6351 } else { 6352 $('.privileged-ticket-purchase-limit-warn-wrap').hide(); 6353 } 6354
6355 var total = this.getSelectedTicketsTotal(); 6356 6357 // Set the ticket purchase limits 6358 $('.ticket-purchase-limit-warn-wrap span.ticket-purchase-limit').text(this.config.ticketPurchaseLimit); 6359 $('.collective-ticket-purchase-limit-warn-wrap span.ticket-purchase-limit').text(this.config.collectivePurchaseLimit); 6360 6361 if (total > 0) { 6362 this.renderSelectedTickets(); 6363 if (this.showSelectedTickets(this.config.currentLocation)) { 6364 $tickets.slideDown(); 6365 } 6366 } else { 6367 $tickets.slideUp(function () { 6368 $('.display-selected-tickets', $tickets).text(''); 6369 }); 6370 } 6371 if (total === 0 || reachedSlotLimit) { 6372 $('.go-save-and-continue').addClass('go-save-and-continue-hidden'); 6373 $('.ticket-purchase-limit-warn-wrap').hide(); 6374 $('.go-save-and-continue-sticky').addClass('go-save-and-continue-inactive-sticky'); 6375 $('.sticky-bottom-card-select').addClass('inactive'); 6376 6377 } else if ((this.config.ticketPurchaseLimit && total > this.config.ticketPurchaseLimit) || total > this.getCurrentVariantStockQty() || (this.config.customerIsCollectiveMember && this.getSelectedCollectiveTicketsTotal() > this.config.collectivePurchaseLimit)) { 6378 6379 if (this.config.customerIsCollectiveMember && this.getSelectedCollectiveTicketsTotal() > this.config.collectivePurchaseLimit) { 6380 $('.collective-ticket-purchase-limit-warn-wrap').show(); 6381 } 6382 6383 if (this.config.ticketPurchaseLimit && total > this.config.ticketPurchaseLimit) { 6384 $('.ticket-purchase-limit-warn-wrap').show(); 6385 $('.ticket-purchase-limit-stock-warn-wrap').hide(); 6386 $('.go-save-and-continue-sticky').addClass('go-save-and-continue-inactive-sticky'); 6387 $('.sticky-bottom-card-select').addClass('inactive'); 6388 } else { 6389 $('.ticket-purchase-limit-warn-wrap').hide(); 6390 if (total > this.getCurrentVariantStockQty()) { 6391 $('.ticket-purchase-limit-stock-warn-wrap').show(); 6392 $('.go-save-and-continue-sticky').addClass('go-save-and-continue-inactive-sticky'); 6393 $('.sticky-bottom-card-select').addClass('inactive'); 6394 } else { 6395 $('.ticket-purchase-limit-stock-warn-wrap').hide(); 6396 $('.go-save-and-continue-sticky').removeClass('go-save-and-continue-inactive-sticky'); 6397 $('.sticky-bottom-card-select').removeClass('inactive'); 6398 } 6399 } 6400 $('.go-save-and-continue').addClass('go-save-and-continue-hidden'); 6401 $('.mem-ticket-purchase-limit-warn-wrap').hide(); 6402 6403 } else if (this.config.memberPurchaseLimit && ((this.config.onlyMemberPrivilege && total > this.config.memberPurchaseLimit) ||
6404 this.getSelectedMemTicketsTotal() > this.config.memberPurchaseLimit)) { 6405 $('.mem-ticket-purchase-limit-warn-wrap').show(); 6406 $('.ticket-purchase-limit-warn-wrap').hide(); 6407 $('.ticket-purchase-limit-stock-warn-wrap').hide(); 6408 $('.go-save-and-continue').addClass('go-save-and-continue-hidden'); 6409 } else { 6410 var $buttonToBasket = $('.go-save-and-continue.to-basket'); 6411 var $buttonToDonation = $('.go-save-and-continue.to-donation'); 6412 var $stickyButton = $('.go-save-and-continue-sticky'); 6413 var $stickyBottomCard = $('.sticky-bottom-card-select'); 6414 if (this.checkForGiftAidExemptTickets() || this.config.hasExemptTicketsInBasket) { 6415 $buttonToBasket.removeClass('go-save-and-continue-hidden'); 6416 $buttonToDonation.addClass('go-save-and-continue-hidden'); 6417 $stickyButton.removeClass('go-save-and-continue-inactive-sticky go-save-and-continue-hidden'); 6418 $stickyBottomCard.removeClass('inactive'); 6419 } else { 6420 $buttonToDonation.removeClass('go-save-and-continue-hidden'); 6421 $buttonToBasket.addClass('go-save-and-continue-hidden'); 6422 $stickyButton.removeClass('go-save-and-continue-inactive-sticky go-save-and-continue-hidden'); 6423 $stickyBottomCard.removeClass('inactive'); 6424 } 6425 6426 $('.ticket-purchase-limit-warn-wrap').hide(); 6427 $('.collective-ticket-purchase-limit-warn-wrap').hide(); 6428 $('.ticket-purchase-limit-stock-warn-wrap').hide(); 6429 $('.mem-ticket-purchase-limit-warn-wrap').hide(); 6430 } 6431 } 6432 6433 else if (what === 'giftAid') { 6434 if (this.config.selected.giftAid !== "null") { 6435 $('.go-save-and-continue').removeClass('go-save-and-continue-hidden'); 6436 $('.go-save-and-continue-donation').removeClass('go-save-and-continue-donation-hidden'); 6437 $('.go-save-and-continue-sticky').removeClass('go-save-and-continue-inactive-sticky'); 6438 $('.sticky-bottom-card-select').removeClass('inactive'); 6439 this.TatePushStatePageManager.hideNext(); 6440 } else { 6441 $('.go-save-and-continue').addClass('go-save-and-continue-hidden'); 6442 $('.go-save-and-continue-donation').addClass('go-save-and-continue-donation-hidden'); 6443 $('.go-save-and-continue-sticky').addClass('go-save-and-continue-inactive-sticky'); 6444 $('.sticky-bottom-card-select').addClass('inactive'); 6445 this.TatePushStatePageManager.hideNext(); 6446 } 6447 } 6448 6449 else if (what === 'donation') { 6450 6451 } 6452 }, 6453 6454 getPIDFromDate: function (date) { 6455 var pid = null; 6456 $.each(this.config.products, function (index, product) { 6457 if (this.toString(moment(date)) === product.date) { 6458 pid = product.id; 6459 return false; 6460 } 6461 }.bind(this)); 6462 return pid; 6463 }, 6464 6465 getViewPort: function () { 6466 return this.config.viewport; 6467 }, 6468 6469 /** 6470 * Flag so that resize doesn't trigger 6471 * the redraw if in same view port 6472 */ 6473 setViewPort: function () { 6474 this.config.viewport = this.config.isMobileScreen() ? "mobile" : "desktop"; 6475 }, 6476 6477 setSelectDate: function (date) { 6478 if (this.config.selected.date !== this.toString(date)) { 6479 this.config.selected.time = "null"; 6480 this.config.selected.tickets = {}; 6481 } 6482 this.config.selected.date = this.toString(date); 6483 this.config.selected.month = moment(date).format('MM'); 6484 var pid = this.getPIDFromDate(date); 6485 if (pid) { 6486 this.config.pid = pid; 6487 $(document).trigger( 6488 'TatePushStatePageReplace', 6489 [ 6490 'SelectEntryTime', 6491 TateUtil.appendParamsToUrl( 6492 this.config.urls.selectEntryTime, 6493 {'prid': pid} 6494 ) 6495 ] 6496 ); 6497 this.hasAdvanceTicket(pid); 6498 6499 // set new day sold out href 6500 var url = TateUtil.removeParamFromURL($('.day-sold-out-trigger').data('ajax-url'), 'variant'); 6501 url = TateUtil.appendParamsToUrl(url, {'variant':pid}); 6502 6503 var exhibition = TateUtil.removeParamFromURL($('.day-sold-out-exhibition-trigger').data('ajax-url'), 'variant'); 6504 exhibition = TateUtil.appendParamsToUrl(exhibition, {'variant':pid}); 6505 6506 // set new url 6507 $('.day-sold-out-trigger').attr('data-ajax-url', url); 6508 $('.day-sold-out-exhibition-trigger').attr('data-ajax-url', exhibition); 6509 6510 // re-ini modal 6511 $(window).trigger("CalendarOnModalAppear"); 6512 6513 //this.loadDaySoldOut(pid); 6514 } 6515 this.validate('time'); 6516 this.validate('date'); 6517 this.validate('tickets'); 6518 this.saveToSession(); 6519 }, 6520 6521 setSelectedTime: function (id, time) { 6522 var vid = this.getVIDFromID(id); 6523 $(document).trigger( 6524 'TatePushStatePageReplace', 6525 [ 6526 'SelectTickets', 6527 TateUtil.appendParamsToUrl( 6528 this.config.urls.selectTickets, 6529 {'variant_pr_id': vid} 6530 ) 6531 ] 6532 ); 6533 if (this.config.selected.time !== time) { 6534 this.config.selected.tickets = {}; 6535 this.renderSelectedTickets(); 6536 } 6537 this.config.vid = vid; 6538 this.config.selected.timeSlotId = id; 6539 this.config.selected.time = time; 6540 this.validate('time'); 6541 this.validate('tickets'); 6542 this.saveToSession(); 6543 }, 6544 6545 selectTime: function (id, time) { 6546 $('div.timeslot--selected').removeClass('timeslot--selected'); 6547 $('div[data-id=' + id + ']').addClass('timeslot--selected'); 6548 this.setSelectedTime(id, time); 6549 }, 6550 6551 getVIDFromID: function (id) { 6552 var vid = null; 6553 $.each(this.config.variants, function (index, value) { 6554 if (value.time === id) { 6555 vid = value.id; 6556 return false;
6557 } 6558 }); 6559 return vid; 6560 }, 6561 6562 /** 6563 * Check whatever today date is available 6564 * @return {Boolean} 6565 */ 6566 isTodayEnabled: function () { 6567 var self = this; 6568 var today = self.getToday(), 6569 anabled = true; 6570 $.each(self.config.products, function (index, product) { 6571 var date = self.toDate(product.date); 6572 if (date.valueOf() == today.valueOf()) { 6573 anabled = product.show; 6574 return false; 6575 } 6576 }); 6577 return anabled; 6578 }, 6579 6580 /** 6581 * Deactivate today calendar cell 6582 */ 6583 deactivateTodayCell: function () { 6584 $('.dw-cal-today').removeClass('dw-cal-day-marked dw-cal-e dwb-e dwb-nhl'); 6585 $('.dw-cal-today').css('cursor', 'default'); 6586 $('.dw-cal-today').on('click', function (e) { 6587 e.stopPropagation(); 6588 }); 6589 }, 6590 6591 setUnavailableTabIndex: function () { 6592 $('.dw-cal-day[aria-disabled="true"], .dw-cal-day[aria-hidden="true"]').attr('tabindex', '-1'); 6593 }, 6594 6595 setSoldOutDays: function() { 6596 6597 var i, soldOutDate, $dayCell; 6598 var soldOutDates = this.config.soldOutDates; 6599 6600 if (!soldOutDates) { 6601 return; 6602 } 6603 6604 for (i = 0; i < soldOutDates.length; ++i) { 6605 6606 soldOutDate = soldOutDates[i]; 6607 6608 $dayCell = $('.dw-cal-day[data-full="' + soldOutDate + '"]'); 6609 $dayCell.addClass('dw-cal-sold-out'); 6610 $dayCell.on('click touchstart', function (e) { 6611 e.stopPropagation(); 6612 }); 6613 } 6614 }, 6615 6616 openTicketsModal: function() { 6617 var self = this; 6618 6619 var modalMaxHeight = ''; 6620 var headerHeight=0; 6621 if ($(window).width() < 720) { 6622 $(window).height()-66; 6623 modalMaxHeight = $(window).height()-66; 6624 headerHeight=66; 6625 } 6626 if ($(window).width() >= 720 && $(window).width() <= 1024 ) { 6627 modalMaxHeight = $(window).height()-60; 6628 headerHeight=60; 6629 } 6630 if ($(window).width() > 1024) { 6631 modalMaxHeight = $(window).height()-80; 6632 headerHeight=80; 6633 } 6634 modalMaxHeight = modalMaxHeight.toString()+'px'; 6635 var desiredHeight='calc(100%-' +headerHeight +'px)'; 6636 const modalToUse = !self.config.isBookingNotRequiredEvent ? self.config.urls.memberOnlyEventModal : self.config.urls.memberOrSupporterModal; 6637 6638 $.colorbox({ 6639 href: TateUtil.appendParamsToUrl(modalToUse, {'cgid': self.config.cgid}), 6640 className: 'member-or-supporter-modal', 6641 width: '100%', 6642 height: '100%', 6643 maxWidth: desiredHeight, 6644 opacity:0, 6645 top:headerHeight, 6646 maxHeight: modalMaxHeight, 6647 closeButton: false, 6648 overlayClose: false, 6649 onComplete: function() { 6650 6651 $('.member-or-supporter-continue-button').on('click', function(e) { 6652 e.preventDefault(); 6653 $.colorbox.close(); 6654 }); 6655 6656 $(document).tooltip({ 6657 items: '.tooltip', 6658 content: function () { 6659 return $(this).find('.tooltip-content').html(); 6660 } 6661 }); 6662 6663 $('.member-or-supporter-email').on('click', function() { 6664 window.open('mailto:' + $(this).text()); 6665 }); 6666 } 6667 }); 6668 6669 $('body').css('overflow', 'hidden'); 6670 $('body').css('position', 'fixed'); 6671 $('body').css('width', '100%'); 6672 6673 $(document).bind('cbox_closed', function(){ 6674 $('body').css('overflow', 'auto'); 6675 $('body').css('position', 'static'); 6676 }); 6677 }, 6678 6679 openExhibitionLunchModal: function() { 6680 var $banner = $('.tickets-admission-lunch-banner').first(); 6681 var $lunchModal = $banner.find('.tickets-lunch-modal').first(); 6682 var $lunchModalWrapper = $lunchModal.parent('.tickets-exhibition-lunch-modal-wrapper'); 6683 var lunchModalWrapperId = 'tickets-exhibition-lunch-modal-inline'; 6684 6685 if (!$lunchModal.length) { 6686 $lunchModal = $banner.next('.tickets-lunch-modal'); 6687 $lunchModalWrapper = $lunchModal.parent('.tickets-exhibition-lunch-modal-wrapper'); 6688 } 6689 6690 if (!$lunchModal.length) { 6691 $lunchModal = $banner.next('.tickets-exhibition-lunch-modal-wrapper').find('.tickets-lunch-modal'); 6692 $lunchModalWrapper = $lunchModal.parent('.tickets-exhibition-lunch-modal-wrapper'); 6693 } 6694 6695 if (!$lunchModal.length) { 6696 return; 6697 } 6698 6699 if (!$lunchModalWrapper.length) { 6700 $lunchModal.wrap('<div class="tickets-exhibition-lunch-modal-wrapper"></div>'); 6701 $lunchModalWrapper = $lunchModal.parent(); 6702 } 6703 6704 if (!$lunchModalWrapper.attr('id')) { 6705 $lunchModalWrapper.attr('id', lunchModalWrapperId); 6706 } 6707 6708 $lunchModal.removeClass('d-none'); 6709 6710 $.colorbox({ 6711 inline: true, 6712 href: '#' + $lunchModalWrapper.attr('id'), 6713 className: 'tickets-lunch-modal-popup', 6714 width: '95%', 6715 maxWidth: '960px', 6716 maxHeight: '90%', 6717 closeButton: true, 6718 onComplete: function() { 6719 $.fn.colorbox.resize(); 6720 }, 6721 onCleanup: function() { 6722 $lunchModal.addClass('d-none'); 6723 } 6724 }); 6725 }, 6726 6727 renderSelectDate: function () { 6728 var self = this; 6729 self.adjustStickyButton(); 6730 6731 $(window).trigger('CalendarOnModalAppear', [self]); 6732 6733 // Set viewPort flag (for responsive redraw) 6734 self.setViewPort(); 6735 6736 6737 if (!self.config.isLoggedIn && !self.config.isMemberEventsModalOpened) { 6738 self.openTicketsModal(); 6739 self.config.isMemberEventsModalOpened = true; 6740 } 6741 6742 // observers for calendar events 6743 $(window).off('CalendarOnDayChange').on("CalendarOnDayChange", function (event, day, inst) { 6744 self.setSelectDate(day.date); 6745 }); 6746 6747 $(self.config.renderElement).mobiscroll().calendar({ 6748 currentDate: self.getToday(), 6749 sessionTimeOut: '+20m', 6750 display: 'inline', 6751 layout: 'liquid', 6752 navigation: 'month', 6753 markedDisplay: 'bottom', 6754 months: self.ConfigTranslator.getMonths(), 6755 calendarHeight: 300, 6756 minDate: self.ConfigTranslator.getMinDate(), 6757 maxDate: self.ConfigTranslator.getMaxDate(), 6758 markedText: true, 6759 weekDays: 'short', 6760 highlightNow: false, 6761 marked: self.ConfigTranslator.getMarkedDays(), 6762 swipe: self.ConfigTranslator.getSwipe(), 6763 defaultValue: self.ConfigTranslator.getDefaultValue(), 6764 mousewheel: false, 6765 firstDay: 1, 6766 onDayChange: function (day, inst) { 6767 6768 $(window).trigger('CalendarOnDayChange', [day, inst]); 6769 }, 6770 onDestroy: function (inst) {}, 6771 onEventSelect: function (e, event, d, inst) { 6772 $(window).trigger('CalendarOnEventSelect', [e, event, d, inst]); 6773 }, 6774 onInit: function (inst) { 6775 $(window).trigger('CalendarOnInit', [self, inst]); 6776 }, 6777 onMonthLoaded: function (year, month, inst) { 6778 6779 // check today calendar state 6780 // deactivate if it is not available 6781 if (!self.isTodayEnabled()) { 6782 self.deactivateTodayCell(); 6783 } 6784 self.setUnavailableTabIndex(); 6785 self.setSoldOutDays(); 6786 6787 $(window).trigger('CalendarOnMonthLoaded', [year, month, inst]); 6788 }, 6789 onMonthChange: function (year, month, inst) { 6790 $(window).trigger('CalendarOnMonthChange', [year, month, inst]); 6791 } 6792 }); 6793 6794 $(window).resize(function() { 6795 if (self.config.isMobileScreen() === true && self.getViewPort() !== "mobile") { 6796 self.setViewPort(); //Reset viewport flag 6797 $(self.config.renderElement).mobiscroll('option', { 6798 months: self.ConfigTranslator.getMonths() 6799 }); 6800 } 6801 6802 if (self.config.isMobileScreen() === false && self.getViewPort() !== "desktop") { 6803 self.setViewPort(); //Reset viewport flag 6804 $(self.config.renderElement).mobiscroll('option', { 6805 months: self.ConfigTranslator.getMonths() 6806 }); 6807 } 6808 6809 if (!self.config.isLoggedIn && !self.config.isMemberEventsModalOpened) { 6810 if ($("#colorbox.member-or-supporter-modal").css("display") == "block") { 6811 self.openTicketsModal(); 6812 } 6813 } 6814 6815 setTimeout(function() { 6816 $('.member-or-supporter-modal').colorbox.resize({ 6817 height: window.innerHeight, 6818 width: window.innerWidth 6819 }); 6820 }, 100); 6821 }); 6822 6823 }, 6824 6825 /** 6826 * Checks available Advanced Tickets 6827 */ 6828 hasAdvanceTicket: function (pid) { 6829 if (typeof pid === "undefined") { 6830 return; 6831 } 6832 $.ajax(TateUtil.appendParamsToUrl(this.config.urls.hasAdvanceTicket, {'pid': pid, 'format': 'ajax'})).done(function (data) { 6833 if (!data.success) { 6834 $('#advanceTicket').hide(); 6835 } else { 6836 $('#advanceTicket').slideDown(); 6837 } 6838 }); 6839 }, 6840 6841 /** 6842 * Day sold out check 6843 * @param {string} pid product id 6844 */ 6845 loadDaySoldOut: function (pid) { 6846 var self = this; 6847 if (typeof pid === "undefined") { 6848 return; 6849 } 6850 $.ajax(TateUtil.appendParamsToUrl(this.config.urls.daySoldOut, {'pid': pid, 'format': 'ajax'})).done(function (data) { 6851 if (typeof data.daySoldOut !== undefined && data.daySoldOut === true) { 6852 self.config.selected.date = "null"; 6853 self.validate('date'); 6854 6855 if (data.isExhibition) { 6856 $('.day-sold-out-exhibition-trigger').trigger('click'); 6857 } else { 6858 $('.day-sold-out-trigger').trigger('click'); 6859 } 6860 } 6861 }); 6862 }, 6863 6864 /** 6865 * Load function 6866 */ 6867 loadDates: function (year, month, inst) { 6868 var self = this; 6869 if (!inst.refreshing) { 6870 self.setStartDate(year, month, '01'); 6871 6872 var url = TateUtil.appendParamsToUrl(self.config.urls.categoryJSON, { 6873 startDate: self.toString(self.getStartDate()), 6874 endDate: self.toString(self.getEndDate()), 6875 offset: self.getOffset(), 6876 count: self.getCount(), 6877 cgid: self.getCGID(), 6878 format: 'ajax' 6879 }); 6880 $.ajax({ 6881 url: url, 6882 dataType: 'json', 6883 beforeSend: function () { 6884 inst.disable(); 6885 } 6886 }).done(function (data) { 6887 6888 if (data.tessituraDown) { 6889 self.loadServiceDown(); 6890 } 6891 6892 self.config.products = data.products; 6893 self.config.productsdates = []; 6894 self.config.soldOutDates = []; 6895 6896 $.each(data.products, function (index, value) { 6897 self.config.productsdates.push(value.date); 6898 }); 6899 6900 inst.settings.marked = []; 6901 6902 inst.refreshing = true; 6903 inst.settings.marked = self.ConfigTranslator.getMarkedDays(); 6904 inst.settings.invalid = self.ConfigTranslator.getInvalidDays(); 6905 6906 inst.redraw(); 6907 inst.refreshing = false;
6908 6909 inst.enable(); 6910 6911 self.validate('date'); 6912 6913 }); 6914 } 6915 }, 6916 6917 loadServiceDown: function() { 6918 6919 var self = this; 6920 6921 $('.ticket-content-ajax').load(self.config.urls.serviceDown); 6922 }, 6923 6924 /** 6925 * Create a days array from a date period 6926 * used to determine whatever we have a valid or invalid day 6927 * if the day exist in the period and not found in ticket list 6928 * the day is market as invalid 6929 */ 6930 createDaysFromPeriod: function (from, to) { 6931 var days = [], 6932 currentDay = from, 6933 i = 0; 6934 while (currentDay.valueOf() <= to.valueOf()) { 6935 days.push(this.toString(currentDay)); 6936 currentDay = moment(currentDay).add(1, 'days'); 6937 i++; 6938 } 6939 return days; 6940 }, 6941 6942 /** 6943 * Gets the total selected tickets 6944 */ 6945 getSelectedTicketsTotal: function () { 6946 var total = 0; 6947 if ('tickets' in this.config.selected && Object.keys(this.config.selected.tickets).length > 0) { 6948 $.each(this.config.selected.tickets, function (index, value) { 6949 total += parseInt(value); 6950 }); 6951 } 6952 return total; 6953 }, 6954 6955 /** 6956 * Gets the total selected mem tickets 6957 */ 6958 getSelectedMemTicketsTotal: function () { 6959 var self = this, total = 0; 6960 6961 if (Object.keys(this.config.selected.tickets).length > 0) { 6962 $.each(this.config.selected.tickets, function (index, value) { 6963 6964 if (self.config.memOptionsIds.indexOf(index) != -1) { 6965 total += parseInt(value); 6966 } 6967 }); 6968 } 6969 return total; 6970 }, 6971 6972 /** 6973 * Gets the total selected collective tickets 6974 */ 6975 getSelectedCollectiveTicketsTotal: function () { 6976 var self = this, total = 0, collectiveOptionIDArr = Resources.COLLECTIVE_OPTION_ID.split(','); 6977 6978 if (Object.keys(this.config.selected.tickets).length > 0) { 6979 $.each(this.config.selected.tickets, function (key, value) { 6980 6981 if (collectiveOptionIDArr.indexOf(key) > -1) { 6982 total += parseInt(value); 6983 } 6984 6985 }); 6986 } 6987 return total; 6988 }, 6989 6990 // check what need to be checked 6991 locationChange: function (flowStarted) { 6992 var self = this, 6993 cols = this.config.isMobileScreen() ? 1 : 2, 6994 $date = $('.card-footer-selected-date'), 6995 $promo = $('.membership-promo'), 6996 $membershipUpsell = $('.membership-upsell-overlay'), 6997 $heading = $('.select-a-date'), 6998 $time = $('.card-footer-selected-time'), 6999 $continueBtn = $('.start-flow'), 7000 $tickets = $('.card-footer-selected-tickets'); 7001 7002 if (TateCalendarManagerConfig.pid !== "null") { 7003 this.config.selected.pid = TateCalendarManagerConfig.pid; 7004 }
7005 if (TateCalendarManagerConfig.selected.date !== "null") { 7006 this.config.selected.date = TateCalendarManagerConfig.selected.date; 7007 } 7008 if (TateCalendarManagerConfig.selected.time !== "null") { 7009 this.config.selected.time = TateCalendarManagerConfig.selected.time; 7010 } 7011 if (TateCalendarManagerConfig.selected.vid !== "null") { 7012 this.config.selected.vid = TateCalendarManagerConfig.selected.vid; 7013 } 7014 if (TateCalendarManagerConfig.selected.timeSlotId !== "null") { 7015 this.config.selected.timeSlotId = TateCalendarManagerConfig.selected.timeSlotId; 7016 } 7017 if (TateCalendarManagerConfig.selected.vats !== "null") { 7018 this.config.selected.vats = TateCalendarManagerConfig.selected.vats; 7019 } 7020 if (TateCalendarManagerConfig.selected.giftAid !== "null") { 7021 this.config.selected.giftAid = TateCalendarManagerConfig.selected.giftAid; 7022 } 7023 /** sets selectDateDisabled from configuration */ 7024 if (typeof TateCalendarManagerConfig.selectDateDisabled !== "undefined") { 7025 this.config.selectDateDisabled = TateCalendarManagerConfig.selectDateDisabled; 7026 } 7027 /** sets selectEntryTimeDisabled from configuration */ 7028 if (typeof TateCalendarManagerConfig.selectEntryTimeDisabled !== "undefined") { 7029 this.config.selectEntryTimeDisabled = TateCalendarManagerConfig.selectEntryTimeDisabled; 7030 } 7031 /** sets isTicketDonationEnabled from configuration */ 7032 if (typeof TateCalendarManagerConfig.isTicketDonationEnabled !== "undefined") { 7033 this.config.isTicketDonationEnabled = TateCalendarManagerConfig.isTicketDonationEnabled; 7034 } 7035 7036 // add event observers 7037 $('.edit-selected-date').off('click').on('click', function (e) { 7038 e.preventDefault(); 7039 self.TatePushStatePageManager.goTO('SelectDate'); 7040 }); 7041 7042 $('.edit-selected-time').off('click').on('click', function (e) { 7043 e.preventDefault(); 7044 self.TatePushStatePageManager.goTO('SelectEntryTime'); 7045 }); 7046 7047 $('.edit-selected-tickets').off('click').on('click', function (e) { 7048 e.preventDefault(); 7049 self.TatePushStatePageManager.goTO('SelectTickets'); 7050 }); 7051 7052 if ($continueBtn.length > 0) { 7053 $continueBtn.off('click').on('click', function(e) { 7054 e.preventDefault(); 7055 $membershipUpsell.hide(); 7056 self.config.hideCalendar = false; 7057 self.config.selected.hideCalendar = false; 7058 self.locationChange(); 7059 }); 7060 } 7061 7062 // bind close event 7063 $(document).off('cbox_complete').on('cbox_complete', function () { 7064 $('a.choose-another-time, a.choose-another-date').off('click').on('click', function (e) { 7065 e.preventDefault(); 7066 $.colorbox.close(); 7067 }); 7068 }); 7069 7070 this.validate('date'); 7071 this.validate('time'); 7072 if (!!self.config.times && self.config.times.length) { 7073 this.validate('tickets'); 7074 } else { 7075 self.setTimes(function () { 7076 self.validate('tickets'); 7077 }); 7078 } 7079 this.validate('giftAid'); 7080
7081 if (this.config.selected.date !== "null") { 7082 $date.slideDown(); 7083 } else { 7084 $date.slideUp(); 7085 } 7086 7087 // show selected time 7088 if (this.config.selected.time !== "null") { 7089 $time.slideDown(); 7090 } else { 7091 $time.slideUp(); 7092 } 7093 7094 /** 7095 * show selected tickets if qty > 0 and is it not disabled 7096 */ 7097 if (this.getSelectedTicketsTotal() > 0 && 7098 this.showSelectedTickets(this.config.currentLocation)) { 7099 $tickets.slideDown(); 7100 } else { 7101 $tickets.hide(); 7102 } 7103 7104 /** 7105 * show selected date if it is not on Select Date and is not diabled 7106 */ 7107 if (['SelectDate'].indexOf(this.config.currentLocation) === -1 && 7108 this.config.selectDateDisabled === false) { 7109 $('.edit-selected-date-wrap', $date).slideDown(); 7110 } else { 7111 $('.edit-selected-date-wrap', $date).slideUp(); 7112 } 7113 7114 if (['SelectDate', 'SelectEntryTime'].indexOf(this.config.currentLocation) === -1 && 7115 this.config.selectEntryTimeDisabled === false) { 7116 $('.edit-selected-time-wrap', $time).slideDown(); 7117 } else { 7118 $('.edit-selected-time-wrap', $time).slideUp(); 7119 } 7120 7121 // selected tickets 7122 if (this.showSelectedTickets(this.config.currentLocation)) { 7123 $('.edit-selected-tickets-wrap', $tickets).slideDown(); 7124 } else { 7125 $('.edit-selected-tickets-wrap', $tickets).hide(); 7126 } 7127 7128 switch (this.config.currentLocation) { 7129 case 'SelectDate': 7130 if (!this.config.hideCalendar || !self.config.selected.hideCalendar || !$continueBtn.length > 0) { 7131 $heading.show(); 7132 this.renderSelectDate(); 7133 $membershipUpsell.hide(); 7134 } 7135 $(".card-group").addClass("SelectDate"); 7136 break; 7137 7138 case 'SelectEntryTime': 7139 this.renderSelectEntryTime(); 7140 $(".card-group").addClass("SelectEntryTime"); 7141 break; 7142 7143 case 'SelectTickets': 7144 this.renderSelectTickets(); 7145 $(".card-group").addClass("SelectTickets"); 7146 break; 7147 7148 case 'Donations': 7149 this.setGiftAid("null"); 7150 7151 this.renderDonations(); 7152 break; 7153 7154 case 'DonationsGiftAid': 7155 this.renderDonationsGiftAid(); 7156 break; 7157 } 7158 7159 /** 7160 * Trigger back button visibility check 7161 */ 7162 $(document).trigger('TatePushStateManagerBackButtonCheckState'); 7163 7164 $(window).scrollTop(0); 7165 }, 7166 7167 getSelectedTicketQty: function (id) { 7168 return typeof this.config.selected.tickets !== "undefined" && typeof this.config.selected.tickets[id] !== "undefined" ? this.config.selected.tickets[id] : 0; 7169 }, 7170 7171 renderSelectEntryTime: function () { 7172 var self = this, 7173 cols = this.config.isMobileScreen() ? 1 : 2; 7174 self.adjustStickyButton(); 7175 7176 $(window).trigger('CalendarOnModalAppear', [self]); 7177 7178 if (!self.config.isLoggedIn && !self.config.isMemberEventsModalOpened) { 7179 self.openTicketsModal(); 7180 self.config.isMemberEventsModalOpened = true; 7181 } 7182 // load times 7183 $.ajax({ 7184 url: TateUtil.appendParamsToUrl(this.config.urls.selectTime, { 7185 pid: this.getPID(), 7186 format: 'ajax' 7187 }) 7188 }).done(function(data) { 7189 7190 if (data.tessituraDown) { 7191 self.loadServiceDown(); 7192 return; 7193 } 7194 7195 if (data.timeslots.length == 0 && data.expiredMembership) { 7196 self.openMembershipRenewModal(2); 7197 } 7198 7199 var hasSpecialTimeslots = data.hasSpecialTimeslots; 7200 7201 self.config.times = data.timeslots; 7202 self.config.variants = data.variants; 7203 7204 var times = []; 7205 7206 var $html = '<div class="grid grid-outer">'; 7207 if (cols === 2) { 7208 $html += '<div class="grid__inner grid-col--50">left</div>'; 7209 $html += '<div class="grid__inner grid-col--50">right</div>'; 7210 } else { 7211 $html += '<div class="grid__inner">one</div>'; 7212 } 7213 $html += '</div>'; 7214 7215 var variantsAvailability = {}; 7216 7217 for (var variable in data.variants) { 7218 var currentVariant = data.variants[variable]; 7219 variantsAvailability[currentVariant.time] = currentVariant.isAvailable; 7220 } 7221 7222 // render times 7223 $.each(self.config.times, function (index, value) { 7224 var cls = value.timeslot === self.config.selected.time && value.active ? 'timeslot--selected' : ''; 7225 if ((index + 1) === self.config.times.length) { 7226 cls += ' last-child'; 7227 } 7228 7229 if (hasSpecialTimeslots) { 7230 cls += ' bigger-timeslot'; 7231 } 7232 7233 var lunchMessage = ''; 7234 var lunchCls = ''; 7235 7236 if (value.lunchMessage) { 7237 lunchMessage = value.lunchMessage + '<br>'; 7238 lunchCls = ' plus-lunch-msg'; 7239 } 7240 7241 if (variantsAvailability[value.vid] && value.active) { 7242 value.html = '<div role="button" tabindex="0" data-action="selectTime" data-id="' + value.vid + '" data-time="' + value.timeslot + '" class="timeslot ' + cls + '">'; 7243 } else { 7244 value.html = '<div class="timeslot timeslot--disabled ' + cls + '">'; 7245 } 7246 if (value.passholdersOnly) { 7247 7248 if (value.stockMessage) { 7249 value.html += '<p class="passholders-only-msg passholders-only-plus-stock' + lunchCls + '"> ' + lunchMessage + value.passholdersOnlyMsg + '<br>' + value.stockMessage + '</p>'; 7250 } else { 7251 value.html += '<p class="passholders-only-msg' + lunchCls + '"> ' + lunchMessage + value.passholdersOnlyMsg + '</p>'; 7252 } 7253 } else if (value.stockMessage) { 7254 value.html += '<p class="stock--msg stock--msg__' + value.stockMessageType + lunchCls + '"> ' + lunchMessage + value.stockMessage + '</p>'; 7255 } else if (lunchMessage) { 7256 value.html += '<p class="lunch-msg"> ' + value.lunchMessage + '</p>'; 7257 } 7258 var timeslot = self.splitTime(value.timeslot); 7259 value.html += '<p><i class="icon icon--tick"></i> ' + (moment(new Date(2017, 11, 8, timeslot[0], timeslot[1], 0)).format("h:mmA")).toLowerCase() + '</p>'; 7260 if (value.briefMessage !== '') { 7261 var text = $('<div />').html(value.briefMessage).html().replace('-ajax-url-', self.config.urls.pageShowMembershipBenefits); 7262 value.html += '<div class="brief-msg">
7262' + text + '</div>'; 7263 } 7264 value.html += '</div>'; 7265 times.push(value); 7266 }); 7267 7268 if (cols === 2) { 7269 var leftHTML = "", 7270 rightHTML = ""; 7271 7272 $.each(times.splice(0, Math.ceil(times.length / 2)), function (index, value) { 7273 leftHTML += value.html; 7274 }); 7275 7276 $.each(times, function (index, value) { 7277 rightHTML += value.html; 7278 }); 7279 7280 $html = $html.replace('left', leftHTML); 7281 $html = $html.replace('right', rightHTML); 7282 } else { 7283 var oneHTML = ''; 7284 $.each(times, function (index, value) { 7285 oneHTML += value.html; 7286 }); 7287 $html = $html.replace('one', oneHTML); 7288 } 7289 7290 // inject 7291 $('#entryTime').html($html); 7292 7293 // attack events 7294 $('#entryTime div[data-action=selectTime]').off('click').on('click', function (e) { 7295 e.preventDefault(); 7296 var id = $(this).attr('data-id'), 7297 time = $(this).attr('data-time'); 7298 self.selectTime(id, time); 7299 }); 7300 7301 // dispatch CalendarOnModalAppear event 7302 // to notify the modal manager 7303 // that we need assistance 7304 $(window).trigger('CalendarOnModalAppear', [self]); 7305 7306 // dispatch TateAccordionPanelCatch event 7307 // to notify the accordion panel manager 7308 // that we need assistance 7309 $(document).trigger('TateAccordionPanelCatch'); 7310 7311 self.validate('time'); 7312 7313 if (window.location.search.indexOf('qrcode=') > -1 && !data.hasAvailableTickets) { 7314 7315 $.colorbox({ 7316 href: TateUtil.appendParamsToUrl(self.config.urls.soldOutModal, {'cgid': self.config.cgid}), 7317 className: 'today-sold-out-modal', 7318 width: '95%', 7319 maxWidth: '670px', 7320 closeButton: false 7321 }); 7322 7323 $('body').css('overflow', 'hidden'); 7324 $('body').css('position', 'fixed'); 7325 $('body').css('width', '100%'); 7326 7327 $(document).bind('cbox_closed', function(){ 7328 $('body').css('overflow', 'auto'); 7329 $('body').css('position', 'static'); 7330 }); 7331 } 7332 7333 7334 }.bind(this)); 7335 }, 7336 7337 decrementIncrementEvents: function() { 7338 var self = this; 7339 7340 // decrement event handler 7341 $('.option-item button.btn--action_decrement').off('click').on('click', function (e) { 7342 e.preventDefault(); 7343 var id = $(this).data('id'); 7344 self.decrementTicket(id); 7345 }); 7346 7347 // increment event handler 7348 $('.option-item button.btn--action_increment').off('click').on('click', function (e) { 7349 e.preventDefault(); 7350 var id = $(this).data('id'); 7351 self.incrementTicket(id); 7352 }); 7353 }, 7354 7355 promoAjaxCall: function() { 7356 var self = this; 7357 var pcdCode = $('[data-id="promo"]').val(); 7358 7359 $.ajax(TateUtil.appendParamsToUrl(self.config.urls.checkPromoCode, { 7360 pcdCode: pcdCode, 7361 pid: self.config.selected.vid 7362 7363 })).done(function(data) { 7364 if (data.success) { 7365 var priceHolderText = '<span class="price-holder">' + data.priceText + '</span>', 7366 id = data.id; 7367 7368 // Create html for recieved ticket. 7369 var $pcdTicket = [ 7370 '<div data-id="' + id + '" class="grid grid-outer option-item green-class">', 7371 ' <div class="grid__inner grid-col--40 option-item-desc">', 7372 ' <span class="desc promo-ticket">' + replaceBrief(data.description) + '</span>', 7373 priceHolderText, 7374 ' </div>', 7375 ' <div class="grid__inner grid-col--40 option-item-price">', 7376 priceHolderText, 7377 ' </div>', 7378 ' <div class="grid__inner grid-col--20 option-item-form">', 7379 ' <div class="btn-row">', 7380 ' <button aria-label="' + Resources.QUANTITY + ' ' + Resources.MINUS + '" class="btn btn--float__left btn--size__small bt
7380n--style__text btn--type__outline btn--type__outline_grey btn--action_decrement" data-id="' + id + '">', 7381 ' <span class="btn__text">-</span>', 7382 ' </button>', 7383 ' <div class="form-item form-item--number">', 7384 ' <label for="inputqty' + id + '" class="h-e">-a-</label>', 7385 ' <input id="inputqty' + id + '" value="0" class="form-item__input form-item__input--number input--qty " data-id="' + id + '" type="input" />', 7386 ' </div>', 7387 ' <button aria-label="' + Resources.QUANTITY + ' ' + Resources.PLUS + '" class="btn btn--float__left btn--size__small btn--style__text btn--type__outline btn--type__outline_grey btn--action_increment" data-id="' + id + '">', 7388 ' <span class="btn__text">+</span>', 7389 ' </button>', 7390 ' </div>', 7391 ' </div>', 7392 '</div>' 7393 ].join("\n"); 7394 7395 $('#entryTickets').append($pcdTicket); 7396 7397 self.config.tickets[id] = { 7398 id: id, 7399 description: data.description, 7400 priceText: data.priceText 7401 }; 7402 7403 //initialize events for +/- buttons//initialize events for +/- buttons 7404 self.decrementIncrementEvents(); 7405 7406 //show success message 7407 $('#ticketCoupon').find('.coupon-error').addClass('hidden'); 7408 $('#ticketCoupon').find('.coupon-applied').removeClass('hidden'); 7409 } else { 7410 //show error message 7411 $('#ticketCoupon').find('.coupon-error').removeClass('hidden'); 7412 $('#ticketCoupon').find('.coupon-applied').addClass('hidden'); 7413 } 7414 7415 }); 7416 7417 }, 7418 7419 /** 7420 * Renders Select Tickets panel 7421 */ 7422 renderSelectTickets: function () { 7423 7424 var self = this; 7425 var ticketMemberBannerEventsContainer = $('.ticket-member-banner-events-container'); 7426 self.adjustStickyButton(); 7427 7428 // dispatch CalendarOnModalAppear event 7429 // to notify the modal manager that we need assistance 7430 $(window).trigger('CalendarOnModalAppear', [self]); 7431 7432 if (!self.config.isLoggedIn && !self.config.isMemberEventsModalOpened) { 7433 self.openTicketsModal(); 7434 } 7435 7436 $(document).off('click.exhibitionLunchModal').on('click.exhibitionLunchModal', '.tickets-admission-lunch-banner .tickets-lunch-banner-menu a', function (e) { 7437 e.preventDefault(); 7438 self.openExhibitionLunchModal(); 7439 }); 7440 7441 // replace stock qty 7442 $('.ticket-purchase-limit-stock-warn').text(self.getCurrentVariantStockQty()); 7443 7444 var params = {}; 7445 params['cgid'] = this.getCGID(); 7446 params['pid'] = this.getPID(); 7447 params['dwvar_' + this.getPID() + '_TicketTimeslotVariantAttribute'] = this.getTimeSlotID(); 7448 params['format'] = 'ajax'; 7449 7450 7451 $.ajax(TateUtil.appendParamsToUrl(this.config.urls.optionsJSON, params)).done(function(data) { 7452 7453 if (data.options.length == 0 && data.expiredMembership) { 7454 self.openMembershipRenewModal(3); 7455 } 7456 7457 self.config.options = data.options; 7458 self.config.ticketPurchaseLimit = data.purchaseLimit; 7459 self.config.collectivePurchaseLimit = data.collectivePurchaseLimit; 7460 self.config.customerIsCollectiveMember = window.isCollectiveActive; 7461 self.config.customerIsMember = window.customerIsMember; 7462 self.config.onlyMemberPrivilege = data.onlyMemberPrivilege; 7463 self.config.memberPurchaseLimit = data.memberPurchaseLimit; 7464 self.config.hasExemptTicketsInBasket = data.hasExemptTicketsInBasket; 7465 self.config.collectiveOptions = data.collectiveOptions; 7466 self.config.memberOptions = data.memberOptions; 7467 self.config.memOptionsIds = []; 7468 var $html = '', 7469 $htmlAccordion = '', 7470 ticketMoreOptions = SitePreferences.TICKET_MORE_OPTIONS, 7471 collectiveOptionIDArr = Resources.COLLECTIVE_OPTION_ID.split(','), 7472 memberOptionIDArr = Resources.MEMBER_OPTION_ID.split(','), 7473 ticketSuppression = SitePreferences.TICKET_SUPPRESSION, 7474 removeMemberBannerForEvents = true; 7475 7476 /** 7477 * Determines whether a regular collective option should be displayed based on the option's ID and customer membership status. 7478 * @param {Object} opt - The option object to evaluate, expected to have an 'id' property. 7479 * @returns {boolean} - Returns true if the option should be shown; false otherwise. 7480 */ 7481 function showRegularCollectiveOption(opt) { 7482 var isCollectiveById = collectiveOptionIDArr.indexOf(opt.id) > -1; 7483 var showOption = true; 7484 7485 if (self.config.customerIsCollectiveMember && isCollectiveById) { 7486 showOption = false;
7487 } 7488 7489 return showOption; 7490 } 7491 7492 /** 7493 * Determines whether a member option should be displayed based on its ID. 7494 * Checks if the provided option's ID exists in the global memberOptionIDArr array. 7495 * If the ID is found, the option will not be shown. 7496 * 7497 * @param {Object} opt - The option object to evaluate, expected to have an 'id' property. 7498 * @returns {boolean} - Returns true if the option should be shown; false otherwise. 7499 */ 7500 function showRegularMemberOption(opt) { 7501 var isMemberById = memberOptionIDArr.indexOf(opt.id) > -1; 7502 var showOption = true; 7503 7504 if (isMemberById) { 7505 showOption = false; 7506 } 7507 7508 return showOption; 7509 } 7510 7511 $.each(self.config.options, function (index, value) { 7512 self.config.tickets[value.id] = value; 7513 var id = value.id; 7514 var qty = self.getSelectedTicketQty(id); 7515 var memOptionsClass = ''; 7516 7517 if (value.isMemOption) { 7518 memOptionsClass = ' memOption'; 7519 self.config.memOptionsIds.push(id); 7520 } 7521 7522 /** 7523 * two ticket option IDs commes from SitePreference. 7524 * the two and all tickets listed between within the accordion. 7525 * If nothing set in SitePreference all tickets are shown. 7526 */ 7527 var priceHolderText = ''; 7528 if (typeof value.promoName !== 'undefined') { 7529 priceHolderText = [ 7530 '<div class="price-holder-wrapper-with-discount">', 7531 ' <span class="price-holder">' + value.promoOptionPriceText + '</span>', 7532 ' <span class="price-holder-was">' + value.priceText + '</span>', 7533 '</div>' 7534 ].join(''); 7535 } else { 7536 priceHolderText = '<span class="price-holder">' + value.priceText + '</span>'; 7537 } 7538 7539 var ajaxSuccess = ''; 7540 if (value.description.indexOf(Resources.SPECIAL_PREFIX) !== -1) { 7541 ajaxSuccess = 'promo-ticket'; 7542 } 7543 7544 var desc = replaceBrief(value.description.replace(Resources.SPECIAL_PREFIX, '')); 7545 var optionBannerClass = value.bannerClass ? ' ' + value.bannerClass : ''; 7546 7547 if (!self.config.customerIsCollectiveMember && collectiveOptionIDArr.indexOf(id) > -1) { 7548 /** 7549 * If customer hasn't active Collective membership 7550 * don't render this product option 7551 */ 7552 } else if (ticketMoreOptions.indexOf(id) != -1 && showRegularMemberOption(value) && showRegularCollectiveOption(value)) { 7553 $htmlAccordion += [ 7554 '<div data-id="' + id + '" class="grid grid-outer option-item' + memOptionsClass + optionBannerClass + '">', 7555 ' <div class="grid__inner grid-col--40 option-item-desc">', 7556 ' <span class="desc ' + ajaxSuccess + '">' + desc + '</span>', 7557 priceHolderText, 7558 ' </div>', 7559 ' <div class="grid__inner grid-col--40 option-item-price">', 7560 priceHolderText, 7561 ' </div>', 7562 ' <div class="grid__inner grid-col--20 option-item-form">', 7563 ' <div class="btn-row">', 7564 ' <button aria-label="' + Resources.QUANTITY + ' ' + Resources.MINUS + '" class="btn btn--float__left btn--size__small bt
7564n--style__text btn--type__outline btn--type__outline_grey btn--action_decrement" data-id="' + id + '">', 7565 ' <span class="btn__text">-</span>', 7566 ' </button>', 7567 ' <div class="form-item form-item--number">', 7568 ' <label for="inputqty' + id + '" class="h-e">' + Resources.ENTER_TICKETS_QTY_FOR + ' ' + desc + '</label>', 7569 ' <input id="inputqty' + id + '" value="' + qty + '" class="form-item__input form-item__input--number input--qty ' + (qty > 0 ? 'item--qty__border--green' : '') + '" data-id="' + id + '" type="input" />', 7570 ' </div>', 7571 ' <button aria-label="' + Resources.QUANTITY + ' ' + Resources.PLUS + '" class="btn btn--float__left btn--size__small btn--style__text btn--type__outline btn--type__outline_grey btn--action_increment" data-id="' + id + '">', 7572 ' <span class="btn__text">+</span>', 7573 ' </button>', 7574 ' </div>', 7575 ' </div>', 7576 '</div>' 7577 ].join("\n"); 7578 7579 } else if (ticketSuppression.indexOf(id) != -1) { 7580 // don't print these tickets 7581 } else if (showRegularMemberOption(value) && showRegularCollectiveOption(value)) { 7582 $html += [ 7583 '<div data-id="' + id + '" class="grid grid-outer option-item' + memOptionsClass + optionBannerClass + '">', 7584 ' <div class="grid__inner grid-col--40 option-item-desc">', 7585 ' <span class="desc ' + ajaxSuccess + '">' + desc + '</span>', 7586 priceHolderText, 7587 ' </div>', 7588 ' <div class="grid__inner grid-col--40 option-item-price">', 7589 priceHolderText, 7590 ' </div>', 7591 ' <div class="grid__inner grid-col--20 option-item-form">', 7592 ' <div class="btn-row">', 7593 ' <button aria-label="' + Resources.QUANTITY + ' ' + Resources.MINUS + '" class="btn btn--float__left btn--size__small bt
7593n--style__text btn--type__outline btn--type__outline_grey btn--action_decrement" data-id="' + id + '">', 7594 ' <span class="btn__text">-</span>', 7595 ' </button>', 7596 ' <div class="form-item form-item--number">', 7597 ' <label for="inputqty' + id + '" class="h-e">' + Resources.ENTER_TICKETS_QTY_FOR + ' ' + desc + '</label>', 7598 ' <input id="inputqty' + id + '" value="' + qty + '" class="form-item__input form-item__input--number input--qty ' + (qty > 0 ? 'item--qty__border--green' : '') + '" data-id="' + id + '" type="input" />', 7599 ' </div>', 7600 ' <button aria-label="' + Resources.QUANTITY + ' ' + Resources.PLUS + '" class="btn btn--float__left btn--size__small btn--style__text btn--type__outline btn--type__outline_grey btn--action_increment" data-id="' + id + '">', 7601 ' <span class="btn__text">+</span>', 7602 ' </button>', 7603 ' </div>', 7604 ' </div>', 7605 '</div>' 7606 ].join("\n"); 7607 } 7608 }); 7609 7610 // Member Banner 7611 if (self.config.memberOptions && self.config.memberOptions.length > 0) { 7612 var memberOptions = self.config.memberOptions; 7613 7614 if (memberOptions.some(opt => opt.priceText && opt.priceText.trim() !== '')) { 7615 removeMemberBannerForEvents = false; 7616 } 7617 7618 function buildQtyControls(option) { 7619 var id = option.id; 7620 var qty = self.getSelectedTicketQty(id) 7621 var memOptionsClass = qty > 0 ? ' has-qty' : ''; 7622 7623 return '' + 7624 '<div class="grid grid-outer option-item' + memOptionsClass + '" data-id="' + id + '">' + 7625 ' <div class="btn-row">' + 7626 ' <button aria-label="' + Resources.QUANTITY + ' ' + Resources.MINUS + '" class="btn btn--float__left btn--size__small bt
7626n--style__text btn--type__outline btn--type__outline_grey btn--action_decrement" data-id="' + id + '">' + 7627 ' <span class="btn__text">-</span>' + 7628 ' </button>' + 7629 ' <div class="form-item form-item--number">' + 7630 ' <label class="h-e" for="inputqty' + id + '">' + Resources.ENTER_TICKETS_QTY_FOR + ' ' + option.description + '</label>' + 7631 ' <input id="inputqty' + id + '" value="' + qty + '" class="form-item__input form-item__input--number input--qty ' + (qty > 0 ? 'item--qty__border--green' : '') + '" data-id="' + id + '" type="input" />' + 7632 ' </div>' + 7633 ' <button aria-label="' + Resources.QUANTITY + ' ' + Resources.PLUS + '" class="btn btn--float__left btn--size__small btn--style__text btn--type__outline btn--type__outline_grey btn--action_increment" data-id="' + id + '">' + 7634 ' <span class="btn__text">+</span>' + 7635 ' </button>' + 7636 ' </div>' + 7637 '</div>'; 7638 } 7639 7640 $(document).ready(function() { 7641 var $template = $('.tate-member-banner').first(); 7642 if (!$template.length) return; 7643 7644 $('[data-mb-clone="1"]').remove(); 7645 7646 if (!self.config.customerIsMember) { 7647 var option = memberOptions[0]; 7648 var priceHolderText = '<span class="price-holder">' + option.priceText + '</span>'; 7649 $template.find($('#memberBannerTicketOption')).html(buildQtyControls(option)); 7650 7651 // Several member ticket types displayed for non-members (only one banner is displayed with Discount Tickets Available message) 7652 if (memberOptions.length > 1) { 7653 $template.addClass('multiple-member-tickets'); 7654 $template.find($('.ticket-banner-title')).append('<span class="tate-member-tickets-available">' + Resources.DISCOUNT_TICKETS_AVAILABLE + '</span>'); 7655 } else { 7656 // One member ticket type displayed for non-members (display actual ticket description as a name) 7657 $template.find('.ticket-banner-title').text(option.description); 7658 $template.find($('#memberBannerPrice')).html(priceHolderText); 7659 $template.find($('#memberBannerPriceDesktop')).html(priceHolderText); 7660 } 7661 } else { 7662 $template.hide(); 7663 for (var i = 0; i < memberOptions.length; i++) { 7664 var opt = memberOptions[i]; 7665 var priceHTML = opt.priceText ? '<span class="price-holder">' + opt.priceText + '</span>' : ''; 7666 var $clone = $template.clone(true, true); 7667 7668 $clone.attr('data-mb-clone', '1').css('display', 'flex'); 7669 $clone.find('.ticket-banner-title').first().text(opt.description); 7670 $clone.find('.member-banner-price').first().html(priceHTML); 7671 $clone.find('.member-banner-price-desktop').first().html(priceHTML); 7672 $clone.find('.member-banner-ticket-option').first().html(buildQtyControls(opt)); 7673 $clone.attr('data-option-id', opt.id); 7674 $template.after($clone); 7675 } 7676 } 7677 self.decrementIncrementEvents(); 7678 }); 7679 } 7680 7681 if ($htmlAccordion !== '') { 7682 $('#entryTicketsAccordion').html($htmlAccordion); 7683 // toggle ticket accordion for more options 7684 $('.ticket-accordion-wrapper .accordion-header').on('click', function (e) { 7685 e.preventDefault(); 7686 $('#entryTicketsAccordion').toggle(); 7687 $('.accordion-header').toggleClass('gray-background'); 7688 $('.accordion-header i.icon').toggle(); 7689 }); 7690 $('.ticket-accordion-wrapper').show(); 7691 } 7692 7693 if (removeMemberBannerForEvents && ticketMemberBannerEventsContainer.length) { 7694 ticketMemberBannerEventsContainer.html(''); 7695 } else { 7696 $('.tate-member-banner').css('display', 'flex'); 7697 } 7698 7699 $('#entryTickets').html($html); 7700 7701 // Collective Banner 7702 if (self.config.collectiveOptions && self.config.collectiveOptions.length > 0) { 7703 var collectiveOptions = self.config.collectiveOptions; 7704
7705 function buildQtyControls(option) { 7706 var optionQty = self.getSelectedTicketQty(option.id); 7707 7708 return '' + 7709 '<div class="grid grid-outer option-item no-padding" data-id="' + option.id + '">' + 7710 ' <div class="btn-row">' + 7711 ' <button aria-label="' + Resources.QUANTITY + ' ' + Resources.MINUS + '" class="btn btn--float__left btn--size__small btn--style__text btn--type__outline btn--type__outline_grey btn--action_decrement" data-id="' + option.id + '">' + 7712 ' <span class="btn__text">-</span>' + 7713 ' </button>' + 7714 ' <div class="form-item form-item--number">' + 7715 ' <label class="h-e" for="inputqty' + option.id + '">' + Resources.ENTER_TICKETS_QTY_FOR + '</label>' + 7716 ' <input id="inputqty' + option.id + '" value="' + optionQty + '" class="form-item__input form-item__input--number input--qty ' + (optionQty > 0 ? 'item--qty__border--green' : '') + '" data-id="' + option.id + '" type="input" />' + 7717 ' </div>' + 7718 ' <button aria-label="' + Resources.QUANTITY + ' ' + Resources.PLUS + '" class="btn btn--float__left btn--size__small bt
7718n--style__text btn--type__outline btn--type__outline_grey btn--action_increment" data-id="' + option.id + '">' + 7719 ' <span class="btn__text">+</span>' + 7720 ' </button>' + 7721 ' </div>' + 7722 '</div>'; 7723 } 7724 7725 $(document).ready(function () { 7726 var $template = $('.tate-collective-banner').first(); 7727 if (!$template.length) return; 7728 7729 $('[data-tc-clone="1"]').remove(); 7730 7731 if (!self.config.customerIsCollectiveMember) { 7732 var option = collectiveOptions[0]; 7733 var priceHolderText = '<span class="price-holder">' + option.priceText + '</span>'; 7734 $template.find($('#tateCollectiveTicketOption')).html(buildQtyControls(option)); 7735 7736 // Several collective ticket types displayed for non collective members (only one banner is displayed with Discount Tickets Available message) 7737 if (collectiveOptions.length > 1) { 7738 $template.addClass('multiple-collective-tickets'); 7739 $template.find($('.ticket-banner-info')).append('<span class="tate-collective-tickets-available">' + Resources.DISCOUNT_TICKETS_AVAILABLE + '</span>'); 7740 } else { 7741 // One collective ticket type displayed for non collective members (display actual ticket description as a name) 7742 $template.find('.ticket-banner-title').text(option.description); 7743 $template.find($('#tateCollectivePrice')).html(priceHolderText); 7744 $template.find($('#tateCollectivePriceDesktop')).html(priceHolderText); 7745 } 7746 } else { 7747 $template.hide(); 7748 for (var i = 0; i < collectiveOptions.length; i++) { 7749 var opt = collectiveOptions[i]; 7750 var priceHTML = '<span class="price-holder">' + opt.priceText + '</span>'; 7751 var $clone = $template.clone(true, true); 7752 7753 $clone.attr('data-tc-clone', '1'); 7754 $clone.find('.ticket-banner-title').first().text(opt.description); 7755 $clone.find('.ticket-price-holder').first().html(priceHTML); 7756 $clone.find('.ticket-price-holder-desktop').first().html(priceHTML); 7757 $clone.find('.ticket-banner-controls-holder').first().html(buildQtyControls(opt)); 7758 $clone.attr('data-option-id', opt.id).css('display', 'flex'); 7759 $template.after($clone); 7760 } 7761 } 7762 self.decrementIncrementEvents(); 7763 }); 7764 7765 var $tateCollectiveBanner = $('.tate-collective-banner').first(); 7766 7767 if (!self.config.customerIsCollectiveMember) { 7768 var $optionItems = $('#entryTickets .option-item'); 7769 if ($tateCollectiveBanner.length) { 7770 $tateCollectiveBanner.addClass('no-margin-top'); 7771 if ($optionItems.length >= 2) { 7772 $optionItems.eq(1).after($tateCollectiveBanner); 7773 } else if ($optionItems.length === 1) { 7774 $optionItems.eq(0).after($tateCollectiveBanner); 7775 } else { 7776 $('#entryTickets').append($tateCollectiveBanner); 7777 } 7778 } 7779 } 7780 7781 if ($tateCollectiveBanner.length) { 7782 $tateCollectiveBanner.css('display', 'flex'); 7783 } 7784 } 7785 7786 // add promo code input 7787 var $ticketCoupon = ''; 7788 $ticketCoupon += [ 7789 ' <div class="ticket-promo-wrapper">', 7790 ' <div class="form-item form-item--number promo-input-wrapper">', 7791 ' <label for="applycoupon" class="h-e">' + Resources.APPLY_COUPON + '</label>', 7792 ' <input id="applycoupon" class="form-item__input form-item__input--number input--promo " data-id="promo" type="input" placeholder="'+ Resources.ENTE
7792R_PROMO_CODE +'" />', 7793 ' </div>', 7794 ' <div class="btn-row coupon-button-wrapper">', 7795 ' <button class="btn btn--submit btn--action_promo">', 7796 ' <span class="btn__text">' + Resources.APPLY_COUPON + '</span>', 7797 ' </button>', 7798 ' </div>', 7799 ' <div class="coupon-applied hidden">', 7800 ' <span class="promo-applied-heading"><i class="icon--tick"></i><span>' + Resources.COUPON_APPLIED + '</span></span>', 7801 ' </div>', 7802 ' <div class="error coupon-error hidden">', 7803 ' <span class="promo-error-heading"><i class="icon--chevron-up"></i><span class="message">'+ Resources.COUPON_ERROR + '</span></span>', 7804 ' </div>', 7805 ' <div class="promo-message-wrapper">', 7806 ' <div class="promo-applied-message">' + Resources.COUPON_MESSAGE + '</div>', 7807 ' </div>', 7808 ' </div>' 7809 ].join("\n"); 7810 7811 // inject coupons 7812 $('#ticketCoupon').html($ticketCoupon); 7813 7814 // if event is only for members/collective dissable control buttons 7815 if ($('.ticket-purchase-only-members-warn').length > 0 || $('.ticket-purchase-only-collective-warn').length > 0 || $('.event-ticket-has-past-warn-wrap').length > 0) { 7816 $('#entryTickets .btn-row, #entryTicketsAccordion .btn-row').css('opacity', 0.5); 7817 $('#entryTickets .btn-row button, #entryTickets .btn-row input, #entryTicketsAccordion .btn-row button, #entryTicketsAccordion .btn-row input').attr("disabled", true); 7818 } 7819 7820 // if the user is not member disable mem options 7821 if (self.config.memberPurchaseLimit == 0) { 7822 $('.memOption .btn-row').css('opacity', 0.5); 7823 $('.memOption .btn-row button, .memOption .btn-row input').attr('disabled', true); 7824 } 7825 7826 //initialize events for +/- buttons 7827 self.decrementIncrementEvents(); 7828 7829 /** check for valid number entry and reset field value upon validation fail */ 7830 $('.option-item input.input--qty').off('keyup').on('keyup', function (e) { 7831 e.preventDefault(); 7832 7833 var qty = $(this).val(); 7834 if (['', 0].indexOf(qty) === -1) { 7835 $(this).val(isNaN(parseInt(qty)) ? '' : parseInt(qty)); 7836 } 7837 }); 7838 7839 /** check for valid number entry and sets zero upon validation fail */ 7840 $('.option-item input.input--qty').off('change').on('change', function (e) { 7841 e.preventDefault(); 7842 7843 var id = $(this).attr('data-id'), 7844 qty = $(this).val(); 7845 7846 /** validate current qty */ 7847 if (isNaN(parseInt(qty))) { 7848 // set value to zero if qty is not a number 7849 $(this).val(0); 7850 } else { 7851 // parse in int and set value to selected array 7852 self.setTicketQty(id, parseInt(qty)); 7853 } 7854 }); 7855 7856 /** ticket puchase limit close button event handler */ 7857 $('.ticket-purchase-limit-warn-wrap .closebtn').off('click').on('click', function (e) { 7858 e.preventDefault(); 7859 $('.ticket-purchase-limit-warn-wrap').hide(); 7860 }); 7861 7862 $('.collective-ticket-purchase-limit-warn-wrap .closebtn').off('click').on('click', function (e) { 7863 e.preventDefault(); 7864 $('.collective-ticket-purchase-limit-warn-wrap').hide(); 7865 }); 7866 7867 $('.mem-ticket-purchase-limit-warn-wrap .closebtn').off('click').on('click', function (e) { 7868 e.preventDefault(); 7869 $('.mem-ticket-purchase-limit-warn-wrap').hide(); 7870 }); 7871 7872 $('.event-ticket-has-past-warn-wrap .closebtn').off('click').on('click', function (e) { 7873 e.preventDefault(); 7874 $('.event-ticket-has-past-warn-wrap').hide(); 7875 }); 7876 7877 /** save selected tickets and then continue */ 7878 $('.go-save-and-continue').off('click').on('click', function (e) { 7879 e.preventDefault(); 7880 var total = self.getSelectedTicketsTotal(); 7881 if (total > 0) { 7882 self.saveToSession(function (data) { 7883 if (typeof data.status !== "undefined" && data.status === true) { 7884 // if customer has gift aid exempt tickets skip donaton step 7885 if (self.config.isTicketDonationEnabled && (self.checkForGiftAidExemptTickets() || self.config.hasExemptTicketsInBasket)) { 7886 $('.add-to-basket-without-donation').trigger('submit'); 7887 } else if (self.config.isTicketDonationEnabled) { 7888 // check donation enabled trigger next step 7889 $('.go-continue').trigger('click'); 7890 } else { 7891 // submit add to basket without donation 7892 $('.add-to-basket-without-donation').trigger('submit'); 7893 } 7894 } 7895 }); 7896 } 7897 }); 7898
7899 // Add handler for sticky save-and-continue button 7900 $('.go-save-and-continue-sticky').off('click').on('click', function (e) { 7901 e.preventDefault(); 7902 var total = self.getSelectedTicketsTotal(); 7903 if (total > 0) { 7904 self.saveToSession(function (data) { 7905 if (typeof data.status !== "undefined" && data.status === true) { 7906 if (self.config.isTicketDonationEnabled && (self.checkForGiftAidExemptTickets() || self.config.hasExemptTicketsInBasket)) { 7907 $('.add-to-basket-without-donation').trigger('submit'); 7908 } else if (self.config.isTicketDonationEnabled) { 7909 $('.go-continue').trigger('click'); 7910 } else { 7911 $('.add-to-basket-without-donation').trigger('submit'); 7912 } 7913 } 7914 }); 7915 } 7916 }); 7917 7918 //promo code submit event handler 7919 $('.btn--action_promo').off('click').on('click', function (e) { 7920 e.preventDefault(); 7921 self.promoAjaxCall(); 7922 }); 7923 7924 $('[data-id="promo"]').off('keyup').on('keyup', function (e) { 7925 e.preventDefault(); 7926 if (e.keyCode === 13) { 7927 self.promoAjaxCall(); 7928 } 7929 }); 7930 7931 // trigger accordion panel 7932 $(document).trigger('TateAccordionPanelCatch'); 7933 7934 if (self.config.times.length) { 7935 self.validate('tickets'); 7936 } else { 7937 self.setTimes(function () { 7938 self.validate('tickets'); 7939 }); 7940 } 7941 }); 7942 }, 7943 7944 /** 7945 * Check is there added gift aid exempt ticket options 7946 */ 7947 checkForGiftAidExemptTickets: function () { 7948 var self = this, hasExemptTickets = false, giftAidExemptArray = SitePreferences.TICKET_GIFT_AID_EXEMPT; 7949 7950 if (Object.keys(this.config.selected.tickets).length > 0) { 7951 $.each(this.config.selected.tickets, function (key, value) { 7952 7953 if (giftAidExemptArray.indexOf(key) > -1 && value > 0) { 7954 hasExemptTickets = true; 7955 return false; 7956 } 7957 7958 }); 7959 } 7960 return hasExemptTickets; 7961 }, 7962 7963 /** 7964 * Save to session selected ticket data 7965 * @param {Function} done callback 7966 * @param {Function} fail callback 7967 * @param {Function} always callback 7968 */ 7969 saveToSession: function (done, fail, always) { 7970 var self = this; 7971 $.ajax({ 7972 url: TateUtil.ajaxUrl(self.config.urls.saveToSession), 7973 type: 'POST', 7974 cache: false, 7975 contentType: 'application/json', 7976 dataType: "json", 7977 data: JSON.stringify($.extend(self.config.selected, { 7978 cgid: self.getCGID(), 7979 pid: self.getPID(), 7980 vid: self.getVID() 7981 })) 7982 }).done(function (data) { 7983 if (typeof done !== "undefined") { 7984 done(data); 7985 } 7986 }); 7987 }, 7988 7989 decrementTicket:function (id) { 7990 if (typeof this.config.selected.tickets[id] === "undefined") { 7991 this.config.selected.tickets[id] = 0; 7992 } 7993 7994 var $input = $('.option-item[data-id=' + id + '] input'), 7995 qty = Math.max(this.config.selected.tickets[id] - 1, 0); 7996 7997 this.config.selected.tickets[id] = qty; 7998 $input.val(qty); 7999 if (qty > 0) { 8000 $input.addClass('item--qty__border--green') 8001 } else { 8002 $input.removeClass('item--qty__border--green'); 8003 } 8004 this.validate('tickets'); 8005 this.renderSelectedTickets(); 8006 }, 8007 8008 incrementTicket: function (id) { 8009 if (typeof this.config.selected.tickets[id] === "undefined") { 8010 this.config.selected.tickets[id] = 0; 8011 } 8012 8013 var $input = $('.option-item[data-id=' + id + '] input'), 8014 qty = this.config.selected.tickets[id] + 1; 8015 8016 this.config.selected.tickets[id] = qty; 8017 $input.val(qty); 8018 if (qty > 0) { 8019 $input.addClass('item--qty__border--green') 8020 } else { 8021 $input.removeClass('item--qty__border--green'); 8022 } 8023 this.validate('tickets'); 8024 this.renderSelectedTickets(); 8025 }, 8026 8027 setTimes: function(callback) { 8028 var self = this; 8029 $.ajax({ 8030 url: TateUtil.appendParamsToUrl(self.config.urls.selectTime, { 8031 pid: self.getPID(), 8032 format: 'ajax' 8033 }) 8034 }).done(function(data) { 8035 8036 self.config.times = data.timeslots; 8037 callback(); 8038 }); 8039 }, 8040 8041 setTicketQty: function (id, qty) { 8042 if (typeof this.config.selected.tickets[id] === "undefined") { 8043 this.config.selected.tickets[id] = 0; 8044 } 8045 var $input = $('.option-item[data-id=' + id + '] input'), 8046 qty = Math.max(0, qty) 8047 this.config.selected.tickets[id] = qty; 8048 $input.val(qty); 8049 if (qty > 0) { 8050 $input.addClass('item--qty__border--green') 8051 } else { 8052 $input.removeClass('item--qty__border--green'); 8053 } 8054 this.validate('tickets'); 8055 this.renderSelectedTickets(); 8056 }, 8057 8058 /** 8059 * Renders currect selected tickers to selected tickets html 8060 */ 8061 renderSelectedTickets: function () { 8062 var self = this, 8063 $tickets = $('.card-footer-selected-tickets'), 8064 html = ""; 8065 8066 $.each(this.config.selected.tickets, function (index, value) { 8067 if (value > 0 && typeof self.config.tickets[index] !== "undefined") { 8068 var ticket = self.config.tickets[index]; 8069 html += [ 8070 '<div class="grid grid grid-outer">', 8071 ' <div class="grid__inner grid-col--60" style="padding-right: 0; padding-left: 7px;">', 8072 ' <span class="ticket-qty">' + value + ' x ' + '</span><span class="ticket-name">' + (ticket.description.replace('(', '</span><span class="h-e brief">').replace(')', '</span>').replace(Resources.SPECIAL_PREFIX, '')), 8073 ' </div>', 8074 ' <div class="grid__inner grid-col--40" style="padding-left: 4px">', 8075 ' <span>' + ticket.priceText + ' each</span>', 8076 ' </div>', 8077 '</div>' 8078 ].join("\n"); 8079 } 8080 }); 8081 8082 html += '<div class="grid grid grid-outer">'; 8083 8084 // Pluralized ticket count message
8085 var totalTickets = this.getSelectedTicketsTotal(); 8086 var pluralText = totalTickets === 1 ? 'ticket' : 'tickets'; 8087 // $('.selected-tickets-summary').text('You have selected ' + totalTickets + ' ' + pluralText + '.'); 8088 8089 // Update button text based on ticket count 8090 var btnText = ''; 8091 if (totalTickets === 0) { 8092 btnText = Resources.ADD_TICKET; 8093 } else if (totalTickets === 1) { 8094 btnText = Resources.ADD_TICKET; 8095 } else { 8096 btnText = Resources.ADD_TICKET_PLURAL; 8097 } 8098 $('.go-save-and-continue, .go-save-and-continue-sticky').find('.btn__text').text(btnText); 8099 8100 $('.display-selected-tickets', $tickets).html(html); 8101 8102 // write ticket to add to cart without donation form 8103 $('input[data-name=ticket_tickets]').val(JSON.stringify(this.config.selected.tickets)); 8104 8105 }, 8106 8107 /** 8108 * Set the selected donation value to configuration 8109 */ 8110 setDonationValue: function (donation) { 8111 var selected = $('.donation-item-selected').data('value'), 8112 $ticketGiftAidBox = $('.ticket-gift-aid-box'); 8113 8114 // clean all items 8115 $('.donation-item').removeClass('donation-item-selected'); 8116 8117 // if current selected donation is the current 8118 // selected donations, deactivate and return panel 8119 // to default state 8120 if (selected == donation) { 8121 donation = 0; 8122 } 8123 8124 // write donation to config 8125 this.config.selected.donation = donation; 8126 8127 // write donation to form 8128 $('input[data-id=donation]').val(donation); 8129 8130 // select current donation element 8131 var donationElement = $('.donation-item[data-value=' + donation + ']'); 8132 if (donationElement.length > 0) { 8133 $('.donation-item[data-value=' + donation + ']').addClass('donation-item-selected'); 8134 8135 // hide no thanks button holder 8136 $('.nothanks-wrap').hide(); 8137 8138 // show gift aid dialog 8139 $('.gift-aid-dialog-wrap').show(); 8140 } else { 8141 $('.nothanks-wrap').show(); 8142 $('.gift-aid-dialog-wrap').hide(); 8143 $('.go-save-and-continue-donation').addClass('go-save-and-continue-donation-hidden'); 8144 $('input[data-name=giftAid]').removeAttr('checked'); 8145 } 8146 8147 // scroll to ticket gift aid box 8148 if ($ticketGiftAidBox.length > 0) { 8149 $('html, body').animate({ 8150 scrollTop: $ticketGiftAidBox.offset().top - 120 8151 }, 500); 8152 } 8153 }, 8154 8155 /** 8156 * 8157 */ 8158 getDonationValue: function () { 8159 if (this.config.selected.donation !== null) { 8160 return this.config.selected.donation; 8161 } 8162 return 0; 8163 }, 8164 8165 renderDonations: function () { 8166 var self = this, 8167 $donationItemsTicket = $('.donation-items-ticket'); 8168 8169 // events 8170 $('.go-continue-with-donation').off('click').on('click', function (e) { 8171 e.preventDefault(); 8172 8173 const $this = $(this); 8174 if ($this.hasClass('disabled')) { 8175 return; 8176 } 8177 8178 $this.addClass('disabled'); 8179 $this.siblings('a').addClass('disabled'); 8180 8181 self.TatePushStatePageManager.goTO('DonationsGiftAid'); 8182 }); 8183 8184 $('.go-continue-add-to-basket-without-donation').off('click').on('click', function (e) { 8185 e.preventDefault(); 8186 8187 const $this = $(this); 8188 if ($this.hasClass('disabled')) { 8189 return; 8190 } 8191 8192 $this.addClass('disabled'); 8193 $this.siblings('a').addClass('disabled'); 8194 8195 $('.add-to-basket-without-donation').trigger('submit'); 8196 }); 8197 8198 if ($donationItemsTicket.length > 0) { 8199 8200 var previousDonation = self.getDonationValue(); 8201 if (previousDonation) { 8202 self.setDonationValue(previousDonation); 8203 } 8204 8205 $('.donation-item', $donationItemsTicket).off('click').on('click', function (e) { 8206 e.preventDefault(); 8207 var id = $(this).data('id'), 8208 value = $(this).data('value'); 8209 8210 $('.go-save-and-continue-donation .btn__text').text(Resources.ADD_TO_BASKET); 8211 8212 // set donation value 8213 self.setDonationValue(value); 8214 }); 8215 } 8216 8217 // event handler for no thanks button 8218 $('a[data-action=nothanks]').off('click').on('click', function (e) { 8219 e.preventDefault(); 8220 $('.go-save-and-continue-donation .btn__text').text(Resources.ADD_TO_BASKET_WITHOUT_DONATION); 8221 $('.go-save-and-continue-donation').removeClass('go-save-and-continue-donation-hidden'); 8222 self.setDonationValue(0); 8223 self.setGiftAid(false); 8224 }); 8225 8226 // event handler for gift aid selection 8227 $('input[data-name=giftAid]').off('change').on('change', function (e) { 8228 e.preventDefault(); 8229 self.setGiftAid($(this).val()); 8230 }); 8231 8232 // save selected tickets and then continue 8233 $('.go-save-and-continue-donation').off('click').on('click', function (e) { 8234 e.preventDefault(); 8235 8236 const $this = $(this); 8237 if ($this.hasClass('disabled')) { 8238 return; 8239 } 8240 8241 $this.addClass('disabled'); 8242 $this.siblings('a').addClass('disabled'); 8243 8244 self.saveToSession(function (data) { 8245 if (typeof data.status !== "undefined" && data.status === true) { 8246 $('.add-to-basket').trigger('submit'); 8247 } 8248 }); 8249 }); 8250 8251 $.ajax(TateUtil.appendParamsToUrl(this.config.urls.donationsJSON, { 8252 format: 'ajax' 8253 })).done(function(data) { 8254 8255 $.each(data.tickets, function (index, value) { 8256 self.config.tickets[value.id] = value; 8257 self.config.selected.tickets[value.id] = value.quantity; 8258 }); 8259 8260 self.validate('tickets'); 8261 }); 8262 }, 8263 8264 setGiftAid: function (giftAid) { 8265 var self = this; 8266 8267 self.config.selected.giftAid = giftAid; 8268 8269 self.validate('giftAid'); 8270 }, 8271 8272 /** 8273 * 8274 */ 8275 renderDonationsGiftAid: function () { 8276 var self = this; 8277 var $firstParagraphYes = $('.ticket-gift-aid-bottom-yes:not
8277(.additional)'); 8278 var $additionalParagraph = $('.ticket-gift-aid-bottom-yes.additional'); 8279 8280 // Ensure ticket definitions are loaded before rendering summary 8281 if (!self.config.tickets || Object.keys(self.config.tickets).length === 0) { 8282 // Fetch ticket definitions from donationsJSON endpoint 8283 $.ajax(TateUtil.appendParamsToUrl(self.config.urls.donationsJSON, { format: 'ajax' })) 8284 .done(function(data) { 8285 // Populate ticket definitions 8286 $.each(data.tickets, function (index, value) { 8287 self.config.tickets[value.id] = value; 8288 // Optionally update selected.tickets quantities if needed 8289 if (typeof self.config.selected.tickets[value.id] === 'undefined') { 8290 self.config.selected.tickets[value.id] = value.quantity; 8291 } 8292 }); 8293 self.renderSelectedTickets(); 8294 }); 8295 } else { 8296 self.renderSelectedTickets(); 8297 } 8298 8299 $('input[data-name=giftAid]').off('change').on('change', function (e) { 8300 e.preventDefault(); 8301 var giftAid = $(this).val(); 8302 self.setGiftAid(giftAid); 8303 8304 $('.ticket-gift-aid-bottom').hide(); 8305 8306 if (giftAid === "true") { 8307 $firstParagraphYes.show(); 8308 } else { 8309 $firstParagraphYes.hide(); 8310 $additionalParagraph.hide(); 8311 $firstParagraphYes.find('.read-more').show(); 8312 $firstParagraphYes.find('.hide').hide(); 8313 } 8314 }); 8315 8316 $firstParagraphYes.find('.read-more, .hide').on('click', function () { 8317 $firstParagraphYes.find('.read-more, .hide').toggle(); 8318 $additionalParagraph.toggle(); 8319 }); 8320 8321 $('.go-save-and-continue').off('click').on('click', function (e) { 8322 e.preventDefault(); 8323 8324 const $this = $(this); 8325 if ($this.hasClass('disabled')) { 8326 return; 8327 } 8328 8329 $this.addClass('disabled'); 8330 $this.siblings('a').addClass('disabled'); 8331 8332 $('.add-to-basket-with-donation').trigger('submit'); 8333 }); 8334 8335 $('.go-save-and-continue-sticky').off('click').on('click', function (e) { 8336 e.preventDefault(); 8337 8338 const $this = $(this); 8339 if ($this.hasClass('disabled')) { 8340 return; 8341 } 8342 8343 $this.addClass('disabled'); 8344 $this.siblings('a').addClass('disabled'); 8345 8346 $('.add-to-basket-with-donation').trigger('submit'); 8347 }); 8348 8349 self.validate('giftAid'); 8350 }, 8351 8352 openMembershipRenewModal: function(step) { 8353 8354 var self = this; 8355 8356 var modalMaxHeight = '510px'; 8357 8358 if ($(window).width() < 720) { 8359 modalMaxHeight = '580px'; 8360 } 8361 8362 $.colorbox({ 8363 href: TateUtil.appendParamsToUrl(self.config.urls.renewMembershipModal, {'step': step, 'event': self.config.cgid}), 8364 className: 'renew-membership-modal', 8365 width: '95%', 8366 height: '92%', 8367 maxWidth: '620px', 8368 maxHeight: modalMaxHeight, 8369 closeButton: true 8370 }); 8371 8372 $('body').css('overflow', 'hidden'); 8373 $('body').css('position', 'fixed'); 8374 $('body').css('width', '100%'); 8375 8376 $(document).bind('cbox_closed', function(){ 8377 $('body').css('overflow', 'auto'); 8378 $('body').css('position', 'static'); 8379 }); 8380 }, 8381 adjustStickyButton: function() { 8382 var stickyButtons = [ 8383 '.sticky-bottom-card.mobile-only', 8384 '.sticky-bottom-card-select' 8385 ]; 8386 var pageContent = $('.page__content'); 8387 var tabletBreakpoint = 840 8388 var mobileBreakpoint = 720 8389 8390 // Check if the window width is between 720px and 840px 8391 if ($(window).width() >= mobileBreakpoint && $(window).width() <= tabletBreakpoint) { 8392 var totalStickyHeight = 0; 8393 8394 stickyButtons.forEach(function(selector) { 8395 var stickyButton = $(selector); 8396 if (stickyButton.length) { 8397 var stickyHeight = stickyButton.outerHeight(true); 8398 totalStickyHeight += stickyHeight; 8399 } 8400 }); 8401 8402 if (pageContent.length) { 8403 pageContent.css('padding-bottom', totalStickyHeight + 'px'); 8404 } 8405 } else { 8406 if (pageContent.length) { 8407 pageContent.css('padding-bottom', ''); 8408 } 8409 } 8410 }, 8411 /** 8412 * Init function 8413 */ 8414 init: function (config) { 8415 var self = this; 8416 8417 // stop all execution if not on the right place 8418 if (typeof config.currentLocation === "undefined") { 8419 return; 8420 } 8421 8422 $.extend(config, { 8423 renderElement: '#calendar', 8424 isMobileScreen: function () { 8425 return $(window).width() < self.config.mobileBreakPoint ? true : false;
8426 }, 8427 isSwipe: function () { 8428 return Modernizr.touchevents ? true : false; 8429 } 8430 }); 8431 8432 // make startdate till enddate key array 8433 config.startdate = self.toDate(config.startdate); 8434 config.enddate = self.toDate(config.enddate); 8435 config.today = self.toDate(config.today); 8436 8437 config.alldays = self.createDaysFromPeriod(config.startdate, config.enddate); 8438 8439 config.productsdates = []; 8440 8441 $.extend(self, { 8442 RecordFilter: { 8443 startdate: null, 8444 enddate: null, 8445 count: 62, 8446 offset: 0 8447 8448 }, 8449 config: config, 8450 ConfigTranslator: { 8451 getDefaultValue: function (from) { 8452 return self.config.selected.date !== null && self.config.selected.date !== "null" ? self.toDate(self.config.selected.date) : null; 8453 }, 8454 getMonths: function () { 8455 return self.config.isMobileScreen() ? 1 : 2; 8456 }, 8457 /** 8458 * Get calendar min date 8459 8460 8461 8462 * @return {date} start date of calendar rendering 8463 */ 8464 getMinDate: function () { 8465 // check whatever event start date is in the future 8466 return config.startdate > self.getToday() ? config.startdate : self.getToday(); 8467 }, 8468 getMaxDate: function () { 8469 return self.config.enddate; 8470 }, 8471 /** 8472 8473 * Get all invalid days 8474 * @return {Array} all invalid days 8475 */ 8476 getInvalidDays: function () { 8477 var days = []; 8478 $.each(self.config.alldays, function(index, value) { 8479 if (self.config.productsdates.indexOf(value) === -1) { 8480 days.push(self.toDate(value)); 8481 } 8482 }); 8483 return days; 8484 }, 8485 /** 8486 * Get all market days 8487 * @return {Array} array of days objects 8488 */ 8489 getMarkedDays: function () { 8490 var days = [], 8491 today = self.getToday(); 8492 $.each(self.config.products, function (index, product) { 8493 8494 var date = self.toDate(product.date); 8495 var text = ''; 8496 8497 if (product.soldOut) { 8498 8499 text = 'SOLD OUT'; 8500 self.config.soldOutDates.push(date.getFullYear() + '-' + date.getMonth() + '-' + date.getDate()); 8501 8502 } else if (date.valueOf() == today.valueOf()) { 8503 text = 'TODAY'; 8504 } 8505 8506 days.push({ 8507 id: product.id, 8508 d: date, 8509 text: text, 8510 color: 'transparent' 8511 }); 8512 }); 8513 return days; 8514 }, 8515 getSwipe: function () { 8516 return self.config.isSwipe(); 8517 } 8518 } 8519 }); 8520 8521 self.TatePushStatePageManager = new TatePushStatePageManager(); 8522 8523 $(window).on("CalendarOnInit", function () { 8524 self.validate(); 8525 }); 8526 8527 $(window).on("CalendarOnMonthLoaded", function (event, year, month, inst) { 8528 var $headers = $('.dw-cal-btnw-m'), 8529 $wrap = $('.mbsc-w-p.dw-cal-c'); 8530 if ($headers.length=== 2) { 8531 $wrap.prepend('<div class="calendar-vertical-line" />'); 8532 } 8533 self.loadDates(year, month, inst); 8534 8535 inst.currentDate = {"year" : year, "month" : month}; 8536 }); 8537 8538 $(window).on("CalendarOnMonthChange", function (event, year, month, inst) { 8539 // Moving through the calendar, left or right, GTM data 8540 if ((inst.currentDate.year > year || inst.currentDate.year === year) && inst.currentDate.month > month) { 8541 if (dataLayer.length > 0) { 8542 dataLayer.push({ 8543 event: "dateLeft", 8544 label: "" 8545 }); 8546 } 8547 } else { 8548 if (dataLayer.length > 0) { 8549 dataLayer.push({ 8550 event: "dateRight", 8551 label: "" 8552 }); 8553 } 8554 } 8555 }); 8556 8557 $(window).on('CalendarOnEventSelect', function (e, event, d, inst) {}); 8558 8559 self.locationChange(); 8560 } 8561 }; 8562 8563 return TateCalendarManager; 8564}); 8565 8566define('components/TateStepNavigationManager',['jquery', 'components/TatePushStatePageManager', 'components/TateUtil'], function ($, TatePushStatePageManager, TateUtil) { 8567 8568 "use strict"; 8569 8570 var TateStepNavigationManager = function () { 8571 8572 var self = this; 8573 8574 $(document).ready(function () { 8575 var config = typeof TateStepNavigationManagerConfig !== "undefined" ? TateStepNavigationManagerConfig : {}; 8576 self.init(config); 8577 }); 8578 }; 8579 8580 TateStepNavigationManager.prototype = { 8581 init: function (config) { 8582 var self = this; 8583 8584 $.extend(self, { 8585 config: config 8586 }); 8587 } 8588 }; 8589 8590 return TateStepNavigationManager; 8591}); 8592 8593define('components/TateMetaManager',['jquery', 'components/TateUtil'], function ($, TateUtil) { 8594 8595 "use strict"; 8596 8597 var TateMetaManager = function () { 8598 8599 var self = this; 8600 8601 $(document).ready(function () { 8602 var config = typeof TateMetaManagerConfig !== "undefined" ? TateMetaManagerConfig : {}; 8603 self.init(config); 8604 }.bind(this)); 8605 }; 8606 8607 TateMetaManager.prototype = { 8608 /** 8609 * Set document title 8610 * @param {string} title 8611 */ 8612 setTitle: function (title) { 8613 if (title) { 8614 $(document).prop('title', title); 8615 } 8616 }, 8617 /** 8618 * Attach events handler 8619 */ 8620 events: function () { 8621 var self = this; 8622 8623 $(window).on('PushStatePageOnLoadComplete', function(e, url, title) { 8624 if (title) { 8625 self.setTitle(title); 8626 } 8627 }); 8628 }, 8629 /** 8630 * Init handler 8631 * @param {object} config 8632 */ 8633 init: function (config) { 8634 var self = this; 8635 this.config = config; 8636 this.events(); 8637 } 8638 }; 8639 8640 return TateMetaManager; 8641}); 8642 8643define('vanilla/tate-jquery',['jquery'], function ($) { 8644 var TatejQueryUILib = function () { 8645 /* 8646 * 8647 * Tate JavaScript API 8648 * 8649 */ 8650 8651 // Tate's global object 8652 var $tate = $tate || {}; 8653 8654 (function($){ 8655 8656 // 8657 // Internal variables 8658 // 8659 $tate._vars = {} 8660 8661 // allow lazy-loading of jQuery selectors 8662 // why? cos if you load main.js before the <body> then the selectors 8663 // will be empty cos the page hasn't loaded any elements yet 8664 $tate._select = function(selector) { 8665 return $(selector); 8666 } 8667 8668 // 8669 // Current page 8670 // 8671 page = { 8672 promos: function() { return $tate._select('.promo-list') }, 8673 search_box: function() { return $tate._select('input[name=q]') } 8674 }; 8675 8676 $tate.page = page; 8677 8678 // 8679 // Equal Height methods and properties 8680 // 8681 8682 // internal switch not to perform the equal height refresh "too often" (when 8683 // the user resizes their browser window) 8684 $tate._vars.doEqualHeight = []; 8685 8686 // exported method to do equal height promo items (the method below only contains 8687 // the logic) 8688 $tate.equalHeightElement = function(selector) { 8689 8690 var varname = selector ? selector : '<global>'; 8691 var elements = selector ? $(selector) : $tate.page.promos(); 8692 8693 // are we already doing equal height or have done it super very recently? 8694 if(varname in $tate._vars.doEqualHeight && 8695 !$tate._vars.doEqualHeight[varname]) 8696 return; 8697 8698 // current element or children elements? 8699 if(!elements.hasClass('promo-list--equal-height')) 8700 elements = elements.find('.promo-list--equal-height'); 8701 8702 // reset height on selected elements to let the browser render the box'es 8703 elements.each(function(){ 8704 $(this).removeAttr("data-original-height"); 8705 $(this).find('.promo-item--inner').css('height' , ''); 8706 }); 8707 8708 $tate._vars.doEqualHeight[varname] = false;
8709 $tate._applyEqualHeightElement(selector); 8710 // do not call equalHeight more than once every 100 msecs 8711 setTimeout(function() { $tate._vars.doEqualHeight[varname] = true }, 100); 8712 } 8713 8714 // internal method - actually does the equal height transformation 8715 $tate._applyEqualHeightElement = function(selector) { 8716 8717 var elements = selector ? $(selector) : $tate.page.promos(); 8718 8719 // current element or children elements? 8720 if(!elements.hasClass('promo-list--equal-height')) 8721 elements = elements.find('.promo-list--equal-height'); 8722 8723 elements.each(function(){ 8724 var t = $(this); 8725 var h = 0; 8726 8727 t.find('.promo-item--inner').each(function(){ 8728 th = $(this).outerHeight(); 8729 $(this).attr("data-original-height", th); 8730 if (th > h){ 8731 h = th; 8732 } 8733 }).css('height' , h + 'px'); // 16 is the baseline px 8734 }) 8735 } 8736 8737 // reset promo items' height, optionally starting from $(selector) 8738 $tate.resetHeight = function(selector) { 8739 8740 var elements = selector ? $(selector) : $tate.page.promos(); 8741 8742 // current element or children elements? 8743 if(!elements.hasClass('promo-list--equal-height')) 8744 elements = elements.find('.promo-list--equal-height') 8745 8746 elements.each(function(){ 8747 $(this).find('.promo-item--inner').css('height' , 'auto'); 8748 }) 8749 } 8750 8751 // show promo items after the list has been built 8752 $tate.showPromos = function() { 8753 $tate.page.promos().find('div.promo-hidden-on-load').each(function() { 8754 $(this).removeClass('promo-hidden-on-load') 8755 }); 8756 } 8757 8758 // 8759 // Hamburger menu toggling - suitable for vegetarians 8760 // 8761 8762 // current selected hamburger menu 8763 $tate._vars.hamburgerMenu = null; 8764 8765 $tate.initHamburgerMenu = function() { 8766 $('*[data-role=hamburger-switch]').each(function() { 8767 8768 var el = $(this); 8769 var switch_for = el.attr('data-switch-for'); 8770 if(!switch_for) 8771 return 8772 8773 $tate.registerHamburger(el, switch_for); 8774 }); 8775 } 8776 8777 $tate.registerHamburger = function(el, switch_for) { 8778 8779 el.click(function(event) { 8780 event.preventDefault(); 8781 8782 var current = $tate._vars.hamburgerMenu; 8783 if(current) 8784 { 8785 if(current == switch_for) 8786 { 8787 $('#'+current).slideUp(); 8788 $tate._vars.hamburgerMenu = null; 8789 return; 8790 } 8791 8792 $('#'+current).hide(); 8793 } 8794 8795 $tate._vars.hamburgerMenu = switch_for; 8796 8797 $('#'+switch_for).slideDown(); 8798 }); 8799 8800 } 8801 8802 // 8803 // Footer menu toggling (only enabled on small screens) 8804 // 8805 // similar to the above Hamburger functions 8806 // but it's simpler for the footer columns (no toggling involved) 8807 8808 $tate.initFooter = function() { 8809 8810 // Hides the footer columns when width is too little 8811 // and user can reveal them by clicking on the 8812 // column's title 8813 $("footer h2.block-title").each(function() { 8814 var title = $(this); 8815 title.on("click", function(event) { 8816 event.preventDefault(); 8817 var magic_attr = title.css('cursor'); 8818
8819 // the 'cursor' css is set via @media queries (when width is small) 8820 if(typeof(magic_attr) == 'undefined' || magic_attr == null 8821 || magic_attr != 'pointer') 8822 return; 8823 8824 title.siblings("div.content").each(function() { 8825 var content = $(this); 8826 if(content.is(":visible")) 8827 { 8828 content.slideUp(); 8829 title.removeClass("footer-block--open"); 8830 } 8831 else 8832 { 8833 content.slideDown(); 8834 title.addClass("footer-block--open"); 8835 } 8836 }); 8837 }); 8838 }); 8839 }; 8840 8841 // 8842 // Dirty Elements 8843 // 8844 // Used to flag elements (usually form elements) whose data or state 8845 // has changed (e.g. user entered their email address to a form) 8846 // and the form hasn't been submitted (let's say). 8847 // 8848 // When such scenario occurs and the users are ready to leave the 8849 // page - a warning will be displayed to the users asking to confirm 8850 // 8851 8852 $tate._vars.dirty = {}; 8853 8854 // $tate.flagAsDirty(tc_name, tc_msg); 8855 $tate.flagAsDirty = function(name, msg) { 8856 $tate._vars.dirty[name] = msg; 8857 }; 8858 8859 $tate.unflagAsDirty = function(name) { 8860 $tate._vars.dirty[name] = false; 8861 }; 8862 8863 $tate.dirtyElements = function() { 8864 8865 els = []; 8866 8867 for(d in $tate._vars.dirty) 8868 { 8869 if(!$tate._vars.dirty[d]) 8870 continue 8871 els.push({ 8872 'name': d, 8873 'msg': $tate._vars.dirty[d] 8874 }); 8875 } 8876 8877 return els; 8878 }; 8879 8880 $tate.resetDirtyElements = function() { 8881 $tate._vars.dirty = {}; 8882 } 8883 8884 $tate.isDirty = function(name) { 8885 if(!name) 8886 return false; 8887 if($tate._vars.dirty[name]) 8888 return true; 8889 return false; 8890 } 8891 8892 $(window).on("beforeunload", function(){ 8893 8894 var els = $tate.dirtyElements(); 8895 if(!els || typeof(els) == "undefined" || els.length < 1) 8896 return; 8897 8898 // only show the first 'available' error msg 8899 for(i in els) 8900 { 8901 if(typeof(els[i].msg) == "undefined") 8902 continue 8903 return els[i].msg; 8904 } 8905 }); 8906 8907 })(jQuery); 8908 8909 8910 /* 8911 * 8912 * Tate UI JS Components (note: they are jQuery plug-ins) 8913 * 8914 * method names are prefixed with 'tateUi' to avoid name clashing eg. jQueryUI provides 8915 * a .tabs() method - so ours is called .tateUiTabs() 8916 * 8917 */ 8918 8919 (function($){ 8920 8921 // Tate Modal Box Form 8922 $.fn.tateUiModalForm = function(options){ 8923 var target = $(this); 8924 8925 if (!target) return 0; // Impossible? 8926 if (!options) throw new Error("tateUiModalForm - No options specified..."); 8927 if (!options.html) throw new Error("tateUiModalForm - No HTML for lightbox specified..."); 8928 8929 var settings = $.extend({ 8930 'onSubmit': function(){ 8931 return 0; 8932 } 8933 }); 8934 8935 var form_destination = options.html.attr('action'), 8936 form_method = options.html.attr('method'), 8937 form_original_button_state = options.html.find('button[data-action=submit]').attr('class'); 8938 8939 // Button fires modal window. 8940 target.on('click', function(e){ 8941 e.preventDefault(); 8942 8943 var form_html = options.html.wrap('<div>').parent().html(); 8944 options.html.unwrap(); 8945 8946 var html = []; 8947 8948 var modal_header = '<div class="modal-box"><div class="modal-box--content">', 8949 modal_footer = '</div></div>'; 8950 8951 html.push(modal_header); 8952 html.push(form_html); 8953 html.push(modal_footer); 8954 8955 $.colorbox({ 8956 html: html.join("\n"),
8957 closeButton: false, 8958 onClosed: function() { $.colorbox.remove(); } 8959 }); 8960 8961 $('.modal-box--content form').tateUiForm({}); 8962 }); 8963 8964 // Submit button inside form 8965 $(document).on('submit', options.html, function(e){ 8966 e.preventDefault(); 8967 8968 // Javascript scope ¯\(°_o)/¯ 8969 var data = {}, 8970 $submitBtn = $('.modal-box--content form button[data-action=submit]'); 8971 8972 $submitBtn.tateUiIcon('fa-spinner fa-spin'); 8973 8974 // Set up data for ajax 8975 $('.modal-box--content form input').each(function(){ 8976 var $me = $(this); 8977 data[$me.attr('name')] = $me.val(); 8978 }); 8979 8980 // Fire off ajax to end point specified in form 8981 $.ajax({ 8982 data: data, 8983 url: form_destination, 8984 method: form_method, 8985 success: function(data, textStatus, xhr){ 8986 if (xhr.status >= 200 && xhr.status <= 300){ 8987 // Perfec' 8988 $submitBtn.tateUiIcon('fa-check'); 8989 if (typeof options.onSuccess == "function") options.onSuccess(data, xhr); 8990 setTimeout(function(){ 8991 $.colorbox.remove(); 8992 }, 250); 8993 } else { 8994 // Oops? 8995 $submitBtn.tateUiIcon('fa-times'); 8996 if (typeof options.onError == "function") options.onError(data, xhr); 8997 } 8998 }, 8999 error: function(data, textStatus, xhr){ 9000 // Definite oops. 9001 $submitBtn.tateUiIcon('fa-times'); 9002 9003 $('.modal-box--content').html(""); 9004 $('.modal-box--content').html('<div class="patternui--typography-set-inner"><p class="standfirst">Oops...</p> <p>We seem to be having some trouble on our end. Please try again later.</p></div><div class="btn-row"><div class="btn-group btn-group--right"><a href="#" id="closeModelBtn" class="btn btn--medium btn--icon-r btn--shamrock"><i class="icon fa fa-close"></i><span class="btn-text">Okay</span></a></div></div>'); 9005 9006 // Set bind for close model button 9007 $(document).on('click', '#closeModelBtn', function(e){ 9008 e.preventDefault(); 9009 $.colorbox.remove(); 9010 }); 9011 9012 if (typeof options.onError == "function") options.onError(data, xhr); 9013 } 9014 }); 9015 }); 9016 }; 9017 9018 // Tate Confirm Box Form 9019 $.fn.tateUiConfirm = function(options){ 9020 var target = $(this); 9021 9022 if(!target) 9023 return; 9024 9025 var settings = $.extend({ 9026 'title': 'Confirm', 9027 'message': '', 9028 'onConfirm': function() {} 9029 }, options); 9030 9031 var message = settings.message; 9032 var title = settings.title; 9033 9034 target.on('click', function(event) { 9035 event.preventDefault(); 9036 9037 var confirm_title = '<div class="modal-box--title">' + title + '</div>'; 9038 9039 var confirm_content = '<div class="modal-box--content">' + message + '</div>'; 9040 9041 var confirm_buttons = '<div class="btn-row">' + 9042 '<div class="btn-group btn-group--center">' + 9043 '<button class="btn btn--small btn--text-link" data-role="button" data-value="0">' + 9044 '<span class="btn-text">Cancel</span>' + 9045 '</button>' + 9046 '<button class="btn btn--small btn--vermilion" data-role="button" data-value="1">' + 9047 '<span class="btn-text">Confirm</span>' + 9048 '</button>' + 9049 '</div>' + 9050 '</div>'; 9051 9052 var confirm_box = $('<div class="confirm modal-box">' + confirm_title + confirm_content + confirm_buttons + '</div>'); 9053 $('body').append(confirm_box); 9054 $('.confirm [data-role=button]').on('click', function(event){ 9055 9056 event.preventDefault(); 9057 9058 $.colorbox.remove(); 9059 $('.confirm').remove(); 9060 if ($(this).attr('data-value') == "1") { 9061 settings.onConfirm(); 9062 } 9063 return false;
9064 }); 9065 9066 $.colorbox({ 9067 inline:true, 9068 href:".confirm", 9069 closeButton: false, 9070 onClosed: function() { $.colorbox.remove(); $('.confirm').remove(); } 9071 }); 9072 9073 return false; 9074 }); 9075 }; 9076 9077 // Tate focus search box <input> 9078 $.fn.tateUiFocusTextToEnd = function() { 9079 this.focus(); 9080 var $thisVal = this.val(); 9081 this.val('').val($thisVal); 9082 return this; 9083 }; 9084 9085 // when called with a <button>, it replaces the button's icon style 9086 // eg. $(mybutton).icon('fa-trash-o') 9087 // $(mybutton).icon('fa-spinner fa-spin') 9088 $.fn.tateUiIcon = function(classes) { 9089 if(!classes) classes = ''; 9090 var button = $(this); 9091 var icon = button.find('i.icon'); 9092 if(icon.length == 0) { 9093 // add the icon if it doesn't exist 9094 button 9095 .find('span.btn-text') 9096 .before('<i class="icon fa '+classes+'"></i>'); 9097 } 9098 else { 9099 icon 9100 .removeClass() 9101 .addClass('icon fa ' + classes); 9102 } 9103 return this; 9104 }; 9105 9106 // Tate Tabs 9107 // params: 9108 // 'onTabChange': function(tabid) { your_code_here; } (optional) 9109 $.fn.tateUiTabs = function(options) { 9110 9111 var settings = $.extend({}, options); 9112 9113 var ti = $(this); 9114 9115 ti.find('.tabbed--content-item').addClass('tabbed--content--hidden'); 9116 ti.find('.tabbed--content_title').hide(); 9117 9118 ti.find('.tabbed-menu--item').each(function(){ 9119 9120 var t = $(this); 9121 var a = t.find('a'); 9122 9123 if(t.hasClass('active')){ 9124 var i = t.index(); 9125 var tc = t.closest('.tabbed-container').find('.tabbed--content-item'); 9126 tc.eq(i).removeClass('tabbed--content--hidden'); 9127 } 9128 9129 a.on('click' , function(event, i){ 9130 event.preventDefault(); 9131 ti.find('.tabbed-menu--item').removeClass('active'); 9132 9133 var link = $(this); 9134 link.parent().addClass('active'); 9135 9136 var i = link.parent().index(); 9137 9138 ti.find('.tabbed--content-item').addClass('tabbed--content--hidden'); 9139 ti.find('.tabbed--content-item').eq(i).removeClass('tabbed--content--hidden'); 9140 9141 if(settings.onTabChange) 9142 settings.onTabChange(i) 9143 }); 9144 }); 9145 } 9146 9147 // 9148 // Tate Infinite Scroll 9149 // 9150 9151 $.fn.tateUiInfiniteScroll = function(params) { 9152 9153 var pages = params.pages; 9154 var url = params.url; 9155 9156 if(typeof(pages) == "undefined" || typeof(url) == "undefined") 9157 { 9158 return; 9159 } 9160 9161 // which element triggers fetching the next page 9162 // default to "window" ie when the user scrolls 9163 // all the way down 9164 if(typeof(params.trigger) != "undefined") 9165 trigger = params.trigger 9166 else 9167 trigger = false 9168 9169 if(typeof(params.html_label) != "undefined") 9170 html_label = params.html_label 9171 else 9172 html_label = "<p>Loading...</p>" 9173 9174 var name; 9175 if(typeof(params.name) != "undefined") 9176 name = params.name.replace(/ /g, "_") 9177 else 9178 name = params.url.replace(/\//g, "_") 9179 9180 if(typeof(params.back_to_top) != "undefined" && params.back_to_top) 9181 var back_to_top = '<div id="'+name+'_b2t" class="link--back-to-top" style="display:none;"><a href="#page" class="btn btn--small btn--icon-r btn--square"><i class="icon fa fa-angle-double-up"></i><span class="btn-text">Back to top</span></a>'; 9182 $("footer.canvas--section").prepend(back_to_top); 9183 9184 var marker_id = name + "_marker"; 9185 var b2t = $("#"+name+"_b2t"); 9186 9187 // extra url (GET) parameters 9188 var args = params.args; 9189 if(typeof(args) == "undefined") 9190 args = {} 9191 9192 var current_page = 1; 9193 var initial_offset = 0; 9194 if(typeof(params.current_page) != "undefined") 9195 current_page = params.current_page; 9196 if(current_page == 0) 9197 initial_offset = 1 9198 9199 if( typeof($tate._vars.infinite_scroll) == "undefined" ) 9200 $tate._vars.infinite_scroll = {} 9201 9202 $tate._vars.infinite_scroll[name] = { 9203 'pages': pages, 9204 'current_page': current_page, 9205 'pending': false, 9206 'b2t': "hidden" // any animation in-progress? 9207 // one 'hidden', 'animating', 'shown' 9208 }; 9209 9210 var container = $(this); 9211 9212 // the marker <div> ie the <div> that will receive the next page of data 9213 var marker = "<div id='"+marker_id+"' style='display:none'>"+html_label+"</div>"; 9214 container.append(marker); 9215 9216 $(window).scroll(function() 9217 { 9218 if(trigger) 9219 relative_pos = $("#"+trigger).offset().top 9220 else 9221 relative_pos = $(document).height() 9222 9223 // show/hide the "back to top" button depending on the scrolling position 9224 if($(window).scrollTop() < 500) 9225 { 9226 if($tate._vars.infinite_scroll[name]['b2t'] != 'hidden') { 9227 $tate._vars.infinite_scroll[name]['b2t'] = 'animating'; 9228 b2t.animate( 9229 { marginTop:'-60px' }, 9230 250, 9231 function() { 9232 b2t.hide(); 9233 $tate._vars.infinite_scroll[name]['b2t'] = 'hidden'; 9234 } 9235 ); 9236 } 9237 } 9238 else 9239 { 9240 if($tate._vars.infinite_scroll[name]['b2t'] != 'shown') { 9241 9242 $tate._vars.infinite_scroll[name]['b2t'] = 'animating'; 9243 b2t.show().animate( 9244 { marginTop:'0px' }, 9245 250, 9246 function() { 9247 $tate._vars.infinite_scroll[name]['b2t'] = 'shown'; 9248 } 9249 ); 9250 } 9251 } 9252 9253 if($(window).scrollTop() >= relative_pos - $(window).height()) 9254 { 9255 if($('div#'+marker_id).length == 0) 9256 return; 9257 9258 if($tate._vars.infinite_scroll[name]['pages'] <= 9259 $tate._vars.infinite_scroll[name]['current_page'] + initial_offset) 9260 // we're done here 9261 return; 9262 9263 $('div#'+marker_id).show(); 9264 var next_page = $tate._vars.infinite_scroll[name]['current_page'] + 1; 9265 9266 // don't run the same ajax query 9267 if($tate._vars.infinite_scroll[name]['pending']) 9268 return; 9269 $tate._vars.infinite_scroll[name]['pending'] = true; 9270 9271 new_data_url = url + "?"; 9272 var url_args = []; 9273 for(var k in args) 9274 if(args[k]) 9275 url_args.push(k + "=" + args[k]); 9276 9277 url_args.push("page=" + next_page); 9278 new_data_url += url_args.join("&"); 9279 9280 $.ajax({ 9281 url: new_data_url, 9282 success: function(html) 9283 { 9284 $('div#'+marker_id).remove(); 9285 if(html) 9286 { 9287 container.append(html); 9288 container.append(marker); 9289 9290 $(document).trigger("tate-scroll-page-loaded", [name, next_page, pages]); 9291 } 9292 9293 $tate._vars.infinite_scroll[name]['pending'] = false;
9294 $tate._vars.infinite_scroll[name]['current_page']++; 9295 9296 if($tate._vars.infinite_scroll[name]['b2t'] != 'hidden') 9297 return; 9298 9299 $tate._vars.infinite_scroll[name]['b2t'] = 'animating'; 9300 b2t.css('marginTop', '-60px').show().animate( 9301 { marginTop:'0px' }, 9302 250, 9303 function() { 9304 $tate._vars.infinite_scroll[name]['b2t'] = 'shown'; 9305 } 9306 ); 9307 } 9308 }); 9309 } 9310 }); 9311 9312 } 9313 9314 9315 // 9316 // Tate Forms 9317 // 9318 9319 // reset all error messages 9320 $.fn.tateUiResetForm = function() { 9321 $(this) 9322 .find('span.form-input--error-text') 9323 .closest('div.form-field').removeClass('form-field--error'); 9324 } 9325 9326 // turn the selected <form> into a managed form, with validation 9327 // rules and UI-lib custom error classes 9328 // relies on jquery-validate - http://jqueryvalidation.org/ 9329 $.fn.tateUiForm = function(options) { 9330 9331 var form = $(this); 9332 9333 // auto-add the required asterisk for required fields 9334 form.find('.form-field--required input').each(function() { 9335 var input_id = $(this).attr('id'); 9336 if(input_id) { 9337 // front-end 9338 form.find('label[for='+input_id+']').append('<abbr title="Required">*</abbr>'); 9339 // also need that for jquery-validate 9340 $(this).attr('required', 'required'); 9341 } 9342 }); 9343 9344 // enable the custom submit button, if any 9345 form.find('button[data-action=submit]').on('click', function(event) { 9346 event.preventDefault(); 9347 form.submit(); 9348 }); 9349 9350 // built-in validation methods 9351 // cf. http://jqueryvalidation.org/ 9352 rules = {}; 9353 rules_len = 0; 9354 valid_rules = { 9355 'email': true, 9356 'url': true 9357 }; 9358 9359 // fixes attributes - UI lib conventions vs. jQuery validation conventions 9360 form.find('.form-field--input').each(function() { 9361 var div = $(this); 9362 if(div.hasClass('form-field--valid-url')) 9363 { 9364 div.find('input').attr('data-validate', 'url'); 9365 } 9366 else if(div.hasClass('form-field--valid-email')) 9367 { 9368 div.find('input').attr('data-validate', 'email'); 9369 } 9370 }); 9371 9372 form.find('input[data-validate]').each(function() { 9373 input = $(this); 9374 name = input.attr('name'); 9375 validator = input.attr('data-validate'); 9376 if(name && validator && valid_rules[validator]) 9377 { 9378 rules[name] = {}; 9379 rules[name][validator] = true; 9380 rules_len++; 9381 } 9382 }); 9383 9384 validateOptions = { 9385 'showErrors': function(errorMap, errorList) { 9386 9387 // reset state 9388 form.tateUiResetForm(); 9389 9390 // fixes error message 'top' property 9391 for(err in errorMap) { 9392 if(err){ 9393 var err_el = form.find('span[data-error-for='+err+']'); 9394 if(err_el) { 9395 var th = err_el.siblings('label').outerHeight(); 9396 if(th) 9397 err_el.css('top', th + 'px') 9398 err_el 9399 .closest('div.form-field').addClass('form-field--error'); 9400 } 9401 break; 9402 } 9403 } 9404 }, 9405 'onfocusout': function(element, event) { 9406 // reset state 9407 form.tateUiResetForm(); 9408 } 9409 } 9410 9411 if(rules && rules_len > 0) 9412 validateOptions.rules = rules; 9413 9414 if(options != null && options.submitHandler) 9415 validateOptions.submitHandler = options.submitHandler; 9416 9417 // $.validate() is provided by the jquery-validate plug-in 9418 form.validate(validateOptions); 9419 9420 // track changes across the form 9421 // and message users when they're leaving the 9422 // page with unsaved changes 9423 9424 if(typeof(options.trackChanges) == "undefined") 9425 return; 9426 9427 tc = options.trackChanges; 9428 9429 // optional option 9430 tc_name = tc.name; 9431 if(typeof(tc_name) == "undefined") 9432 tc_name = "trackelt_" + new Date().valueOf() + "_" + Math.floor((Math.random() * 10000)); 9433 9434 tc_msg = tc.msg; 9435 if(typeof(tc_msg) == "undefined") 9436 { 9437 return; 9438 } 9439 9440 // tags to track (other tags are not supported: https://api.jquery.com/change/) 9441 tags = ['input', 'select', 'textarea']; 9442 9443 for(i in tags) 9444 form.find(tags[i]).change(function() {
9445 $tate.flagAsDirty(tc_name, tc_msg); 9446 }); 9447 9448 form.submit(function() { 9449 $tate.unflagAsDirty(tc_name); 9450 }); 9451 9452 } 9453 9454 }(jQuery)); 9455 9456 9457 // READ MORE FUNCTION 9458 9459 $(document).ready(function(){ 9460 var rmCount = 0; 9461 9462 $('.read-more--hidden').each(function(){ 9463 $('.read-more--active p').css('margin-bottom' , '0'); 9464 var t = $(this); 9465 $(this).after('<span class="read-more--handle rm--' + rmCount + '">Read more</span>'); 9466 $(this).hide(); 9467 $('.rm--'+ rmCount).on('click' , function(){ 9468 if ($(this).hasClass('rm--open')) { 9469 $(this).text('Read more').removeClass('rm--open'); 9470 t.slideUp(); 9471 } 9472 else { 9473 t.slideDown(); 9474 $(this).text('Read less').addClass('rm--open'); 9475 } 9476 9477 }) 9478 rmCount++; 9479 9480 }); 9481 9482 $('.jump-menu__select-list').on('change', function(){ 9483 var selection = $(this).find('option:selected'); 9484 if (selection && selection.attr('value')) { 9485 window.location = selection.attr('value'); 9486 } 9487 }); 9488 9489 // Make the social share functions open in a new window 9490 $('.splash-header__share .list__item--social a').on('click', function(e){ 9491 var href = $(this).attr('href'); 9492 if (href.substring(0, 4) != 'http') 9493 return; // Don't interfere with default behaviour of the 'share by email' link 9494 e.preventDefault(); 9495 window.open(href, 'targetWindow', "toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width="
9495+ 500 + ",height=" + 500); 9496 return false; 9497 }); 9498 9499 }); 9500 }; 9501 9502 return new TatejQueryUILib(); 9503}); 9504/* 9505* Our library is built here. Require all components and insert them into one object. 9506* The object is exported through AMD and exposed globally in the build process. 9507* 9508* 9509* @notice IT IS VERY IMPORTANT TO MAINTAIN THE ORDER OF THE IMPORTS AND FUNCTION PARAMETERS 9510* FAILING THAT WILL IMPORT THE WRONG CLASS UNDER THE WRONG OBJECT. 9511*/ 9512 9513define('TateUI',[ 9514 'components/TatePolyfill', 9515 'components/TateWindow', 9516 'components/TateStorage', 9517 'components/TateNotification', 9518 'components/TateGOTO', 9519 'components/TateReady', 9520 'components/TateBTT', 9521 'components/TateLazyLoad', 9522 'components/TateOpenTimes', 9523 'components/TateLogin', 9524 'components/TateNav', 9525 'components/TateBreadcrumbs', 9526 'components/TateShareIcons', 9527 'components/TateSplash', 9528 'components/TateAdvancedFilters', 9529 'components/TateTabs', 9530 'components/TateReviews', 9531 'components/TateJPlayer', 9532 'components/TateInfiniteScroll', 9533 'components/BannerSlider', 9534 9535 'components/TateModalManager', 9536 'components/TateAccordionManager', 9537 'components/TateAccordionPanelManager', 9538 'components/TatePushStatePageManager', 9539 'components/TateCalendarManager', 9540 'components/TateUtil', 9541 'components/TateStepNavigationManager', 9542 'components/TateMetaManager', 9543 9544 'vanilla/tate-jquery' 9545], function ( 9546 TatePolyfill, 9547 TateWindow, 9548 TateStorage, 9549 TateNotification, 9550 TateGOTO, 9551 TateReady, 9552 TateBTT, 9553 TateLazyLoad, 9554 TateOpenTimes, 9555 TateLogin, 9556 TateNav, 9557 TateBreadcrumbs, 9558 TateShareIcons, 9559 TateSplash, 9560 TateAdvancedFilters, 9561 TateTabs, 9562 TateReviews, 9563 TateJPlayer, 9564 TateInfiniteScroll, 9565 BannerSlider, 9566 9567 TateModalManager, 9568 TateAccordionManager, 9569 TateAccordionPanelManager, 9570 TatePushStatePageManager, 9571 TateCalendarManager, 9572 TateUtil, 9573 TateStepNavigationManager, 9574 TateMetaManager, 9575 9576 TateJQUERY 9577) { 9578 9579var tate_ready = new TateReady(), 9580 tate_polyfill = new TatePolyfill(), 9581 tate_back_to_top = new TateBTT(), 9582 tate_lazy_load = new TateLazyLoad(), 9583 tate_open_times = new TateOpenTimes(), 9584 tate_login = new TateLogin(), 9585 tate_nav = new TateNav(), 9586 tate_bc = new TateBreadcrumbs(), 9587 tate_share_icons = new TateShareIcons(), 9588 tate_splash = new TateSplash(), 9589 tate_advanced_filters = new TateAdvancedFilters(), 9590 tate_tabs = new TateTabs(), 9591 tate_reviews = new TateReviews(), 9592 tate_jplayer = new TateJPlayer(), 9593 tate_infinite_scroll = new TateInfiniteScroll(), 9594 tate_banner_slider = new BannerSlider(), 9595 9596 tate_modal_manager = new TateModalManager(), 9597 tate_accordion_manager = new TateAccordionManager(), 9598 tate_accordion_panel_manager = new TateAccordionPanelManager(), 9599 tate_push_state_page_manager = new TatePushStatePageManager(), 9600 tate_calendar_manager = new TateCalendarManager(), 9601 9602 tate_step_navigation_manager = new TateStepNavigationManager(), 9603 tate_meta_manager = new TateMetaManager(); 9604 9605return { 9606 get: function (what) { 9607 return what; 9608 }, 9609 "Polyfill": TatePolyfill, 9610 "Window": TateWindow, 9611 "Storage": TateStorage, 9612 "Notification": TateNotification, 9613 "GOTO": TateGOTO, 9614 "Ready": TateReady, 9615 "BTT": TateBTT, 9616 "LazyLoad": TateLazyLoad, 9617 "OpenTimes": TateOpenTimes, 9618 "Login": TateLogin, 9619 "Nav": TateNav, 9620 "Breadcrumbs": TateBreadcrumbs, 9621 "ShareIcons": TateShareIcons, 9622 "Splash": TateSplash, 9623 "AdvancedFilters": TateAdvancedFilters, 9624 "Tabs": TateTabs, 9625 "Reviews": TateReviews, 9626 "JPlayer": TateJPlayer, 9627 "InfiniteScroll": TateInfiniteScroll, 9628 "BannerSlider": BannerSlider, 9629 "TateModalManager": TateModalManager, 9630 "TateAccordionManager": TateAccordionManager, 9631 "TateAccordionPanelManager": TateAccordionPanelManager, 9632 "TatePushStatePageManager": TatePushStatePageManager, 9633 "TateCalendarManager": TateCalendarManager, 9634 "TateUtil": TateUtil, 9635 "TateStepNavigationManager": TateStepNavigationManager 9636}; 9637}); 9638 9639 return require('TateUI'); 9640}));
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.