1(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ 2(function (global){(function (){ 3"use strict"; 4 5function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 6/** 7* Ajax Autocomplete for jQuery, version 1.4.11 8* (c) 2017 Tomas Kirda 9* 10* Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license. 11* For details, see the web site: https://github.com/devbridge/jQuery-Autocomplete 12*/ 13 14/*jslint browser: true, white: true, single: true, this: true, multivar: true */ 15/*global define, window, document, jQuery, exports, require */ 16 17// Expose plugin as an AMD module if AMD loader is present: 18(function (factory) { 19 "use strict"; 20 21 if (typeof define === 'function' && define.amd) { 22 // AMD. Register as an anonymous module. 23 define(['jquery'], factory); 24 } else if ((typeof exports === "undefined" ? "undefined" : _typeof(exports)) === 'object' && typeof require === 'function') { 25 // Browserify 26 factory((typeof window !== "undefined" ? window['jQuery'] : typeof global !== "undefined" ? global['jQuery'] : null)); 27 } else { 28 // Browser globals 29 factory(jQuery); 30 } 31})(function ($) { 32 'use strict'; 33 34 var utils = function () { 35 return { 36 escapeRegExChars: function escapeRegExChars(value) { 37 return value.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&"); 38 }, 39 createNode: function createNode(containerClass) { 40 var div = document.createElement('div'); 41 div.className = containerClass; 42 div.style.position = 'absolute'; 43 div.style.display = 'none'; 44 return div; 45 } 46 }; 47 }(), 48 keys = { 49 ESC: 27, 50 TAB: 9, 51 RETURN: 13, 52 LEFT: 37, 53 UP: 38, 54 RIGHT: 39, 55 DOWN: 40 56 }, 57 noop = $.noop; 58 function Autocomplete(el, options) { 59 var that = this; 60 61 // Shared variables: 62 that.element = el; 63 that.el = $(el); 64 that.suggestions = []; 65 that.badQueries = []; 66 that.selectedIndex = -1; 67 that.currentValue = that.element.value; 68 that.timeoutId = null; 69 that.cachedResponse = {}; 70 that.onChangeTimeout = null; 71 that.onChange = null; 72 that.isLocal = false;
73 that.suggestionsContainer = null; 74 that.noSuggestionsContainer = null; 75 that.options = $.extend(true, {}, Autocomplete.defaults, options); 76 that.classes = { 77 selected: 'autocomplete-selected', 78 suggestion: 'autocomplete-suggestion' 79 }; 80 that.hint = null; 81 that.hintValue = ''; 82 that.selection = null; 83 84 // Initialize and set options: 85 that.initialize(); 86 that.setOptions(options); 87 } 88 Autocomplete.utils = utils; 89 $.Autocomplete = Autocomplete; 90 Autocomplete.defaults = { 91 ajaxSettings: {}, 92 autoSelectFirst: false, 93 appendTo: 'body', 94 serviceUrl: null, 95 lookup: null, 96 onSelect: null, 97 width: 'auto', 98 minChars: 1, 99 maxHeight: 300, 100 deferRequestBy: 0, 101 params: {}, 102 formatResult: _formatResult, 103 formatGroup: _formatGroup, 104 delimiter: null, 105 zIndex: 9999, 106 type: 'GET', 107 noCache: false, 108 onSearchStart: noop, 109 onSearchComplete: noop, 110 onSearchError: noop, 111 preserveInput: false, 112 containerClass: 'autocomplete-suggestions', 113 tabDisabled: false, 114 dataType: 'text', 115 currentRequest: null, 116 triggerSelectOnValidInput: true, 117 preventBadQueries: true, 118 lookupFilter: _lookupFilter, 119 paramName: 'query', 120 transformResult: _transformResult, 121 showNoSuggestionNotice: false, 122 noSuggestionNotice: 'No results', 123 orientation: 'bottom', 124 forceFixPosition: false 125 }; 126 function _lookupFilter(suggestion, originalQuery, queryLowerCase) { 127 return suggestion.value.toLowerCase().indexOf(queryLowerCase) !== -1; 128 } 129 ; 130 function _transformResult(response) { 131 return typeof response === 'string' ? $.parseJSON(response) : response; 132 } 133 ; 134 function _formatResult(suggestion, currentValue) { 135 // Do not replace anything if the current value is empty 136 if (!currentValue) { 137 return suggestion.value; 138 } 139 var pattern = '(' + utils.escapeRegExChars(currentValue) + ')'; 140 return suggestion.value.replace(new RegExp(pattern, 'gi'), '<strong>$1<\/strong>').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/<(\/?strong)>/g, '<$1>'); 141 } 142 ; 143 function _formatGroup(suggestion, category) { 144 return '<div class="autocomplete-group">' + category + '</div>'; 145 } 146 ; 147 Autocomplete.prototype = { 148 initialize: function initialize() { 149 var that = this, 150 suggestionSelector = '.' + that.classes.suggestion, 151 selected = that.classes.selected, 152 options = that.options, 153 container; 154 that.element.setAttribute('autocomplete', 'off'); 155 156 // html() deals with many types: htmlString or Element or Array or jQuery
157 that.noSuggestionsContainer = $('<div class="autocomplete-no-suggestion"></div>').html(this.options.noSuggestionNotice).get(0); 158 that.suggestionsContainer = Autocomplete.utils.createNode(options.containerClass); 159 container = $(that.suggestionsContainer); 160 container.appendTo(options.appendTo || 'body'); 161 162 // Only set width if it was provided: 163 if (options.width !== 'auto') { 164 container.css('width', options.width); 165 } 166 167 // Listen for mouse over event on suggestions list: 168 container.on('mouseover.autocomplete', suggestionSelector, function () { 169 that.activate($(this).data('index')); 170 }); 171 172 // Deselect active element when mouse leaves suggestions container: 173 container.on('mouseout.autocomplete', function () { 174 that.selectedIndex = -1; 175 container.children('.' + selected).removeClass(selected); 176 }); 177 178 // Listen for click event on suggestions list: 179 container.on('click.autocomplete', suggestionSelector, function () { 180 that.select($(this).data('index')); 181 }); 182 container.on('click.autocomplete', function () { 183 clearTimeout(that.blurTimeoutId); 184 }); 185 that.fixPositionCapture = function () { 186 if (that.visible) { 187 that.fixPosition(); 188 } 189 }; 190 $(window).on('resize.autocomplete', that.fixPositionCapture); 191 that.el.on('keydown.autocomplete', function (e) { 192 that.onKeyPress(e); 193 }); 194 that.el.on('keyup.autocomplete', function (e) { 195 that.onKeyUp(e); 196 }); 197 that.el.on('blur.autocomplete', function () { 198 that.onBlur(); 199 }); 200 that.el.on('focus.autocomplete', function () { 201 that.onFocus(); 202 }); 203 that.el.on('change.autocomplete', function (e) { 204 that.onKeyUp(e); 205 }); 206 that.el.on('input.autocomplete', function (e) { 207 that.onKeyUp(e); 208 }); 209 }, 210 onFocus: function onFocus() { 211 var that = this; 212 if (that.disabled) { 213 return; 214 } 215 that.fixPosition(); 216 if (that.el.val().length >= that.options.minChars) { 217 that.onValueChange(); 218 } 219 }, 220 onBlur: function onBlur() { 221 var that = this, 222 options = that.options, 223 value = that.el.val(), 224 query = that.getQuery(value); 225 226 // If user clicked on a suggestion, hide() will 227 // be canceled, otherwise close suggestions 228 that.blurTimeoutId = setTimeout(function () { 229 that.hide(); 230 if (that.selection && that.currentValue !== query) { 231 (options.onInvalidateSelection || $.noop).call(that.element); 232 } 233 }, 200); 234 }, 235 abortAjax: function abortAjax() { 236 var that = this; 237 if (that.currentRequest) { 238 that.currentRequest.abort(); 239 that.currentRequest = null; 240 } 241 }, 242 setOptions: function setOptions(suppliedOptions) { 243 var that = this, 244 options = $.extend({}, that.options, suppliedOptions); 245 that.isLocal = Array.isArray(options.lookup); 246 if (that.isLocal) { 247 options.lookup = that.verifySuggestionsFormat(options.lookup); 248 } 249 options.orientation = that.validateOrientation(options.orientation, 'bottom'); 250 251 // Adjust height, width and z-index: 252 $(that.suggestionsContainer).css({ 253 'max-height': options.maxHeight + 'px', 254 'width': options.width + 'px', 255 'z-index': options.zIndex 256 }); 257 this.options = options; 258 }, 259 clearCache: function clearCache() { 260 this.cachedResponse = {}; 261 this.badQueries = []; 262 }, 263 clear: function clear() { 264 this.clearCache(); 265 this.currentValue = ''; 266 this.suggestions = []; 267 }, 268 disable: function disable() { 269 var that = this; 270 that.disabled = true; 271 clearTimeout(that.onChangeTimeout); 272 that.abortAjax(); 273 }, 274 enable: function enable() { 275 this.disabled = false; 276 }, 277 fixPosition: function fixPosition() { 278 // Use only when container has already its content 279 280 var that = this, 281 $container = $(that.suggestionsContainer), 282 containerParent = $container.parent().get(0); 283 // Fix position automatically when appended to body. 284 // In other cases force parameter must be given. 285 if (containerParent !== document.body && !that.options.forceFixPosition) { 286 return; 287 } 288 289 // Choose orientation 290 var orientation = that.options.orientation, 291 containerHeight = $container.outerHeight(), 292 height = that.el.outerHeight(), 293 offset = that.el.offset(), 294 styles = { 295 'top': offset.top, 296 'left': offset.left 297 }; 298 if (orientation === 'auto') { 299 var viewPortHeight = $(window).height(), 300 scrollTop = $(window).scrollTop(), 301 topOverflow = -scrollTop + offset.top - containerHeight, 302 bottomOverflow = scrollTop + viewPortHeight - (offset.top + height + containerHeight); 303 orientation = Math.max(topOverflow, bottomOverflow) === topOverflow ? 'top' : 'bottom'; 304 } 305 if (orientation === 'top') { 306 styles.top += -containerHeight; 307 } else { 308 styles.top += height; 309 } 310 311 // If container is not positioned to body, 312 // correct its position using offset parent offset 313 if (containerParent !== document.body) { 314 var opacity = $container.css('opacity'), 315 parentOffsetDiff; 316 if (!that.visible) { 317 $container.css('opacity', 0).show(); 318 } 319 parentOffsetDiff = $container.offsetParent().offset(); 320 styles.top -= parentOffsetDiff.top; 321 styles.top += containerParent.scrollTop; 322 styles.left -= parentOffsetDiff.left; 323 if (!that.visible) { 324 $container.css('opacity', opacity).hide(); 325 } 326 } 327 if (that.options.width === 'auto') { 328 styles.width = that.el.outerWidth() + 'px'; 329 } 330 $container.css(styles); 331 }, 332 isCursorAtEnd: function isCursorAtEnd() { 333 var that = this, 334 valLength = that.el.val().length, 335 selectionStart = that.element.selectionStart, 336 range; 337 if (typeof selectionStart === 'number') { 338 return selectionStart === valLength; 339 } 340 if (document.selection) { 341 range = document.selection.createRange(); 342 range.moveStart('character', -valLength); 343 return valLength === range.text.length; 344 } 345 return true; 346 }, 347 onKeyPress: function onKeyPress(e) { 348 var that = this; 349 350 // If suggestions are hidden and user presses arrow down, display suggestions: 351 if (!that.disabled && !that.visible && e.which === keys.DOWN && that.currentValue) { 352 that.suggest(); 353 return; 354 } 355 if (that.disabled || !that.visible) { 356 return; 357 } 358 switch (e.which) { 359 case keys.ESC: 360 that.el.val(that.currentValue); 361 that.hide(); 362 break; 363 case keys.RIGHT: 364 if (that.hint && that.options.onHint && that.isCursorAtEnd()) { 365 that.selectHint(); 366 break; 367 } 368 return; 369 case keys.TAB: 370 if (that.hint && that.options.onHint) { 371 that.selectHint(); 372 return; 373 } 374 if (that.selectedIndex === -1) { 375 that.hide(); 376 return; 377 } 378 that.select(that.selectedIndex); 379 if (that.options.tabDisabled === false) { 380 return; 381 } 382 break; 383 case keys.RETURN: 384 if (that.selectedIndex === -1) { 385 that.hide(); 386 return; 387 } 388 that.select(that.selectedIndex); 389 break; 390 case keys.UP: 391 that.moveUp(); 392 break; 393 case keys.DOWN: 394 that.moveDown(); 395 break; 396 default: 397 return; 398 } 399 400 // Cancel event if function did not return: 401 e.stopImmediatePropagation(); 402 e.preventDefault(); 403 }, 404 onKeyUp: function onKeyUp(e) { 405 var that = this; 406 if (that.disabled) { 407 return; 408 } 409 switch (e.which) { 410 case keys.UP: 411 case keys.DOWN: 412 return; 413 } 414 clearTimeout(that.onChangeTimeout); 415 if (that.currentValue !== that.el.val()) { 416 that.findBestHint(); 417 if (that.options.deferRequestBy > 0) { 418 // Defer lookup in case when value changes very quickly: 419 that.onChangeTimeout = setTimeout(function () { 420 that.onValueChange(); 421 }, that.options.deferRequestBy); 422 } else { 423 that.onValueChange(); 424 } 425 } 426 }, 427 onValueChange: function onValueChange() { 428 if (this.ignoreValueChange) { 429 this.ignoreValueChange = false;
430 return; 431 } 432 var that = this, 433 options = that.options, 434 value = that.el.val(), 435 query = that.getQuery(value); 436 if (that.selection && that.currentValue !== query) { 437 that.selection = null; 438 (options.onInvalidateSelection || $.noop).call(that.element); 439 } 440 clearTimeout(that.onChangeTimeout); 441 that.currentValue = value; 442 that.selectedIndex = -1; 443 444 // Check existing suggestion for the match before proceeding: 445 if (options.triggerSelectOnValidInput && that.isExactMatch(query)) { 446 that.select(0); 447 return; 448 } 449 if (query.length < options.minChars) { 450 that.hide(); 451 } else { 452 that.getSuggestions(query); 453 } 454 }, 455 isExactMatch: function isExactMatch(query) { 456 var suggestions = this.suggestions; 457 return suggestions.length === 1 && suggestions[0].value.toLowerCase() === query.toLowerCase(); 458 }, 459 getQuery: function getQuery(value) { 460 var delimiter = this.options.delimiter, 461 parts; 462 if (!delimiter) { 463 return value; 464 } 465 parts = value.split(delimiter); 466 return $.trim(parts[parts.length - 1]); 467 }, 468 getSuggestionsLocal: function getSuggestionsLocal(query) { 469 var that = this, 470 options = that.options, 471 queryLowerCase = query.toLowerCase(), 472 filter = options.lookupFilter, 473 limit = parseInt(options.lookupLimit, 10), 474 data; 475 data = { 476 suggestions: $.grep(options.lookup, function (suggestion) { 477 return filter(suggestion, query, queryLowerCase); 478 }) 479 }; 480 if (limit && data.suggestions.length > limit) { 481 data.suggestions = data.suggestions.slice(0, limit); 482 } 483 return data; 484 }, 485 getSuggestions: function getSuggestions(q) { 486 var response, 487 that = this, 488 options = that.options, 489 serviceUrl = options.serviceUrl, 490 params, 491 cacheKey, 492 ajaxSettings; 493 options.params[options.paramName] = q; 494 if (options.onSearchStart.call(that.element, options.params) === false) { 495 return; 496 } 497 params = options.ignoreParams ? null : options.params; 498 if ($.isFunction(options.lookup)) { 499 options.lookup(q, function (data) { 500 that.suggestions = data.suggestions; 501 that.suggest(); 502 options.onSearchComplete.call(that.element, q, data.suggestions); 503 }); 504 return; 505 } 506 if (that.isLocal) { 507 response = that.getSuggestionsLocal(q); 508 } else { 509 if ($.isFunction(serviceUrl)) { 510 serviceUrl = serviceUrl.call(that.element, q); 511 } 512 cacheKey = serviceUrl + '?' + $.param(params || {}); 513 response = that.cachedResponse[cacheKey]; 514 } 515 if (response && Array.isArray(response.suggestions)) { 516 that.suggestions = response.suggestions; 517 that.suggest(); 518 options.onSearchComplete.call(that.element, q, response.suggestions); 519 } else if (!that.isBadQuery(q)) { 520 that.abortAjax(); 521 ajaxSettings = { 522 url: serviceUrl, 523 data: params, 524 type: options.type, 525 dataType: options.dataType 526 }; 527 $.extend(ajaxSettings, options.ajaxSettings); 528 that.currentRequest = $.ajax(ajaxSettings).done(function (data) { 529 var result; 530 that.currentRequest = null; 531 result = options.transformResult(data, q); 532 that.processResponse(result, q, cacheKey); 533 options.onSearchComplete.call(that.element, q, result.suggestions); 534 }).fail(function (jqXHR, textStatus, errorThrown) { 535 options.onSearchError.call(that.element, q, jqXHR, textStatus, errorThrown); 536 }); 537 } else { 538 options.onSearchComplete.call(that.element, q, []); 539 } 540 }, 541 isBadQuery: function isBadQuery(q) { 542 if (!this.options.preventBadQueries) { 543 return false; 544 } 545 var badQueries = this.badQueries, 546 i = badQueries.length; 547 while (i--) { 548 if (q.indexOf(badQueries[i]) === 0) { 549 return true; 550 } 551 } 552 return false;
553 }, 554 hide: function hide() { 555 var that = this, 556 container = $(that.suggestionsContainer); 557 if ($.isFunction(that.options.onHide) && that.visible) { 558 that.options.onHide.call(that.element, container); 559 } 560 that.visible = false; 561 that.selectedIndex = -1; 562 clearTimeout(that.onChangeTimeout); 563 $(that.suggestionsContainer).hide(); 564 that.signalHint(null); 565 }, 566 suggest: function suggest() { 567 if (!this.suggestions.length) { 568 if (this.options.showNoSuggestionNotice) { 569 this.noSuggestions(); 570 } else { 571 this.hide(); 572 } 573 return; 574 } 575 var that = this, 576 options = that.options, 577 groupBy = options.groupBy, 578 formatResult = options.formatResult, 579 value = that.getQuery(that.currentValue), 580 className = that.classes.suggestion, 581 classSelected = that.classes.selected, 582 container = $(that.suggestionsContainer), 583 noSuggestionsContainer = $(that.noSuggestionsContainer), 584 beforeRender = options.beforeRender, 585 html = '', 586 category, 587 formatGroup = function formatGroup(suggestion, index) { 588 var currentCategory = suggestion.data[groupBy]; 589 if (category === currentCategory) { 590 return ''; 591 } 592 category = currentCategory; 593 return options.formatGroup(suggestion, category); 594 }; 595 if (options.triggerSelectOnValidInput && that.isExactMatch(value)) { 596 that.select(0); 597 return; 598 } 599 600 // Build suggestions inner HTML: 601 $.each(that.suggestions, function (i, suggestion) { 602 if (groupBy) { 603 html += formatGroup(suggestion, value, i); 604 } 605 html += '<div class="' + className + '" data-index="' + i + '">' + formatResult(suggestion, value, i) + '</div>'; 606 }); 607 this.adjustContainerWidth(); 608 noSuggestionsContainer.detach(); 609 container.html(html); 610 if ($.isFunction(beforeRender)) { 611 beforeRender.call(that.element, container, that.suggestions); 612 } 613 that.fixPosition(); 614 container.show(); 615 616 // Select first value by default: 617 if (options.autoSelectFirst) { 618 that.selectedIndex = 0; 619 container.scrollTop(0); 620 container.children('.' + className).first().addClass(classSelected); 621 } 622 that.visible = true; 623 that.findBestHint(); 624 }, 625 noSuggestions: function noSuggestions() { 626 var that = this, 627 beforeRender = that.options.beforeRender, 628 container = $(that.suggestionsContainer), 629 noSuggestionsContainer = $(that.noSuggestionsContainer); 630 this.adjustContainerWidth(); 631 632 // Some explicit steps. Be careful here as it easy to get 633 // noSuggestionsContainer removed from DOM if not detached properly. 634 noSuggestionsContainer.detach(); 635 636 // clean suggestions if any 637 container.empty(); 638 container.append(noSuggestionsContainer); 639 if ($.isFunction(beforeRender)) { 640 beforeRender.call(that.element, container, that.suggestions); 641 } 642 that.fixPosition(); 643 container.show(); 644 that.visible = true; 645 }, 646 adjustContainerWidth: function adjustContainerWidth() { 647 var that = this, 648 options = that.options, 649 width, 650 container = $(that.suggestionsContainer); 651 652 // If width is auto, adjust width before displaying suggestions, 653 // because if instance was created before input had width, it will be zero. 654 // Also it adjusts if input width has changed. 655 if (options.width === 'auto') { 656 width = that.el.outerWidth(); 657 container.css('width', width > 0 ? width : 300); 658 } else if (options.width === 'flex') { 659 // Trust the source! Unset the width property so it will be the max length 660 // the containing elements. 661 container.css('width', ''); 662 } 663 }, 664 findBestHint: function findBestHint() { 665 var that = this, 666 value = that.el.val().toLowerCase(), 667 bestMatch = null; 668 if (!value) { 669 return; 670 } 671 $.each(that.suggestions, function (i, suggestion) { 672 var foundMatch = suggestion.value.toLowerCase().indexOf(value) === 0; 673 if (foundMatch) { 674 bestMatch = suggestion; 675 } 676 return !foundMatch; 677 }); 678 that.signalHint(bestMatch); 679 }, 680 signalHint: function signalHint(suggestion) { 681 var hintValue = '', 682 that = this; 683 if (suggestion) { 684 hintValue = that.currentValue + suggestion.value.substr(that.currentValue.length); 685 } 686 if (that.hintValue !== hintValue) { 687 that.hintValue = hintValue; 688 that.hint = suggestion; 689 (this.options.onHint || $.noop)(hintValue); 690 } 691 }, 692 verifySuggestionsFormat: function verifySuggestionsFormat(suggestions) {
693 // If suggestions is string array, convert them to supported format: 694 if (suggestions.length && typeof suggestions[0] === 'string') { 695 return $.map(suggestions, function (value) { 696 return { 697 value: value, 698 data: null 699 }; 700 }); 701 } 702 return suggestions; 703 }, 704 validateOrientation: function validateOrientation(orientation, fallback) { 705 orientation = $.trim(orientation || '').toLowerCase(); 706 if ($.inArray(orientation, ['auto', 'bottom', 'top']) === -1) { 707 orientation = fallback; 708 } 709 return orientation; 710 }, 711 processResponse: function processResponse(result, originalQuery, cacheKey) { 712 var that = this, 713 options = that.options; 714 result.suggestions = that.verifySuggestionsFormat(result.suggestions); 715 716 // Cache results if cache is not disabled: 717 if (!options.noCache) { 718 that.cachedResponse[cacheKey] = result; 719 if (options.preventBadQueries && !result.suggestions.length) { 720 that.badQueries.push(originalQuery); 721 } 722 } 723 724 // Return if originalQuery is not matching current query: 725 if (originalQuery !== that.getQuery(that.currentValue)) { 726 return; 727 } 728 that.suggestions = result.suggestions; 729 that.suggest(); 730 }, 731 activate: function activate(index) { 732 var that = this, 733 activeItem, 734 selected = that.classes.selected, 735 container = $(that.suggestionsContainer), 736 children = container.find('.' + that.classes.suggestion); 737 container.find('.' + selected).removeClass(selected); 738 that.selectedIndex = index; 739 if (that.selectedIndex !== -1 && children.length > that.selectedIndex) { 740 activeItem = children.get(that.selectedIndex); 741 $(activeItem).addClass(selected); 742 return activeItem; 743 } 744 return null; 745 }, 746 selectHint: function selectHint() { 747 var that = this, 748 i = $.inArray(that.hint, that.suggestions); 749 that.select(i); 750 }, 751 select: function select(i) { 752 var that = this; 753 that.hide(); 754 that.onSelect(i); 755 }, 756 moveUp: function moveUp() { 757 var that = this; 758 if (that.selectedIndex === -1) { 759 return; 760 } 761 if (that.selectedIndex === 0) { 762 $(that.suggestionsContainer).children('.' + that.classes.suggestion).first().removeClass(that.classes.selected); 763 that.selectedIndex = -1; 764 that.ignoreValueChange = false; 765 that.el.val(that.currentValue); 766 that.findBestHint(); 767 return; 768 } 769 that.adjustScroll(that.selectedIndex - 1); 770 }, 771 moveDown: function moveDown() { 772 var that = this; 773 if (that.selectedIndex === that.suggestions.length - 1) { 774 return; 775 } 776 that.adjustScroll(that.selectedIndex + 1); 777 }, 778 adjustScroll: function adjustScroll(index) { 779 var that = this, 780 activeItem = that.activate(index); 781 if (!activeItem) { 782 return; 783 } 784 var offsetTop, 785 upperBound, 786 lowerBound, 787 heightDelta = $(activeItem).outerHeight(); 788 offsetTop = activeItem.offsetTop; 789 upperBound = $(that.suggestionsContainer).scrollTop(); 790 lowerBound = upperBound + that.options.maxHeight - heightDelta; 791 if (offsetTop < upperBound) { 792 $(that.suggestionsContainer).scrollTop(offsetTop); 793 } else if (offsetTop > lowerBound) { 794 $(that.suggestionsContainer).scrollTop(offsetTop - that.options.maxHeight + heightDelta); 795 } 796 if (!that.options.preserveInput) { 797 // During onBlur event, browser will trigger "change" event, 798 // because value has changed, to avoid side effect ignore, 799 // that event, so that correct suggestion can be selected 800 // when clicking on suggestion with a mouse 801 that.ignoreValueChange = true; 802 that.el.val(that.getValue(that.suggestions[index].value)); 803 } 804 that.signalHint(null); 805 }, 806 onSelect: function onSelect(index) { 807 var that = this, 808 onSelectCallback = that.options.onSelect, 809 suggestion = that.suggestions[index]; 810 that.currentValue = that.getValue(suggestion.value); 811 if (that.currentValue !== that.el.val() && !that.options.preserveInput) { 812 that.el.val(that.currentValue); 813 } 814 that.signalHint(null); 815 that.suggestions = []; 816 that.selection = suggestion; 817 if ($.isFunction(onSelectCallback)) { 818 onSelectCallback.call(that.element, suggestion); 819 } 820 }, 821 getValue: function getValue(value) { 822 var that = this, 823 delimiter = that.options.delimiter, 824 currentValue, 825 parts; 826 if (!delimiter) { 827 return value; 828 } 829 currentValue = that.currentValue; 830 parts = currentValue.split(delimiter); 831 if (parts.length === 1) { 832 return value; 833 } 834 return currentValue.substr(0, currentValue.length - parts[parts.length - 1].length) + value; 835 }, 836 dispose: function dispose() { 837 var that = this; 838 that.el.off('.autocomplete').removeData('autocomplete'); 839 $(window).off('resize.autocomplete', that.fixPositionCapture); 840 $(that.suggestionsContainer).remove(); 841 } 842 }; 843 844 // Create chainable jQuery plugin: 845 $.fn.devbridgeAutocomplete = function (options, args) { 846 var dataKey = 'autocomplete'; 847 // If function invoked without argument return 848 // instance of the first matched element: 849 if (!arguments.length) { 850 return this.first().data(dataKey); 851 } 852 return this.each(function () { 853 var inputElement = $(this), 854 instance = inputElement.data(dataKey); 855 if (typeof options === 'string') { 856 if (instance && typeof instance[options] === 'function') { 857 instance[options](args); 858 } 859 } else { 860 // If instance already exists, destroy it: 861 if (instance && instance.dispose) { 862 instance.dispose(); 863 } 864 instance = new Autocomplete(this, options); 865 inputElement.data(dataKey, instance); 866 } 867 }); 868 }; 869 870 // Don't overwrite if it already exists 871 if (!$.fn.autocomplete) { 872 $.fn.autocomplete = $.fn.devbridgeAutocomplete; 873 } 874}); 875 876}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 877},{}],2:[function(require,module,exports){ 878(function (global){(function (){ 879"use strict"; 880 881function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 882/*! 883 * VERSION: 1.20.4 884 * DATE: 2018-02-15 885 * UPDATES AND DOCS AT: http://greensock.com 886 * 887 * @license Copyright (c) 2008-2018, GreenSock. All rights reserved. 888 * This work is subject to the terms at http://greensock.com/standard-license or for
889 * Club GreenSock members, the software agreement that was issued with your membership. 890 * 891 * @author: Jack Doyle, [email protected] 892 */ 893var _gsScope = typeof module !== "undefined" && module.exports && typeof global !== "undefined" ? global : void 0 || window; //helps ensure compatibility with AMD/RequireJS and CommonJS/Node 894(_gsScope._gsQueue || (_gsScope._gsQueue = [])).push(function () { 895 "use strict"; 896 897 _gsScope._gsDefine("plugins.CSSPlugin", ["plugins.TweenPlugin", "TweenLite"], function (TweenPlugin, TweenLite) { 898 /** @constructor **/ 899 var _CSSPlugin = function CSSPlugin() { 900 TweenPlugin.call(this, "css"); 901 this._overwriteProps.length = 0; 902 this.setRatio = _CSSPlugin.prototype.setRatio; //speed optimization (avoid prototype lookup on this "hot" method) 903 }, 904 _globals = _gsScope._gsDefine.globals, 905 _hasPriority, 906 //turns true whenever a CSSPropTween instance is created that has a priority other than 0. This helps us discern whether or not we should spend the time organizing the linked list or not after a CSSPlugin's _onInitTween() method is called. 907 _suffixMap, 908 //we set this in _onInitTween() each time as a way to have a persistent variable we can use in other methods like _parse() without having to pass it around as a parameter and we keep _parse() decoupled from a particular CSSPlugin instance 909 _cs, 910 //computed style (we store this in a shared variable to conserve memory and make minification tighter 911 _overwriteProps, 912 //alias to the currently instantiating CSSPlugin's _overwriteProps array. We use this closure in order to avoid having to pass a reference around from method to method and aid in minification. 913 _specialProps = {}, 914 p = _CSSPlugin.prototype = new TweenPlugin("css"); 915 p.constructor = _CSSPlugin; 916 _CSSPlugin.version = "1.20.4"; 917 _CSSPlugin.API = 2; 918 _CSSPlugin.defaultTransformPerspective = 0; 919 _CSSPlugin.defaultSkewType = "compensated"; 920 _CSSPlugin.defaultSmoothOrigin = true; 921 p = "px"; //we'll reuse the "p" variable to keep file size down 922 _CSSPlugin.suffixMap = { 923 top: p, 924 right: p, 925 bottom: p, 926 left: p, 927 width: p, 928 height: p, 929 fontSize: p, 930 padding: p, 931 margin: p, 932 perspective: p, 933 lineHeight: "" 934 }; 935 var _numExp = /(?:\-|\.|\b)(\d|\.|e\-)+/g, 936 _relNumExp = /(?:\d|\-\d|\.\d|\-\.\d|\+=\d|\-=\d|\+=.\d|\-=\.\d)+/g, 937 _valuesExp = /(?:\+=|\-=|\-|\b)[\d\-\.]+[a-zA-Z0-9]*(?:%|\b)/gi, 938 //finds all the values that begin with numbers or += or -= and then a number. Includes suffixes. We use this to split complex values apart like "1px 5px 20px rgb(255,102,51)" 939 _NaNExp = /(?![+-]?\d*\.?\d+|[+-]|e[+-]\d+)[^0-9]/g, 940 //also allows scientific notation and doesn't kill the leading -/+ in -= and += 941 _suffixExp = /(?:\d|\-|\+|=|#|\.)*/g, 942 _opacityExp = /opacity *= *([^)]*)/i, 943 _opacityValExp = /opacity:([^;]*)/i, 944 _alphaFilterExp = /alpha\(opacity *=.+?\)/i, 945 _rgbhslExp = /^(rgb|hsl)/, 946 _capsExp = /([A-Z])/g, 947 _camelExp = /-([a-z])/gi, 948 _urlExp = /(^(?:url\(\"|url\())|(?:(\"\))$|\)$)/gi, 949 //for pulling out urls from url(...) or url("...") strings (some browsers wrap urls in quotes, some don't when reporting things like backgroundImage) 950 _camelFunc = function _camelFunc(s, g) { 951 return g.toUpperCase(); 952 }, 953 _horizExp = /(?:Left|Right|Width)/i, 954 _ieGetMatrixExp = /(M11|M12|M21|M22)=[\d\-\.e]+/gi, 955 _ieSetMatrixExp = /progid\:DXImageTransform\.Microsoft\.Matrix\(.+?\)/i, 956 _commasOutsideParenExp = /,(?=[^\)]*(?:\(|$))/gi, 957 //finds any commas that are not within parenthesis 958 _complexExp = /[\s,\(]/i, 959 //for testing a string to find if it has a space, comma, or open parenthesis (clues that it's a complex value) 960 _DEG2RAD = Math.PI / 180, 961 _RAD2DEG = 180 / Math.PI, 962 _forcePT = {}, 963 _dummyElement = { 964 style: {} 965 }, 966 _doc = _gsScope.document || { 967 createElement: function createElement() { 968 return _dummyElement; 969 } 970 }, 971 _createElement = function _createElement(type, ns) { 972 return _doc.createElementNS ? _doc.createElementNS(ns || "http://www.w3.org/1999/xhtml", type) : _doc.createElement(type); 973 }, 974 _tempDiv = _createElement("div"), 975 _tempImg = _createElement("img"), 976 _internals = _CSSPlugin._internals = { 977 _specialProps: _specialProps 978 }, 979 //provides a hook to a few internal methods that we need to access from inside other plugins 980 _agent = (_gsScope.navigator || {}).userAgent || "", 981 _autoRound, 982 _reqSafariFix, 983 //we won't apply the Safari transform fix until we actually come across a tween that affects a transform property (to maintain best performance). 984 985 _isSafari, 986 _isFirefox, 987 //Firefox has a bug that causes 3D transformed elements to randomly disappear unless a repaint is forced after each update on each element. 988 _isSafariLT6, 989 //Safari (and Android 4 which uses a flavor of Safari) has a bug that prevents changes to "top" and "left" properties from rendering properly if changed on the same frame as a transform UNLESS we set the element's WebkitBackfaceVisibility to hidden (weird, I know). Doing this for Android 3 and earlier seems to actually cause other problems, though (fun!) 990 _ieVers, 991 _supportsOpacity = function () { 992 //we set _isSafari, _ieVers, _isFirefox, and _supportsOpacity all in one function here to reduce file size slightly, especially in the minified version. 993 var i = _agent.indexOf("Android"), 994 a = _createElement("a"); 995 _isSafari = _agent.indexOf("Safari") !== -1 && _agent.indexOf("Chrome") === -1 && (i === -1 || parseFloat(_agent.substr(i + 8, 2)) > 3); 996 _isSafariLT6 = _isSafari && parseFloat(_agent.substr(_agent.indexOf("Version/") + 8, 2)) < 6; 997 _isFirefox = _agent.indexOf("Firefox") !== -1; 998 if (/MSIE ([0-9]{1,}[\.0-9]{0,})/.exec(_agent) || /Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/.exec(_agent)) { 999 _ieVers = parseFloat(RegExp.$1); 1000 } 1001 if (!a) { 1002 return false;
1003 } 1004 a.style.cssText = "top:1px;opacity:.55;"; 1005 return /^0.55/.test(a.style.opacity); 1006 }(), 1007 _getIEOpacity = function _getIEOpacity(v) { 1008 return _opacityExp.test(typeof v === "string" ? v : (v.currentStyle ? v.currentStyle.filter : v.style.filter) || "") ? parseFloat(RegExp.$1) / 100 : 1; 1009 }, 1010 _log = function _log(s) { 1011 //for logging messages, but in a way that won't throw errors in old versions of IE. 1012 if (_gsScope.console) { 1013 console.log(s); 1014 } 1015 }, 1016 _target, 1017 //when initting a CSSPlugin, we set this variable so that we can access it from within many other functions without having to pass it around as params 1018 _index, 1019 //when initting a CSSPlugin, we set this variable so that we can access it from within many other functions without having to pass it around as params 1020 1021 _prefixCSS = "", 1022 //the non-camelCase vendor prefix like "-o-", "-moz-", "-ms-", or "-webkit-" 1023 _prefix = "", 1024 //camelCase vendor prefix like "O", "ms", "Webkit", or "Moz". 1025 1026 // @private feed in a camelCase property name like "transform" and it will check to see if it is valid as-is or if it needs a vendor prefix. It returns the corrected camelCase property name (i.e. "WebkitTransform" or "MozTransform" or "transform" or null if no such property is found, like if the browser is IE8 or before, "transform" won't be found at all) 1027 _checkPropPrefix = function _checkPropPrefix(p, e) { 1028 e = e || _tempDiv; 1029 var s = e.style, 1030 a, 1031 i; 1032 if (s[p] !== undefined) { 1033 return p; 1034 } 1035 p = p.charAt(0).toUpperCase() + p.substr(1); 1036 a = ["O", "Moz", "ms", "Ms", "Webkit"]; 1037 i = 5; 1038 while (--i > -1 && s[a[i] + p] === undefined) {} 1039 if (i >= 0) { 1040 _prefix = i === 3 ? "ms" : a[i]; 1041 _prefixCSS = "-" + _prefix.toLowerCase() + "-"; 1042 return _prefix + p; 1043 } 1044 return null; 1045 }, 1046 _getComputedStyle = _doc.defaultView ? _doc.defaultView.getComputedStyle : function () {}, 1047 /** 1048 * @private Returns the css style for a particular property of an element. For example, to get whatever the current "left" css value for an element with an ID of "myElement", you could do: 1049 * var currentLeft = CSSPlugin.getStyle( document.getElementById("myElement"), "left"); 1050 * 1051 * @param {!Object} t Target element whose style property you want to query 1052 * @param {!string} p Property name (like "left" or "top" or "marginTop", etc.) 1053 * @param {Object=} cs Computed style object. This just provides a way to speed processing if you're going to get several properties on the same element in quick succession - you can reuse the result of the getComputedStyle() call. 1054 * @param {boolean=} calc If true, the value will not be read directly from the element's "style" property (if it exists there), but instead the getComputedStyle() result will be used. This can be useful when you want to ensure that the browser itself is interpreting the value. 1055 * @param {string=} dflt Default value that should be returned in the place of null, "none", "auto" or "auto auto". 1056 * @return {?string} The current property value 1057 */ 1058 _getStyle = _CSSPlugin.getStyle = function (t, p, cs, calc, dflt) { 1059 var rv; 1060 if (!_supportsOpacity) if (p === "opacity") { 1061 //several versions of IE don't use the standard "opacity" property - they use things like filter:alpha(opacity=50), so we parse that here. 1062 return _getIEOpacity(t); 1063 } 1064 if (!calc && t.style[p]) { 1065 rv = t.style[p]; 1066 } else if (cs = cs || _getComputedStyle(t)) { 1067 rv = cs[p] || cs.getPropertyValue(p) || cs.getPropertyValue(p.replace(_capsExp, "-$1").toLowerCase()); 1068 } else if (t.currentStyle) { 1069 rv = t.currentStyle[p]; 1070 } 1071 return dflt != null && (!rv || rv === "none" || rv === "auto" || rv === "auto auto") ? dflt : rv; 1072 }, 1073 /** 1074 * @private Pass the target element, the property name, the numeric value, and the suffix (like "%", "em", "px", etc.) and it will spit back the equivalent pixel number. 1075 * @param {!Object} t Target element 1076 * @param {!string} p Property name (like "left", "top", "marginLeft", etc.) 1077 * @param {!number} v Value 1078 * @param {string=} sfx Suffix (like "px" or "%" or "em") 1079 * @param {boolean=} recurse If true, the call is a recursive one. In some browsers (like IE7/8), occasionally the value isn't accurately reported initially, but if we run the function again it will take effect. 1080 * @return {number} value in pixels 1081 */ 1082 _convertToPixels = _internals.convertToPixels = function (t, p, v, sfx, recurse) { 1083 if (sfx === "px" || !sfx && p !== "lineHeight") { 1084 return v; 1085 } 1086 if (sfx === "auto" || !v) { 1087 return 0; 1088 } 1089 var horiz = _horizExp.test(p), 1090 node = t, 1091 style = _tempDiv.style, 1092 neg = v < 0, 1093 precise = v === 1, 1094 pix, 1095 cache, 1096 time; 1097 if (neg) { 1098 v = -v; 1099 } 1100 if (precise) { 1101 v *= 100; 1102 } 1103 if (p === "lineHeight" && !sfx) { 1104 //special case of when a simple lineHeight (without a unit) is used. Set it to the value, read back the computed value, and then revert. 1105 cache = _getComputedStyle(t).lineHeight; 1106 t.style.lineHeight = v; 1107 pix = parseFloat(_getComputedStyle(t).lineHeight); 1108 t.style.lineHeight = cache; 1109 } else if (sfx === "%" && p.indexOf("border") !== -1) { 1110 pix = v / 100 * (horiz ? t.clientWidth : t.clientHeight); 1111 } else { 1112 style.cssText = "border:0 solid red;position:" + _getStyle(t, "position") + ";line-height:0;"; 1113 if (sfx === "%" || !node.appendChild || sfx.charAt(0) === "v" || sfx === "rem") { 1114 node = t.parentNode || _doc.body; 1115 if (_getStyle(node, "display").indexOf("flex") !== -1) { 1116 //Edge and IE11 have a bug that causes offsetWidth to report as 0 if the container has display:flex and the child is position:relative. Switching to position: absolute solves it. 1117 style.position = "absolute"; 1118 } 1119 cache = node._gsCache; 1120 time = TweenLite.ticker.frame; 1121 if (cache && horiz && cache.time === time) { 1122 //performance optimization: we record the width of elements along with the ticker frame so that we can quickly get it again on the same tick (seems relatively safe to assume it wouldn't change on the same tick) 1123 return cache.width * v / 100; 1124 } 1125 style[horiz ? "width" : "height"] = v + sfx; 1126 } else { 1127 style[horiz ? "borderLeftWidth" : "borderTopWidth"] = v + sfx; 1128 } 1129 node.appendChild(_tempDiv); 1130 pix = parseFloat(_tempDiv[horiz ? "offsetWidth" : "offsetHeight"]); 1131 node.removeChild(_tempDiv); 1132 if (horiz && sfx === "%" && _CSSPlugin.cacheWidths !== false) { 1133 cache = node._gsCache = node._gsCache || {}; 1134 cache.time = time; 1135 cache.width = pix / v * 100; 1136 } 1137 if (pix === 0 && !recurse) { 1138 pix = _convertToPixels(t, p, v, sfx, true); 1139 } 1140 } 1141 if (precise) { 1142 pix /= 100; 1143 } 1144 return neg ? -pix : pix; 1145 }, 1146 _calculateOffset = _internals.calculateOffset = function (t, p, cs) { 1147 //for figuring out "top" or "left" in px when it's "auto". We need to factor in margin with the offsetLeft/offsetTop 1148 if (_getStyle(t, "position", cs) !== "absolute") { 1149 return 0; 1150 } 1151 var dim = p === "left" ? "Left" : "Top",
1152 v = _getStyle(t, "margin" + dim, cs); 1153 return t["offset" + dim] - (_convertToPixels(t, p, parseFloat(v), v.replace(_suffixExp, "")) || 0); 1154 }, 1155 // @private returns at object containing ALL of the style properties in camelCase and their associated values. 1156 _getAllStyles = function _getAllStyles(t, cs) { 1157 var s = {}, 1158 i, 1159 tr, 1160 p; 1161 if (cs = cs || _getComputedStyle(t, null)) { 1162 if (i = cs.length) { 1163 while (--i > -1) { 1164 p = cs[i]; 1165 if (p.indexOf("-transform") === -1 || _transformPropCSS === p) { 1166 //Some webkit browsers duplicate transform values, one non-prefixed and one prefixed ("transform" and "WebkitTransform"), so we must weed out the extra one here. 1167 s[p.replace(_camelExp, _camelFunc)] = cs.getPropertyValue(p); 1168 } 1169 } 1170 } else { 1171 //some browsers behave differently - cs.length is always 0, so we must do a for...in loop. 1172 for (i in cs) { 1173 if (i.indexOf("Transform") === -1 || _transformProp === i) { 1174 //Some webkit browsers duplicate transform values, one non-prefixed and one prefixed ("transform" and "WebkitTransform"), so we must weed out the extra one here. 1175 s[i] = cs[i]; 1176 } 1177 } 1178 } 1179 } else if (cs = t.currentStyle || t.style) { 1180 for (i in cs) { 1181 if (typeof i === "string" && s[i] === undefined) { 1182 s[i.replace(_camelExp, _camelFunc)] = cs[i]; 1183 } 1184 } 1185 } 1186 if (!_supportsOpacity) { 1187 s.opacity = _getIEOpacity(t); 1188 } 1189 tr = _getTransform(t, cs, false); 1190 s.rotation = tr.rotation; 1191 s.skewX = tr.skewX; 1192 s.scaleX = tr.scaleX; 1193 s.scaleY = tr.scaleY; 1194 s.x = tr.x; 1195 s.y = tr.y; 1196 if (_supports3D) { 1197 s.z = tr.z; 1198 s.rotationX = tr.rotationX; 1199 s.rotationY = tr.rotationY; 1200 s.scaleZ = tr.scaleZ; 1201 } 1202 if (s.filters) { 1203 delete s.filters; 1204 } 1205 return s; 1206 }, 1207 // @private analyzes two style objects (as returned by _getAllStyles()) and only looks for differences between them that contain tweenable values (like a number or color). It returns an object with a "difs" property which refers to an object c
1207ontaining only those isolated properties and values for tweening, and a "firstMPT" property which refers to the first MiniPropTween instance in a linked list that recorded all the starting values of the different properties so that we can revert to them at the end or beginning of the tween - we don't want the cascading to get messed up. The forceLookup parameter is an optional generic object with properties that should be forced into the results - this is necessary for className tweens that are overwriting others because imagine a scenario where a rollover/rollout adds/removes a class and the user swipes the mouse over the target SUPER fast, thus nothing actually changed yet and the subsequent comparison of the properties would indicate they match (especially when px rounding is taken into consideration), thus no tweening is necessary even though it SHOULD tween and remove those properties after the tween (otherwise the inline styles will contaminate things). See the className SpecialProp code for details. 1208 _cssDif = function _cssDif(t, s1, s2, vars, forceLookup) { 1209 var difs = {}, 1210 style = t.style, 1211 val, 1212 p, 1213 mpt; 1214 for (p in s2) { 1215 if (p !== "cssText") if (p !== "length") if (isNaN(p)) if (s1[p] !== (val = s2[p]) || forceLookup && forceLookup[p]) if (p.indexOf("Origin") === -1) if (typeof val === "number" || typeof val === "string") { 1216 difs[p] = val === "auto" && (p === "left" || p === "top") ? _calculateOffset(t, p) : (val === "" || val === "auto" || val === "none") && typeof s1[p] === "string" && s1[p].replace(_NaNExp, "") !== "" ? 0 : val; //if the ending value is defaulting ("" or "auto"), we check the starting value and if it can be parsed into a number (a string which could have a suffix too, like 700px), then we swap in 0 for "" or "auto" so that things actually tween. 1217 if (style[p] !== undefined) { 1218 //for className tweens, we must remember which properties already existed inline - the ones that didn't should be removed when the tween isn't in progress because they were only introduced to facilitate the transition between classes. 1219 mpt = new MiniPropTween(style, p, style[p], mpt); 1220 } 1221 } 1222 } 1223 if (vars) { 1224 for (p in vars) { 1225 //copy properties (except className) 1226 if (p !== "className") { 1227 difs[p] = vars[p]; 1228 } 1229 } 1230 } 1231 return { 1232 difs: difs, 1233 firstMPT: mpt 1234 }; 1235 }, 1236 _dimensions = { 1237 width: ["Left", "Right"], 1238 height: ["Top", "Bottom"] 1239 }, 1240 _margins = ["marginLeft", "marginRight", "marginTop", "marginBottom"], 1241 /** 1242 * @private Gets the width or height of an element 1243 * @param {!Object} t Target element 1244 * @param {!string} p Property name ("width" or "height") 1245 * @param {Object=} cs Computed style object (if one exists). Just a speed optimization. 1246 * @return {number} Dimension (in pixels) 1247 */ 1248 _getDimension = function _getDimension(t, p, cs) { 1249 if ((t.nodeName + "").toLowerCase() === "svg") { 1250 //Chrome no longer supports offsetWidth/offsetHeight on SVG elements. 1251 return (cs || _getComputedStyle(t))[p] || 0; 1252 } else if (t.getCTM && _isSVG(t)) { 1253 return t.getBBox()[p] || 0; 1254 } 1255 var v = parseFloat(p === "width" ? t.offsetWidth : t.offsetHeight), 1256 a = _dimensions[p], 1257 i = a.length; 1258 cs = cs || _getComputedStyle(t, null); 1259 while (--i > -1) { 1260 v -= parseFloat(_getStyle(t, "padding" + a[i], cs, true)) || 0; 1261 v -= parseFloat(_getStyle(t, "border" + a[i] + "Width", cs, true)) || 0; 1262 } 1263 return v; 1264 }, 1265 // @private Parses position-related complex strings like "top left" or "50px 10px" or "70% 20%", etc. which are used for things like transformOrigin or backgroundPosition. Optionally decorates a supplied object (recObj) with the following properties: "ox" (offsetX), "oy" (offsetY), "oxp" (if true, "ox" is a percentage not a pixel value), and "oxy" (if true, "oy" is a percentage not a pixel value) 1266 _parsePosition2 = function _parsePosition(v, recObj) { 1267 if (v === "contain" || v === "auto" || v === "auto auto") { 1268 //note: Firefox uses "auto auto" as default whereas Chrome uses "auto". 1269 return v + " "; 1270 } 1271 if (v == null || v === "") { 1272 v = "0 0"; 1273 } 1274 var a = v.split(" "), 1275 x = v.indexOf("left") !== -1 ? "0%" : v.indexOf("right") !== -1 ? "100%" : a[0], 1276 y = v.indexOf("top") !== -1 ? "0%" : v.indexOf("bottom") !== -1 ? "100%" : a[1], 1277 i; 1278 if (a.length > 3 && !recObj) { 1279 //multiple positions 1280 a = v.split(", ").join(",").split(","); 1281 v = []; 1282 for (i = 0; i < a.length; i++) { 1283 v.push(_parsePosition2(a[i])); 1284 } 1285 return v.join(","); 1286 } 1287 if (y == null) { 1288 y = x === "center" ? "50%" : "0"; 1289 } else if (y === "center") { 1290 y = "50%"; 1291 } 1292 if (x === "center" || isNaN(parseFloat(x)) && (x + "").indexOf("=") === -1) { 1293 //remember, the user could flip-flop the values and say "bottom center" or "center bottom", etc. "center" is ambiguous because it c
1293ould be used to describe horizontal or vertical, hence the isNaN(). If there's an "=" sign in the value, it's relative. 1294 x = "50%"; 1295 } 1296 v = x + " " + y + (a.length > 2 ? " " + a[2] : ""); 1297 if (recObj) { 1298 recObj.oxp = x.indexOf("%") !== -1; 1299 recObj.oyp = y.indexOf("%") !== -1; 1300 recObj.oxr = x.charAt(1) === "="; 1301 recObj.oyr = y.charAt(1) === "="; 1302 recObj.ox = parseFloat(x.replace(_NaNExp, "")); 1303 recObj.oy = parseFloat(y.replace(_NaNExp, "")); 1304 recObj.v = v; 1305 } 1306 return recObj || v; 1307 }, 1308 /** 1309 * @private Takes an ending value (typically a string, but can be a number) and a starting value and returns the change between the two, looking for relative value indicators like += and -= and it also ignores suffixes (but make sure the ending value starts with a number or +=/-= and that the starting value is a NUMBER!) 1310 * @param {(number|string)} e End value which is typically a string, but could be a number 1311 * @param {(number|string)} b Beginning value which is typically a string but could be a number 1312 * @return {number} Amount of change between the beginning and ending values (relative values that have a "+=" or "-=" are recognized) 1313 */ 1314 _parseChange = function _parseChange(e, b) { 1315 if (typeof e === "function") { 1316 e = e(_index, _target); 1317 } 1318 return typeof e === "string" && e.charAt(1) === "=" ? parseInt(e.charAt(0) + "1", 10) * parseFloat(e.substr(2)) : parseFloat(e) - parseFloat(b) || 0; 1319 }, 1320 /** 1321 * @private Takes a value and a default number, checks if the value is relative, null, or numeric and spits back a normalized number accordingly. Primarily used in the _parseTransform() function. 1322 * @param {Object} v Value to be parsed 1323 * @param {!number} d Default value (which is also used for relative calculations if "+=" or "-=" is found in the first parameter) 1324 * @return {number} Parsed value 1325 */ 1326 _parseVal = function _parseVal(v, d) { 1327 if (typeof v === "function") { 1328 v = v(_index, _target); 1329 } 1330 return v == null ? d : typeof v === "string" && v.charAt(1) === "=" ? parseInt(v.charAt(0) + "1", 10) * parseFloat(v.substr(2)) + d : parseFloat(v) || 0; 1331 }, 1332 /** 1333 * @private Translates strings like "40deg" or "40" or 40rad" or "+=40deg" or "270_short" or "-90_cw" or "+=45_ccw" to a numeric radian angle. Of course a starting/default value must be fed in too so that relative values can be calculated properly. 1334 * @param {Object} v Value to be parsed 1335 * @param {!number} d Default value (which is also used for relative calculations if "+=" or "-=" is found in the first parameter) 1336 * @param {string=} p property name for directionalEnd (optional - only used when the parsed value is directional ("_short", "_cw", or "_ccw" suffix). We need a way to store the uncompensated value so that at the end of the tween, we set it to exactly what was requested with no directional compensation). Property name would be "rotation", "rotationX", or "rotationY" 1337 * @param {Object=} directionalEnd An object that will store the raw end values for directional angles ("_short", "_cw", or "_ccw" suffix). We need a way to store the uncompensated value so that at the end of the tween, we set it to exactly what was requested with no directional compensation. 1338 * @return {number} parsed angle in radians 1339 */ 1340 _parseAngle = function _parseAngle(v, d, p, directionalEnd) { 1341 var min = 0.000001, 1342 cap, 1343 split, 1344 dif, 1345 result, 1346 isRelative; 1347 if (typeof v === "function") { 1348 v = v(_index, _target); 1349 } 1350 if (v == null) { 1351 result = d; 1352 } else if (typeof v === "number") { 1353 result = v; 1354 } else { 1355 cap = 360; 1356 split = v.split("_"); 1357 isRelative = v.charAt(1) === "="; 1358 dif = (isRelative ? parseInt(v.charAt(0) + "1", 10) * parseFloat(split[0].substr(2)) : parseFloat(split[0])
1358) * (v.indexOf("rad") === -1 ? 1 : _RAD2DEG) - (isRelative ? 0 : d); 1359 if (split.length) { 1360 if (directionalEnd) { 1361 directionalEnd[p] = d + dif; 1362 } 1363 if (v.indexOf("short") !== -1) { 1364 dif = dif % cap; 1365 if (dif !== dif % (cap / 2)) { 1366 dif = dif < 0 ? dif + cap : dif - cap; 1367 } 1368 } 1369 if (v.indexOf("_cw") !== -1 && dif < 0) { 1370 dif = (dif + cap * 9999999999) % cap - (dif / cap | 0) * cap; 1371 } else if (v.indexOf("ccw") !== -1 && dif > 0) { 1372 dif = (dif - cap * 9999999999) % cap - (dif / cap | 0) * cap; 1373 } 1374 } 1375 result = d + dif; 1376 } 1377 if (result < min && result > -min) { 1378 result = 0; 1379 } 1380 return result; 1381 }, 1382 _colorLookup = { 1383 aqua: [0, 255, 255], 1384 lime: [0, 255, 0], 1385 silver: [192, 192, 192], 1386 black: [0, 0, 0], 1387 maroon: [128, 0, 0], 1388 teal: [0, 128, 128], 1389 blue: [0, 0, 255], 1390 navy: [0, 0, 128], 1391 white: [255, 255, 255], 1392 fuchsia: [255, 0, 255], 1393 olive: [128, 128, 0], 1394 yellow: [255, 255, 0], 1395 orange: [255, 165, 0], 1396 gray: [128, 128, 128], 1397 purple: [128, 0, 128], 1398 green: [0, 128, 0], 1399 red: [255, 0, 0], 1400 pink: [255, 192, 203], 1401 cyan: [0, 255, 255], 1402 transparent: [255, 255, 255, 0] 1403 }, 1404 _hue = function _hue(h, m1, m2) { 1405 h = h < 0 ? h + 1 : h > 1 ? h - 1 : h; 1406 return (h * 6 < 1 ? m1 + (m2 - m1) * h * 6 : h < 0.5 ? m2 : h * 3 < 2 ? m1 + (m2 - m1) * (2 / 3 - h) * 6 : m1) * 255 + 0.5 | 0; 1407 }, 1408 /** 1409 * @private Parses a color (like #9F0, #FF9900, rgb(255,51,153) or hsl(108, 50%, 10%)) into an array with 3 elements for red, green, and blue or if toHSL parameter is true, it will populate the array with hue, saturation, and lightness values. If a relative value is found in an hsl() or hsla() string, it will preserve those relative prefixes and all the values in the array will be strings instead of numbers (in all other cases it will be populated with numbers). 1410 * @param {(string|number)} v The value the should be parsed which could be a string like #9F0 or rgb(255,102,51) or rgba(255,0,0,0.5) or it could be a number like 0xFF00CC or even a named color like red, blue, purple, etc. 1411 * @param {(boolean)} toHSL If true, an hsl() or hsla() value will be returned instead of rgb() or rgba() 1412 * @return {Array.<number>} An array containing red, green, and blue (and optionally alpha) in that order, or if the toHSL parameter was true, the array will contain hue, saturation and lightness (and optionally alpha) in that order. Always numbers unless there's a relative prefix found in an hsl() or hsla() string and toHSL is true. 1413 */ 1414 _parseColor = _CSSPlugin.parseColor = function (v, toHSL) { 1415 var a, r, g, b, h, s, l, max, min, d, wasHSL; 1416 if (!v) { 1417 a = _colorLookup.black; 1418 } else if (typeof v === "number") { 1419 a = [v >> 16, v >> 8 & 255, v & 255]; 1420 } else { 1421 if (v.charAt(v.length - 1) === ",") { 1422 //sometimes a trailing comma is included and we should chop it off (typically from a comma-delimited list of values like a textShadow:"2px 2px 2px blue, 5px 5px 5px rgb(255,0,0)" - in this example "blue," has a trailing comma. We could strip it out inside parseComplex() but we'd need to do it to the beginning and ending values plus it wouldn't provide protection from other potential scenarios like if the user passes in a similar value. 1423 v = v.substr(0, v.length - 1); 1424 } 1425 if (_colorLookup[v]) { 1426 a = _colorLookup[v]; 1427 } else if (v.charAt(0) === "#") { 1428 if (v.length === 4) { 1429 //for shorthand like #9F0 1430 r = v.charAt(1); 1431 g = v.charAt(2); 1432 b = v.charAt(3); 1433 v = "#" + r + r + g + g + b + b; 1434 } 1435 v = parseInt(v.substr(1), 16); 1436 a = [v >> 16, v >> 8 & 255, v & 255]; 1437 } else if (v.substr(0, 3) === "hsl") { 1438 a = wasHSL = v.match(_numExp); 1439 if (!toHSL) { 1440 h = Number(a[0]) % 360 / 360; 1441 s = Number(a[1]) / 100; 1442 l = Number(a[2]) / 100; 1443 g = l <= 0.5 ? l * (s + 1) : l + s - l * s; 1444 r = l * 2 - g; 1445 if (a.length > 3) { 1446 a[3] = Number(a[3]); 1447 } 1448 a[0] = _hue(h + 1 / 3, r, g); 1449 a[1] = _hue(h, r, g); 1450 a[2] = _hue(h - 1 / 3, r, g); 1451 } else if (v.indexOf("=") !== -1) { 1452 //if relative values are found, just return the raw strings with the relative prefixes in place. 1453 return v.match(_relNumExp); 1454 } 1455 } else { 1456 a = v.match(_numExp) || _colorLookup.transparent; 1457 } 1458 a[0] = Number(a[0]); 1459 a[1] = Number(a[1]); 1460 a[2] = Number(a[2]); 1461 if (a.length > 3) { 1462 a[3] = Number(a[3]); 1463 } 1464 } 1465 if (toHSL && !wasHSL) { 1466 r = a[0] / 255; 1467 g = a[1] / 255; 1468 b = a[2] / 255; 1469 max = Math.max(r, g, b); 1470 min = Math.min(r, g, b); 1471 l = (max + min) / 2; 1472 if (max === min) { 1473 h = s = 0; 1474 } else { 1475 d = max - min; 1476 s = l > 0.5 ? d / (2 - max - min) : d / (max + min); 1477 h = max === r ? (g - b) / d + (g < b ? 6 : 0) : max === g ? (b - r) / d + 2 : (r - g) / d + 4; 1478 h *= 60; 1479 } 1480 a[0] = h + 0.5 | 0; 1481 a[1] = s * 100 + 0.5 | 0; 1482 a[2] = l * 100 + 0.5 | 0; 1483 } 1484 return a; 1485 }, 1486 _formatColors = function _formatColors(s, toHSL) { 1487 var colors = s.match(_colorExp) || [], 1488 charIndex = 0, 1489 parsed = "", 1490 i, 1491 color, 1492 temp; 1493 if (!colors.length) { 1494 return s; 1495 } 1496 for (i = 0; i < colors.length; i++) { 1497 color = colors[i]; 1498 temp = s.substr(charIndex, s.indexOf(color, charIndex) - charIndex); 1499 charIndex += temp.length + color.length; 1500 color = _parseColor(color, toHSL); 1501 if (color.length === 3) { 1502 color.push(1); 1503 } 1504 parsed += temp + (toHSL ? "hsla(" + color[0] + "," + color[1] + "%," + color[2] + "%," + color[3] : "rgba(" + color.
1504join(",")) + ")"; 1505 } 1506 return parsed + s.substr(charIndex); 1507 }, 1508 _colorExp = "(?:\\b(?:(?:rgb|rgba|hsl|hsla)\\(.+?\\))|\\B#(?:[0-9a-f]{3}){1,2}\\b"; //we'll dynamically build this Regular Expression to conserve file size. After building it, it will be able to find rgb(), rgba(), # (hexadecimal), and named color values like red, blue, purple, etc. 1509 1510 for (p in _colorLookup) { 1511 _colorExp += "|" + p + "\\b"; 1512 } 1513 _colorExp = new RegExp(_colorExp + ")", "gi"); 1514 _CSSPlugin.colorStringFilter = function (a) { 1515 var combined = a[0] + " " + a[1], 1516 toHSL; 1517 if (_colorExp.test(combined)) { 1518 toHSL = combined.indexOf("hsl(") !== -1 || combined.indexOf("hsla(") !== -1; 1519 a[0] = _formatColors(a[0], toHSL); 1520 a[1] = _formatColors(a[1], toHSL); 1521 } 1522 _colorExp.lastIndex = 0; 1523 }; 1524 if (!TweenLite.defaultStringFilter) { 1525 TweenLite.defaultStringFilter = _CSSPlugin.colorStringFilter; 1526 } 1527 1528 /** 1529 * @private Returns a formatter function that handles taking a string (or number in some cases) and returning a consistently formatted one in terms of delimiters, quantity of values, etc. For example, we may get boxShadow values defined as "0px red" or "0px 0px 10px rgb(255,0,0)" or "0px 0px 20px 20px #F00" and we need to ensure that what we get back is described with 4 numbers and a color. This allows us to feed it into the _parseComplex() method and split the values up appropriately. The neat thing about this _getFormatter() function is that the dflt defines a pattern as well as a default, so for example, _getFormatter("0px 0px 0px 0px #777", true) not only sets the default as 0px for all distances and #777 for the color, but also sets the pattern such that 4 numbers and a color will always get returned. 1530 * @param {!string} dflt The default value and pattern to follow. So "0px 0px 0px 0px #777" will ensure that 4 numbers and a color will always get returned. 1531 * @param {boolean=} clr If true, the values should be searched for color-related data. For example, boxShadow values typically contain a color whereas borderRadius don't. 1532 * @param {boolean=} collapsible If true, the value is a top/left/right/bottom style one that acts like margin or padding, where if only one value is received, it's used for all 4; if 2 are received, the first is duplicated for 3rd (bottom) and the 2nd is duplicated for the 4th spot (left), etc. 1533 * @return {Function} formatter function 1534 */ 1535 var _getFormatter = function _getFormatter(dflt, clr, collapsible, multi) { 1536 if (dflt == null) { 1537 return function (v) { 1538 return v; 1539 }; 1540 } 1541 var dColor = clr ? (dflt.match(_colorExp) || [""])[0] : "", 1542 dVals = dflt.split(dColor).join("").match(_valuesExp) || [], 1543 pfx = dflt.substr(0, dflt.indexOf(dVals[0])), 1544 sfx = dflt.charAt(dflt.length - 1) === ")" ? ")" : "", 1545 delim = dflt.indexOf(" ") !== -1 ? " " : ",", 1546 numVals = dVals.length, 1547 dSfx = numVals > 0 ? dVals[0].replace(_numExp, "") : "", 1548 _formatter2; 1549 if (!numVals) { 1550 return function (v) { 1551 return v; 1552 }; 1553 } 1554 if (clr) { 1555 _formatter2 = function formatter(v) { 1556 var color, vals, i, a; 1557 if (typeof v === "number") { 1558 v += dSfx; 1559 } else if (multi && _commasOutsideParenExp.test(v)) { 1560 a = v.replace(_commasOutsideParenExp, "|").split("|"); 1561 for (i = 0; i < a.length; i++) { 1562 a[i] = _formatter2(a[i]); 1563 } 1564 return a.join(","); 1565 } 1566 color = (v.match(_colorExp) || [dColor])[0]; 1567 vals = v.split(color).join("").match(_valuesExp) || []; 1568 i = vals.length; 1569 if (numVals > i--) { 1570 while (++i < numVals) { 1571 vals[i] = collapsible ? vals[(i - 1) / 2 | 0] : dVals[i]; 1572 } 1573 } 1574 return pfx + vals.join(delim) + delim + color + sfx + (v.indexOf("inset") !== -1 ? " inset" : ""); 1575 }; 1576 return _formatter2; 1577 } 1578 _formatter2 = function _formatter(v) { 1579 var vals, a, i; 1580 if (typeof v === "number") { 1581 v += dSfx; 1582 } else if (multi && _commasOutsideParenExp.test(v)) { 1583 a = v.replace(_commasOutsideParenExp, "|").split("|"); 1584 for (i = 0; i < a.length; i++) { 1585 a[i] = _formatter2(a[i]); 1586 } 1587 return a.join(","); 1588 } 1589 vals = v.match(_valuesExp) || []; 1590 i = vals.length; 1591 if (numVals > i--) { 1592 while (++i < numVals) { 1593 vals[i] = collapsible ? vals[(i - 1) / 2 | 0] : dVals[i]; 1594 } 1595 } 1596 return pfx + vals.join(delim) + sfx; 1597 }; 1598 return _formatter2; 1599 }, 1600 /** 1601 * @private returns a formatter function that's used for edge-related values like marginTop, marginLeft, paddingBottom, paddingRight, etc. Just pass a comma-delimited list of property names related to the edges. 1602 * @param {!string} props a comma-delimited list of property names in order from top to left, like "marginTop,marginRight,marginBottom,marginLeft" 1603 * @return {Function} a formatter function 1604 */ 1605 _getEdgeParser = function _getEdgeParser(props) { 1606 props = props.split(","); 1607 return function (t, e, p, cssp, pt, plugin, vars) { 1608 var a = (e + "").split(" "), 1609 i; 1610 vars = {}; 1611 for (i = 0; i < 4; i++) { 1612 vars[props[i]] = a[i] = a[i] || a[(i - 1) / 2 >> 0]; 1613 } 1614 return cssp.parse(t, vars, pt, plugin); 1615 }; 1616 }, 1617 // @private used when other plugins must tween values first, like BezierPlugin or ThrowPropsPlugin, etc. That plugin's setRatio() gets called first so that the values are updated, and then we loop through the MiniPropTweens which handle copying the values into their appropriate slots so that they can then be applied correctly in the main CSSPlugin setRatio() method. Remember, we typically create a proxy object that has a bunch of uniquely-named properties that we feed to the sub-plugin and it does its magic normally, and then we must interpret those values and apply them to the css because often numbers must get combined/concatenated, suffixes added, etc. to work with css, like boxShadow could have 4 values plus a color. 1618 _setPluginRatio = _internals._setPluginRatio = function (v) { 1619 this.plugin.setRatio(v); 1620 var d = this.data, 1621 proxy = d.proxy, 1622 mpt = d.firstMPT, 1623 min = 0.000001, 1624 val, 1625 pt, 1626 i, 1627 str, 1628 p; 1629 while (mpt) { 1630 val = proxy[mpt.v]; 1631 if (mpt.r) { 1632 val = Math.round(val); 1633 } else if (val < min && val > -min) { 1634 val = 0; 1635 } 1636 mpt.t[mpt.p] = val; 1637 mpt = mpt._next; 1638 } 1639 if (d.autoRotate) { 1640 d.autoRotate.rotation = d.mod ? d.mod(proxy.rotation, this.t) : proxy.rotation; //special case for ModifyPlugin to hook into an auto-rotating bezier 1641 } 1642 //at the end, we must set the CSSPropTween's "e" (end) value dynamically here because that's what is used in the final setRatio() method. Same for "b" at the beginning. 1643 if (v === 1 || v === 0) { 1644 mpt = d.firstMPT; 1645 p = v === 1 ? "e" : "b"; 1646 while (mpt) { 1647 pt = mpt.t; 1648 if (!pt.type) { 1649 pt[p] = pt.s + pt.xs0; 1650 } else if (pt.type === 1) { 1651 str = pt.xs0 + pt.s + pt.xs1; 1652 for (i = 1; i < pt.l; i++) { 1653 str += pt["xn" + i] + pt["xs" + (i + 1)]; 1654 } 1655 pt[p] = str; 1656 } 1657 mpt = mpt._next; 1658 } 1659 } 1660 }, 1661 /** 1662 * @private @constructor Used by a few SpecialProps to hold important values for proxies. For example, _parseToProxy() creates a MiniPropTween instance for each property that must get tweened on the proxy, and we record the original property name as well as the unique one we create for the proxy, plus whether or not the value needs to be roun
1662ded plus the original value. 1663 * @param {!Object} t target object whose property we're tweening (often a CSSPropTween) 1664 * @param {!string} p property name 1665 * @param {(number|string|object)} v value 1666 * @param {MiniPropTween=} next next MiniPropTween in the linked list 1667 * @param {boolean=} r if true, the tweened value should be rounded to the nearest integer 1668 */ 1669 MiniPropTween = function MiniPropTween(t, p, v, next, r) { 1670 this.t = t; 1671 this.p = p; 1672 this.v = v; 1673 this.r = r; 1674 if (next) { 1675 next._prev = this; 1676 this._next = next; 1677 } 1678 }, 1679 /** 1680 * @private Most other plugins (like BezierPlugin and ThrowPropsPlugin and others) can only tween numeric values, but CSSPlugin must accommodate special values that have a bunch of extra data (like a suffix or strings between numeric values, etc.). For example, boxShadow has values like "10px 10px 20px 30px rgb(255,0,0)" which would utterly confuse other plugins. This method allows us to split that data apart and grab only the numeric data and attach it to uniquely-named properties of a generic proxy object ({}) so that we can feed that to virtually any plugin to have the numbers tweened. However, we must also keep track of which properties from the proxy go with which CSSPropTween values and instances. So we create a linked list of MiniPropTweens. Each one records a target (the original CSSPropTween), property (like "s" or "xn1" or "xn2") that we're tweening and the unique property name that was used for the proxy (like "boxShadow_xn1" and "boxShadow_xn2") and whether or not they need to be rounded. That way, in the _setPluginRatio() method we can simply copy the values over from the proxy to the CSSPropTween instance(s). Then, when the main CSSPlugin setRatio() method runs and applies the CSSPropTween values accordingly, they're updated nicely. So the external plugin tweens the numbers, _setPluginRatio() copies them over, and setRatio() acts normally, applying css-specific values to the element. 1681 * This method returns an object that has the following properties:
1682 * - proxy: a generic object containing the starting values for all the properties that will be tweened by the external plugin. This is what we feed to the external _onInitTween() as the target 1683 * - end: a generic object containing the ending values for all the properties that will be tweened by the external plugin. This is what we feed to the external plugin's _onInitTween() as the destination values 1684 * - firstMPT: the first MiniPropTween in the linked list 1685 * - pt: the first CSSPropTween in the linked list that was created when parsing. If shallow is true, this linked list will NOT attach to the one passed into the _parseToProxy() as the "pt" (4th) parameter. 1686 * @param {!Object} t target object to be tweened 1687 * @param {!(Object|string)} vars the object containing the information about the tweening values (typically the end/destination values) that should be parsed 1688 * @param {!CSSPlugin} cssp The CSSPlugin instance 1689 * @param {CSSPropTween=} pt the next CSSPropTween in the linked list 1690 * @param {TweenPlugin=} plugin the external TweenPlugin instance that will be handling tweening the numeric values 1691 * @param {boolean=} shallow if true, the resulting linked list from the parse will NOT be attached to the CSSPropTween that was passed in as the "pt" (4th) parameter. 1692 * @return An object containing the following properties: proxy, end, firstMPT, and pt (see above for descriptions) 1693 */ 1694 _parseToProxy = _internals._parseToProxy = function (t, vars, cssp, pt, plugin, shallow) { 1695 var bpt = pt, 1696 start = {}, 1697 end = {}, 1698 transform = cssp._transform, 1699 oldForce = _forcePT, 1700 i, 1701 p, 1702 xp, 1703 mpt, 1704 firstPT; 1705 cssp._transform = null; 1706 _forcePT = vars; 1707 pt = firstPT = cssp.parse(t, vars, pt, plugin); 1708 _forcePT = oldForce; 1709 //break off from the linked list so the new ones are isolated. 1710 if (shallow) { 1711 cssp._transform = transform; 1712 if (bpt) { 1713 bpt._prev = null; 1714 if (bpt._prev) { 1715 bpt._prev._next = null; 1716 } 1717 } 1718 } 1719 while (pt && pt !== bpt) { 1720 if (pt.type <= 1) { 1721 p = pt.p; 1722 end[p] = pt.s + pt.c; 1723 start[p] = pt.s; 1724 if (!shallow) { 1725 mpt = new MiniPropTween(pt, "s", p, mpt, pt.r); 1726 pt.c = 0; 1727 } 1728 if (pt.type === 1) { 1729 i = pt.l; 1730 while (--i > 0) { 1731 xp = "xn" + i; 1732 p = pt.p + "_" + xp; 1733 end[p] = pt.data[xp]; 1734 start[p] = pt[xp]; 1735 if (!shallow) { 1736 mpt = new MiniPropTween(pt, xp, p, mpt, pt.rxp[xp]); 1737 } 1738 } 1739 } 1740 } 1741 pt = pt._next; 1742 } 1743 return { 1744 proxy: start, 1745 end: end, 1746 firstMPT: mpt, 1747 pt: firstPT 1748 }; 1749 }, 1750 /** 1751 * @constructor Each property that is tweened has at least one CSSPropTween associated with it. These instances store important information like the target, property, starting value, amount of change, etc. They can also optionally have a number of "extra" strings and numeric values named xs1, xn1, xs2, xn2, xs3, xn3, etc. where "s" indicates string and "n" indicates number. These can be pieced together in a complex-value tween (type:1) that has alternating types of data like a string, number, string, number, etc. For example, boxShadow could be "5px 5px 8px rgb(102, 102, 51)". In that value, there are 6 numbers that may need to tween and then pieced back together into a string again with spaces, suffixes, etc. xs0 is special in that it stores the suffix for standard (type:0) tweens, -OR- the first string (prefix) in a complex-value (type:1) CSSPropTween -OR- it can be the non-tweening value in a type:-1 CSSPropTween. We do this to conserve memory. 1752 * CSSPropTweens have the following optional properties as well (not defined through the constructor): 1753 * - l: Length in terms of the number of extra properties that the CSSPropTween has (default: 0). For example, for a boxShadow we may need to tween 5 numbers in which case l would be 5; Keep in mind that the start/end values for the first number that's tweened are always stored in the s and c properties to conserve memory. All additional values thereafter are stored in xn1, xn2, etc. 1754 * - xfirst: The first instance of any sub-CSSPropTweens that are tweening properties of this instance. For example, we may split up a boxShadow tween so that there's a main CSSPropTween of type:1 that has various xs* and xn* values associated with the h-shadow, v-shadow, blur, color, etc. Then we spawn a CSSPropTween for each of those that has a higher priority and runs BEFORE the main CSSPropTween so that the values are all set by the time it needs to re-assemble them. The xfirst gives us an easy way to identify the first one in that chain which typically ends at the main one (because they're all prepende to the linked list) 1755 * - plugin: The TweenPlugin instance that will handle the tweening of any complex values. For example, sometimes we don't want to use normal subt
1755weens (like xfirst refers to) to tween the values - we might want ThrowPropsPlugin or BezierPlugin some other plugin to do the actual tweening, so we create a plugin instance and store a reference here. We need this reference so that if we get a request to round values or disable a tween, we can pass along that request. 1756 * - data: Arbitrary data that needs to be stored with the CSSPropTween. Typically if we're going to have a plugin handle the tweening of a complex-value tween, we create a generic object that stores the END values that we're tweening to and the CSSPropTween's xs1, xs2, etc. have the starting values. We store that object as data. That way, we can simply pass that object to the plugin and use the CSSPropTween as the target. 1757 * - setRatio: Only used for type:2 tweens that require custom functionality. In this case, we call the CSSPropTween's setRatio() method and pass the ratio each time the tween updates. This isn't quite as efficient as doing things directly in the CSSPlugin's setRatio() method, but it's very convenient and flexible. 1758 * @param {!Object} t Target object whose property will be tweened. Often a DOM element, but not always. It could be anything. 1759 * @param {string} p Property to tween (name). For example, to tween element.width, p would be "width". 1760 * @param {number} s Starting numeric value 1761 * @param {number} c Change in numeric value over the course of the entire tween. For example, if element.width starts at 5 and should end at 100, c would be 95. 1762 * @param {CSSPropTween=} next The next CSSPropTween in the linked list. If one is defined, we will define its _prev as the new instance, and the new instance's _next will be pointed at it. 1763 * @param {number=} type The type of CSSPropTween where -1 = a non-tweening value, 0 = a standard simple tween, 1 = a complex value (like one that has multiple numbers in a comma- or space-delimited string like border:"1px solid red"), and 2 = one that uses a custom setRatio function that does all of the work of applying the values on each update. 1764 * @param {string=} n Name of the property that should be used for overwriting purposes which is typically the same as p but not always. For example, we may need to create a subtween for the 2nd part of a "clip:rect(...)" tween in which case "p" might be xs1 but "n" is still "clip" 1765 * @param {boolean=} r If true, the value(s) should be rounded 1766 * @param {number=} pr Priority in the linked list order. Higher priority CSSPropTweens will be updated before lower priority ones. The default priority is 0. 1767 * @param {string=} b Beginning value. We store this to ensure that it is EXACTLY what it was when the tween began without any risk of interpretation issues. 1768 * @param {string=} e Ending value. We store this to ensure that it is EXACTLY what the user defined at the end of the tween without any risk of interpretation issues. 1769 */ 1770 CSSPropTween = _internals.CSSPropTween = function (t, p, s, c, next, type, n, r, pr, b, e) { 1771 this.t = t; //target 1772 this.p = p; //property 1773 this.s = s; //starting value 1774 this.c = c; //change value 1775 this.n = n || p; //name that this CSSPropTween should be associated to (usually the same as p, but not always - n is what overwriting looks at) 1776 if (!(t instanceof CSSPropTween)) { 1777 _overwriteProps.push(this.n); 1778 } 1779 this.r = r; //round (boolean) 1780 this.type = type || 0; //0 = normal tween, -1 = non-tweening (in which case xs0 will be applied to the target's property, like tp.t[tp.p] = tp.xs0), 1 = complex-value SpecialProp, 2 = custom setRatio() that does all the work 1781 if (pr) { 1782 this.pr = pr; 1783 _hasPriority = true; 1784 } 1785 this.b = b === undefined ? s : b; 1786 this.e = e === undefined ? s + c : e; 1787 if (next) { 1788 this._next = next; 1789 next._prev = this; 1790 } 1791 }, 1792 _addNonTweeningNumericPT = function _addNonTweeningNumericPT(target, prop, start, end, next, overwriteProp) { 1793 //cleans up some code redundancies and helps minification. Just a fast way to add a NUMERIC non-tweening CSSPropTween
1794 var pt = new CSSPropTween(target, prop, start, end - start, next, -1, overwriteProp); 1795 pt.b = start; 1796 pt.e = pt.xs0 = end; 1797 return pt; 1798 }, 1799 /** 1800 * Takes a target, the beginning value and ending value (as strings) and parses them into a CSSPropTween (possibly with child CSSPropTweens) that accommodates multiple numbers, colors, comma-delimited values, etc. For example: 1801 * sp.parseComplex(element, "boxShadow", "5px 10px 20px rgb(255,102,51)", "0px 0px 0px red", true, "0px 0px 0px rgb(0,0,0,0)", pt); 1802 * It will walk through the beginning and ending values (which should be in the same format with the same number and type of values) and figure out which parts are numbers, what strings separate the numeric/tweenable values, and then create the CSSPropTweens accordingly. If a plugin is defined, no child CSSPropTweens will be created. Instead, the ending values will be stored in the "data" property of the returned CSSPropTween like: {s:-5, xn1:-10, xn2:-20, xn3:255, xn4:0, xn5:0} so that it can be fed to any other plugin and it'll be plain numeric tweens but the recomposition of the complex value will be handled inside CSSPlugin's setRatio(). 1803 * If a setRatio is defined, the type of the CSSPropTween will be set to 2 and recomposition of the values will be the responsibility of that method. 1804 * 1805 * @param {!Object} t Target whose property will be tweened 1806 * @param {!string} p Property that will be tweened (its name, like "left" or "backgroundColor" or "boxShadow") 1807 * @param {string} b Beginning value 1808 * @param {string} e Ending value 1809 * @param {boolean} clrs If true, the value could contain a color value like "rgb(255,0,0)" or "#F00" or "red". The default is false, so no colors will be recognized (a performance optimization) 1810 * @param {(string|number|Object)} dflt The default beginning value that should be used if no valid beginning value is defined or if the number of values inside the complex beginning and ending values don't match 1811 * @param {?CSSPropTween} pt CSSPropTween instance that is the current head of the linked list (we'll prepend to this). 1812 * @param {number=} pr Priority in the linked list order. Higher priority properties will be updated before lower priority ones. The default priority is 0. 1813 * @param {TweenPlugin=} plugin If a plugin should handle the tweening of extra properties, pass the plugin instance here. If one is defined, then NO subtweens will be created for any extra properties (the properties will be created - just not additional CSSPropTween instances to tween them) because the plugin is expected to do so. However, the end values WILL be populated in the "data" property, like {s:100, xn1:50, xn2:300} 1814 * @param {function(number)=} setRatio If values should be set in a custom function instead of being pieced together in a type:1 (complex-value) CSSPropTween, define that custom function here. 1815 * @return {CSSPropTween} The first CSSPropTween in the linked list which includes the new one(s) added by the parseComplex() call. 1816 */ 1817 _parseComplex = _CSSPlugin.parseComplex = function (t, p, b, e, clrs, dflt, pt, pr, plugin, setRatio) { 1818 //DEBUG: _log("parseComplex: "+p+", b: "+b+", e: "+e); 1819 b = b || dflt || ""; 1820 if (typeof e === "function") { 1821 e = e(_index, _target); 1822 } 1823 pt = new CSSPropTween(t, p, 0, 0, pt, setRatio ? 2 : 1, null, false, pr, b, e); 1824 e += ""; //ensures it's a string 1825 if (clrs && _colorExp.test(e + b)) { 1826 //if colors are found, normalize the formatting to rgba() or hsla(). 1827 e = [b, e]; 1828 _CSSPlugin.colorStringFilter(e); 1829 b = e[0]; 1830 e = e[1]; 1831 } 1832 var ba = b.split(", ").join(",").split(" "), 1833 //beginning array 1834 ea = e.split(", ").join(",").split(" "), 1835 //ending array 1836 l = ba.length, 1837 autoRound = _autoRound !== false, 1838 i, 1839 xi, 1840 ni, 1841 bv, 1842 ev, 1843 bnums, 1844 enums, 1845 bn, 1846 hasAlpha, 1847 temp, 1848 cv, 1849 str, 1850 useHSL; 1851 if (e.indexOf(",") !== -1 || b.indexOf(",") !== -1) { 1852 if ((e + b).indexOf("rgb") !== -1 || (e + b).indexOf("hsl") !== -1) { 1853 //keep rgb(), rgba(), hsl(), and hsla() values together! (remember, we're splitting on spaces) 1854 ba = ba.join(" ").replace(_commasOutsideParenExp, ", ").split(" "); 1855 ea = ea.join(" ").replace(_commasOutsideParenExp, ", ").split(" "); 1856 } else { 1857 ba = ba.join(" ").split(",").join(", ").split(" "); 1858 ea = ea.join(" ").split(",").join(", ").split(" "); 1859 } 1860 l = ba.length; 1861 } 1862 if (l !== ea.length) { 1863 //DEBUG: _log("mismatched formatting detected on " + p + " (" + b + " vs " + e + ")"); 1864 ba = (dflt || "").split(" "); 1865 l = ba.length; 1866 } 1867 pt.plugin = plugin; 1868 pt.setRatio = setRatio; 1869 _colorExp.lastIndex = 0; 1870 for (i = 0; i < l; i++) { 1871 bv = ba[i]; 1872 ev = ea[i]; 1873 bn = parseFloat(bv); 1874 //if the value begins with a number (most common). It's fine if it has a suffix like px 1875 if (bn || bn === 0) { 1876 pt.appendXtra("", bn, _parseChange(ev, bn), ev.replace(_relNumExp, ""), autoRound && ev.indexOf("px") !== -1, true); 1877 1878 //if the value is a color 1879 } else if (clrs && _colorExp.test(bv)) { 1880 str = ev.indexOf(")") + 1; 1881 str = ")" + (str ? ev.substr(str) : ""); //if there's a comma or ) at the end, retain it. 1882 useHSL = ev.indexOf("hsl") !== -1 && _supportsOpacity; 1883 temp = ev; //original string value so we can look for any prefix later. 1884 bv = _parseColor(bv, useHSL); 1885 ev = _parseColor(ev, useHSL); 1886 hasAlpha = bv.length + ev.length > 6; 1887 if (hasAlpha && !_supportsOpacity && ev[3] === 0) { 1888 //older versions of IE don't support rgba(), so if the destination alpha is 0, just use "transparent" for the end color 1889 pt["xs" + pt.l] += pt.l ? " transparent" : "transparent";
1890 pt.e = pt.e.split(ea[i]).join("transparent"); 1891 } else { 1892 if (!_supportsOpacity) { 1893 //old versions of IE don't support rgba(). 1894 hasAlpha = false; 1895 } 1896 if (useHSL) { 1897 pt.appendXtra(temp.substr(0, temp.indexOf("hsl")) + (hasAlpha ? "hsla(" : "hsl("), bv[0], _parseChange(ev[0], bv[0]), ",", false, true).appendXtra("", bv[1], _parseChange(ev[1], bv[1]), "%,", false).appendXtra("", bv[2], _parseChange(ev[2], bv[2]), hasAlpha ? "%," : "%" + str, false); 1898 } else { 1899 pt.appendXtra(temp.substr(0, temp.indexOf("rgb")) + (hasAlpha ? "rgba(" : "rgb("), bv[0], ev[0] - bv[0], ",", true, true).appendXtra("", bv[1], ev[1] - bv[1], ",", true).appendXtra("", bv[2], ev[2] - bv[2], hasAlpha ? "," : str, true); 1900 } 1901 if (hasAlpha) { 1902 bv = bv.length < 4 ? 1 : bv[3]; 1903 pt.appendXtra("", bv, (ev.length < 4 ? 1 : ev[3]) - bv, str, false); 1904 } 1905 } 1906 _colorExp.lastIndex = 0; //otherwise the test() on the RegExp could move the lastIndex and taint future results. 1907 } else { 1908 bnums = bv.match(_numExp); //gets each group of numbers in the beginning value string and drops them into an array 1909 1910 //if no number is found, treat it as a non-tweening value and just append the string to the current xs. 1911 if (!bnums) { 1912 pt["xs" + pt.l] += pt.l || pt["xs" + pt.l] ? " " + ev : ev; 1913 1914 //loop through all the numbers that are found and construct the extra values on the pt. 1915 } else { 1916 enums = ev.match(_relNumExp); //get each group of numbers in the end value string and drop them into an array. We allow relative values too, like +=50 or -=.5 1917 if (!enums || enums.length !== bnums.length) { 1918 //DEBUG: _log("mismatched formatting detected on " + p + " (" + b + " vs " + e + ")"); 1919 return pt; 1920 } 1921 ni = 0; 1922 for (xi = 0; xi < bnums.length; xi++) { 1923 cv = bnums[xi]; 1924 temp = bv.indexOf(cv, ni); 1925 pt.appendXtra(bv.substr(ni, temp - ni), Number(cv), _parseChange(enums[xi], cv), "", autoRound && bv.substr(temp + cv.length, 2) === "px", xi === 0); 1926 ni = temp + cv.length; 1927 } 1928 pt["xs" + pt.l] += bv.substr(ni); 1929 } 1930 } 1931 } 1932 //if there are relative values ("+=" or "-=" prefix), we need to adjust the ending value to eliminate the prefixes and combine the values properly. 1933 if (e.indexOf("=") !== -1) if (pt.data) { 1934 str = pt.xs0 + pt.data.s; 1935 for (i = 1; i < pt.l; i++) { 1936 str += pt["xs" + i] + pt.data["xn" + i]; 1937 } 1938 pt.e = str + pt["xs" + i]; 1939 } 1940 if (!pt.l) { 1941 pt.type = -1; 1942 pt.xs0 = pt.e; 1943 } 1944 return pt.xfirst || pt; 1945 }, 1946 i = 9; 1947 p = CSSPropTween.prototype; 1948 p.l = p.pr = 0; //length (number of extra properties like xn1, xn2, xn3, etc. 1949 while (--i > 0) { 1950 p["xn" + i] = 0; 1951 p["xs" + i] = ""; 1952 } 1953 p.xs0 = ""; 1954 p._next = p._prev = p.xfirst = p.data = p.plugin = p.setRatio = p.rxp = null; 1955 1956 /** 1957 * Appends and extra tweening value to a CSSPropTween and automatically manages any prefix and suffix strings. The first extra value is stored in the s and c of the main CSSPropTween instance, but thereafter any extras are stored in the xn1, xn2, xn3, etc. The prefixes and suffixes are stored in the xs0, xs1, xs2, etc. properties. For example, if I walk through a clip value like "rect(10px, 5px, 0px, 20px)", the values would be stored like this: 1958 * xs0:"rect(", s:10, xs1:"px, ", xn1:5, xs2:"px, ", xn2:0, xs3:"px, ", xn3:20, xn4:"px)" 1959 * And they'd all get joined together when the CSSPlugin renders (in the setRatio() method). 1960 * @param {string=} pfx Prefix (if any) 1961 * @param {!number} s Starting value 1962 * @param {!number} c Change in numeric value over the course of the entire tween. For example, if the start is 5 and the end is 100, the change would be 95. 1963 * @param {string=} sfx Suffix (if any) 1964 * @param {boolean=} r Round (if true). 1965 * @param {boolean=} pad If true, this extra value should be separated by the previous one by a space. If there is no previous extra and pad is true, it will automatically drop the space. 1966 * @return {CSSPropTween} returns itself so that multiple methods can be chained together. 1967 */ 1968 p.appendXtra = function (pfx, s, c, sfx, r, pad) { 1969 var pt = this, 1970 l = pt.l; 1971 pt["xs" + l] += pad && (l || pt["xs" + l]) ? " " + pfx : pfx || ""; 1972 if (!c) if (l !== 0 && !pt.plugin) { 1973 //typically we'll combine non-changing values right into the xs to optimize performance, but we don't combine them when there's a plugin that will be tweening the values because it may depend on the values being split apart, like for a bezier, if a value doesn't change between the first and second iteration but then it does on the 3rd, we'll run into trouble because there's no xn slot for that value! 1974 pt["xs" + l] += s + (sfx || ""); 1975 return pt; 1976 } 1977 pt.l++; 1978 pt.type = pt.setRatio ? 2 : 1; 1979 pt["xs" + pt.l] = sfx || ""; 1980 if (l > 0) { 1981 pt.data["xn" + l] = s + c; 1982 pt.rxp["xn" + l] = r; //round extra property (we need to tap into this in the _parseToProxy() method) 1983 pt["xn" + l] = s; 1984 if (!pt.plugin) { 1985 pt.xfirst = new CSSPropTween(pt, "xn" + l, s, c, pt.xfirst || pt, 0, pt.n, r, pt.pr); 1986 pt.xfirst.xs0 = 0; //just to ensure that the property stays numeric which helps modern browsers speed up processing. Remember, in the setRatio() method, we do pt.t[pt.p] = val + pt.xs0 so if pt.xs0 is "" (the default), it'll cast the end value as a string. When a property is a number sometimes and a string sometimes, it prevents the compiler from locking in the data type, slowing things down slightly. 1987 } 1988 return pt; 1989 } 1990 pt.data = { 1991 s: s + c 1992 }; 1993 pt.rxp = {}; 1994 pt.s = s; 1995 pt.c = c; 1996 pt.r = r; 1997 return pt; 1998 }; 1999 2000 /** 2001 * @constructor A SpecialProp is basically a css property that needs to be treated in a non-standard way, like if it may contain a complex value like boxShadow:"5px 10px 15px rgb(255, 102, 51)" or if it is associated with another plugin like ThrowPropsPlugin or BezierPlugin. Every SpecialProp is associated with a particular property name like "boxShadow" or "throwProps" or "bezier" and it will intercept those values in the vars object that's passed to the CSSPlugin and handle them accordingly. 2002 * @param {!string} p Property name (like "boxShadow" or "throwProps") 2003 * @param {Object=}
2003 options An object containing any of the following configuration options: 2004 * - defaultValue: the default value 2005 * - parser: A function that should be called when the associated property name is found in the vars. This function should return a CSSPropTween instance and it should ensure that it is properly inserted into the linked list. It will receive 4 paramters: 1) The target, 2) The value defined in the vars, 3) The CSSPlugin instance (whose _firstPT should be used for the linked list), and 4) A computed style object if one was calculated (this is a speed optimization that allows retrieval of starting values quicker) 2006 * - formatter: a function that formats any value received for this special property (for example, boxShadow could take "5px 5px red" and format it to "5px 5px 0px 0px red" so that both the beginning and ending values have a common order and quantity of values.) 2007 * - prefix: if true, we'll determine whether or not this property requires a vendor prefix (like Webkit or Moz or ms or O) 2008 * - color: set this to true if the value for this SpecialProp may contain color-related values like rgb(), rgba(), etc. 2009 * - priority: priority in the linked list order. Higher priority SpecialProps will be updated before lower priority ones. The default priority is 0. 2010 * - multi: if true, the formatter should accommodate a comma-delimited list of values, like boxShadow could have multiple boxShadows listed out. 2011 * - collapsible: if true, the formatter should treat the value like it's a top/right/bottom/left value that could be collapsed, like "5px" would apply to all, "5px, 10px" would use 5px for top/bottom and 10px for right/left, etc. 2012 * - keyword: a special keyword that can [optionally] be found inside the value (like "inset" for boxShadow). This allows us to validate beginning/ending values to make sure they match (if the keyword is found in one, it'll be added to the other for consistency by default). 2013 */ 2014 var SpecialProp = function SpecialProp(p, options) { 2015 options = options || {}; 2016 this.p = options.prefix ? _checkPropPrefix(p) || p : p; 2017 _specialProps[p] = _specialProps[this.p] = this; 2018 this.format = options.formatter || _getFormatter(options.defaultValue, options.color, options.collapsible, options.multi); 2019 if (options.parser) { 2020 this.parse = options.parser; 2021 } 2022 this.clrs = options.color; 2023 this.multi = options.multi; 2024 this.keyword = options.keyword; 2025 this.dflt = options.defaultValue; 2026 this.pr = options.priority || 0; 2027 }, 2028 //shortcut for creating a new SpecialProp that can accept multiple properties as a comma-delimited list (helps minification). dflt can be an array for multiple values (we don't do a comma-delimited list because the default value may contain commas, like rect(0px,0px,0px,0px)). We attach this method to the SpecialProp class/object instead of using a private _createSpecialProp() method so that we can tap into it externally if necessary, like from another plugin. 2029 _registerComplexSpecialProp = _internals._registerComplexSpecialProp = function (p, options, defaults) { 2030 if (_typeof(options) !== "object") { 2031 options = { 2032 parser: defaults 2033 }; //to make backwards compatible with older versions of BezierPlugin and ThrowPropsPlugin 2034 } 2035 var a = p.split(","), 2036 d = options.defaultValue, 2037 i, 2038 temp; 2039 defaults = defaults || [d]; 2040 for (i = 0; i < a.length; i++) { 2041 options.prefix = i === 0 && options.prefix; 2042 options.defaultValue = defaults[i] || d; 2043 temp = new SpecialProp(a[i], options); 2044 } 2045 }, 2046 //creates a placeholder special prop for a plugin so that the property gets caught the first time a tween of it is attempted, and at that time it makes the plugin register itself, thus taking over for all future tweens of that property. This allows us to not mandate that things load in a particular order and it also allows us to log() an error that informs the user when they attempt to tween an external plugin-related property without loading its .js file. 2047 _registerPluginProp = _internals._registerPluginProp = function (p) { 2048 if (!_specialProps[p]) { 2049 var pluginName = p.charAt(0).toUpperCase() + p.substr(1) + "Plugin"; 2050 _registerComplexSpecialProp(p, { 2051 parser: function parser(t, e, p, cssp, pt, plugin, vars) { 2052 var pluginClass = _globals.com.greensock.plugins[pluginName]; 2053 if (!pluginClass) { 2054 _log("Error: " + pluginName + " js file not loaded."); 2055 return pt; 2056 } 2057 pluginClass._cssRegister(); 2058 return _specialProps[p].parse(t, e, p, cssp, pt, plugin, vars); 2059 } 2060 }); 2061 } 2062 }; 2063 p = SpecialProp.prototype; 2064 2065 /** 2066 * Alias for _parseComplex() that automatically plugs in certain values for this SpecialProp, like its property name, whether or not colors should be sensed, the default value, and priority. It also looks for any keyword that the SpecialProp defines (like "inset" for boxSh
2066adow) and ensures that the beginning and ending values have the same number of values for SpecialProps where multi is true (like boxShadow and textShadow can have a comma-delimited list) 2067 * @param {!Object} t target element 2068 * @param {(string|number|object)} b beginning value 2069 * @param {(string|number|object)} e ending (destination) value 2070 * @param {CSSPropTween=} pt next CSSPropTween in the linked list 2071 * @param {TweenPlugin=} plugin If another plugin will be tweening the complex value, that TweenPlugin instance goes here. 2072 * @param {function=} setRatio If a custom setRatio() method should be used to handle this complex value, that goes here. 2073 * @return {CSSPropTween=} First CSSPropTween in the linked list 2074 */ 2075 p.parseComplex = function (t, b, e, pt, plugin, setRatio) { 2076 var kwd = this.keyword, 2077 i, 2078 ba, 2079 ea, 2080 l, 2081 bi, 2082 ei; 2083 //if this SpecialProp's value can contain a comma-delimited list of values (like boxShadow or textShadow), we must parse them in a special way, and look for a keyword (like "inset" for boxShadow) and ensure that the beginning and ending BOTH have it if the end defines it as such. We also must ensure that there are an equal number of values specified (we can't tween 1 boxShadow to 3 for example) 2084 if (this.multi) if (_commasOutsideParenExp.test(e) || _commasOutsideParenExp.test(b)) { 2085 ba = b.replace(_commasOutsideParenExp, "|").split("|"); 2086 ea = e.replace(_commasOutsideParenExp, "|").split("|"); 2087 } else if (kwd) { 2088 ba = [b]; 2089 ea = [e]; 2090 } 2091 if (ea) { 2092 l = ea.length > ba.length ? ea.length : ba.length; 2093 for (i = 0; i < l; i++) { 2094 b = ba[i] = ba[i] || this.dflt; 2095 e = ea[i] = ea[i] || this.dflt; 2096 if (kwd) { 2097 bi = b.indexOf(kwd); 2098 ei = e.indexOf(kwd); 2099 if (bi !== ei) { 2100 if (ei === -1) { 2101 //if the keyword isn't in the end value, remove it from the beginning one. 2102 ba[i] = ba[i].split(kwd).join(""); 2103 } else if (bi === -1) { 2104 //if the keyword isn't in the beginning, add it. 2105 ba[i] += " " + kwd; 2106 } 2107 } 2108 } 2109 } 2110 b = ba.join(", "); 2111 e = ea.join(", "); 2112 } 2113 return _parseComplex(t, this.p, b, e, this.clrs, this.dflt, pt, this.pr, plugin, setRatio); 2114 }; 2115 2116 /** 2117 * Accepts a target and end value and spits back a CSSPropTween that has been inserted into the CSSPlugin's linked list and conforms with all the conventions we use internally, like type:-1, 0, 1, or 2, setting up any extra property tweens, priority, etc. For example, if we have a boxShadow SpecialProp and call: 2118 * this._firstPT = sp.parse(element, "5px 10px 20px rgb(2550,102,51)", "boxShadow", this); 2119 * It should figure out the starting value of the element's boxShadow, compare it to the provided end value and create all the necessary CSSPropTweens of the appropriate types to tween the boxShadow. The CSSPropTween that gets spit back should already be inserted into the linked list (the 4th parameter is the current head, so prepend to that). 2120 * @param {!Object} t Target object whose property is being tweened 2121 * @param {Object} e End value as provided in the vars object (typically a string, but not always - like a throwProps would be an object). 2122 * @param {!string} p Property name 2123 * @param {!CSSPlugin} cssp The CSSPlugin instance that should be associated with this tween. 2124 * @param {?CSSPropTween} pt The CSSPropTween that is the current head of the linked list (we'll prepend to it) 2125 * @param {TweenPlugin=} plugin If a plugin will be used to tween the parsed value, this is the plugin instance. 2126 * @param {Object=} vars Original vars object that contains the data for parsing. 2127 * @return {CSSPropTween} The first CSSPropTween in the linked list which includes the new one(s) added by the parse() call. 2128 */ 2129 p.parse = function (t, e, p, cssp, pt, plugin, vars) { 2130 return this.parseComplex(t.style, this.format(_getStyle(t, this.p, _cs, false, this.dflt)), this.format(e), pt, plugin); 2131 }; 2132 2133 /** 2134 * Registers a special property that should be intercepted from any "css" objects defined in tweens. This allows you to handle them however you want without CSSPlugin doing it for you. The 2nd parameter should be a function that accepts 3 parameters: 2135 * 1) Target object whose property should be tweened (typically a DOM element) 2136 * 2) The end/destination value (could be a string, number, object, or whatever you want) 2137 * 3) The tween instance (you probably don't need to worry about this, but it can be useful for looking up information like the duration) 2138 * 2139 * Then, your function should return a function which will be called each time the tween gets rendered, passing a numeric "ratio" parameter to your function that indicates the change factor (usually between 0 and 1). For example: 2140 * 2141 * CSSPlugin.registerSpecialProp("myCustomProp", function(target, value, tween) { 2142 * var start = target.style.width;
2143 * return function(ratio) { 2144 * target.style.width = (start + value * ratio) + "px"; 2145 * console.log("set width to " + target.style.width); 2146 * } 2147 * }, 0); 2148 * 2149 * Then, when I do this tween, it will trigger my special property: 2150 * 2151 * TweenLite.to(element, 1, {css:{myCustomProp:100}}); 2152 * 2153 * In the example, of course, we're just changing the width, but you can do anything you want. 2154 * 2155 * @param {!string} name Property name (or comma-delimited list of property names) that should be intercepted and handled by your function. For example, if I define "myCustomProp", then it would handle that portion of the following tween: TweenLite.to(element, 1, {css:{myCustomProp:100}}) 2156 * @param {!function(Object, Object, Object, string):function(number)} onInitTween The function that will be called when a tween of this special property is performed. The function will receive 4 parameters: 1) Target object that should be tweened, 2) Value that was passed to the tween, 3) The tween instance itself (rarely used), and 4) The property name that's being tweened. Your function should return a function that should be called on every update of the tween. That function will receive a single parameter that is a "change factor" value (typically between 0 and 1) indicating the amount of change as a ratio. You can use this to determine how to set the values appropriately in your function. 2157 * @param {number=} priority Priority that helps the engine determine the order in which to set the properties (default: 0). Higher priority properties will be updated before lower priority ones. 2158 */ 2159 _CSSPlugin.registerSpecialProp = function (name, onInitTween, priority) { 2160 _registerComplexSpecialProp(name, { 2161 parser: function parser(t, e, p, cssp, pt, plugin, vars) { 2162 var rv = new CSSPropTween(t, p, 0, 0, pt, 2, p, false, priority); 2163 rv.plugin = plugin; 2164 rv.setRatio = onInitTween(t, e, cssp._tween, p); 2165 return rv; 2166 }, 2167 priority: priority 2168 }); 2169 }; 2170 2171 //transform-related methods and properties 2172 _CSSPlugin.useSVGTransformAttr = true; //Safari and Firefox both have some rendering bugs when applying CSS transforms to SVG elements, so default to using the "transform" attribute instead (users can override this). 2173 var _transformProps = "scaleX,scaleY,scaleZ,x,y,z,skewX,skewY,rotation,rotationX,rotationY,perspective,xPercent,yPercent".split(","), 2174 _transformProp = _checkPropPrefix("transform"), 2175 //the Javascript (camelCase) transform property, like msTransform, WebkitTransform, MozTransform, or OTransform. 2176 _transformPropCSS = _prefixCSS + "transform", 2177 _transformOriginProp = _checkPropPrefix("transformOrigin"), 2178 _supports3D = _checkPropPrefix("perspective") !== null, 2179 Transform = _internals.Transform = function () { 2180 this.perspective = parseFloat(_CSSPlugin.defaultTransformPerspective) || 0; 2181 this.force3D = _CSSPlugin.defaultForce3D === false || !_supports3D ? false : _CSSPlugin.defaultForce3D || "auto"; 2182 }, 2183 _SVGElement = _gsScope.SVGElement, 2184 _useSVGTransformAttr, 2185 //Some browsers (like Firefox and IE) don't honor transform-origin properly in SVG elements, so we need to manually adjust the matrix accordingly. We feature detect here rather than always doing the conversion for certain browsers because they may fix the problem at some point in the future. 2186 2187 _createSVG = function _createSVG(type, container, attributes) { 2188 var element = _doc.createElementNS("http://www.w3.org/2000/svg", type), 2189 reg = /([a-z])([A-Z])/g, 2190 p; 2191 for (p in attributes) { 2192 element.setAttributeNS(null, p.replace(reg, "$1-$2").toLowerCase(), attributes[p]); 2193 } 2194 container.appendChild(element); 2195 return element; 2196 }, 2197 _docElement = _doc.documentElement || {}, 2198 _forceSVGTransformAttr = function () { 2199 //IE and Android stock don't support CSS transforms on SVG elements, so we must write them to the "transform" attribute. We populate this variable in the _parseTransform() method, and only if/when we come across an SVG element 2200 var force = _ieVers || /Android/i.test(_agent) && !_gsScope.chrome, 2201 svg, 2202 rect, 2203 width; 2204 if (_doc.createElementNS && !force) { 2205 //IE8 and earlier doesn't support SVG anyway 2206 svg = _createSVG("svg", _docElement); 2207 rect = _createSVG("rect", svg, { 2208 width: 100, 2209 height: 50, 2210 x: 100 2211 }); 2212 width = rect.getBoundingClientRect().width; 2213 rect.style[_transformOriginProp] = "50% 50%"; 2214 rect.style[_transformProp] = "scaleX(0.5)"; 2215 force = width === rect.getBoundingClientRect().width && !(_is
2215Firefox && _supports3D); //note: Firefox fails the test even though it does support CSS transforms in 3D. Since we can't push 3D stuff into the transform attribute, we force Firefox to pass the test here (as long as it does truly support 3D). 2216 _docElement.removeChild(svg); 2217 } 2218 return force; 2219 }(), 2220 _parseSVGOrigin = function _parseSVGOrigin(e, local, decoratee, absolute, smoothOrigin, skipRecord) { 2221 var tm = e._gsTransform, 2222 m = _getMatrix(e, true), 2223 v, 2224 x, 2225 y, 2226 xOrigin, 2227 yOrigin, 2228 a, 2229 b, 2230 c, 2231 d, 2232 tx, 2233 ty, 2234 determinant, 2235 xOriginOld, 2236 yOriginOld; 2237 if (tm) { 2238 xOriginOld = tm.xOrigin; //record the original values before we alter them. 2239 yOriginOld = tm.yOrigin; 2240 } 2241 if (!absolute || (v = absolute.split(" ")).length < 2) { 2242 b = e.getBBox(); 2243 if (b.x === 0 && b.y === 0 && b.width + b.height === 0) { 2244 //some browsers (like Firefox) misreport the bounds if the element has zero width and height (it just assumes it's at x:0, y:0), thus we need to manually grab the position in that case. 2245 b = { 2246 x: parseFloat(e.hasAttribute("x") ? e.getAttribute("x") : e.hasAttribute("cx") ? e.getAttribute("cx") : 0) || 0, 2247 y: parseFloat(e.hasAttribute("y") ? e.getAttribute("y") : e.hasAttribute("cy") ? e.getAttribute("cy") : 0) || 0, 2248 width: 0, 2249 height: 0 2250 }; 2251 } 2252 local = _parsePosition2(local).split(" "); 2253 v = [(local[0].indexOf("%") !== -1 ? parseFloat(local[0]) / 100 * b.width : parseFloat(local[0])) + b.x, (local[1].indexOf("%") !== -1 ? parseFloat(local[1]) / 100 * b.height : parseFloat(local[1])) + b.y]; 2254 } 2255 decoratee.xOrigin = xOrigin = parseFloat(v[0]); 2256 decoratee.yOrigin = yOrigin = parseFloat(v[1]); 2257 if (absolute && m !== _identity2DMatrix) { 2258 //if svgOrigin is being set, we must invert the matrix and determine where the absolute point is, factoring in the current transforms. Otherwise, the svgOrigin would be based on the element's non-transformed position on the canvas. 2259 a = m[0]; 2260 b = m[1]; 2261 c = m[2]; 2262 d = m[3]; 2263 tx = m[4]; 2264 ty = m[5]; 2265 determinant = a * d - b * c; 2266 if (determinant) { 2267 //if it's zero (like if scaleX and scaleY are zero), skip it to avoid errors with dividing by zero. 2268 x = xOrigin * (d / determinant) + yOrigin * (-c / determinant) + (c * ty - d * tx) / determinant; 2269 y = xOrigin * (-b / determinant) + yOrigin * (a / determinant) - (a * ty - b * tx) / determinant; 2270 xOrigin = decoratee.xOrigin = v[0] = x; 2271 yOrigin = decoratee.yOrigin = v[1] = y; 2272 } 2273 } 2274 if (tm) { 2275 //avoid jump when transformOrigin is changed - adjust the x/y values accordingly 2276 if (skipRecord) { 2277 decoratee.xOffset = tm.xOffset; 2278 decoratee.yOffset = tm.yOffset; 2279 tm = decoratee; 2280 } 2281 if (smoothOrigin || smoothOrigin !== false && _CSSPlugin.defaultSmoothOrigin !== false) { 2282 x = xOrigin - xOriginOld; 2283 y = yOrigin - yOriginOld; 2284 //originally, we simply adjusted the x and y values, but that would cause problems if, for example, you created a rotational tween part-way through an x/y tween. Managing the offset in a separate variable gives us ultimate flexibility. 2285 //tm.x -= x - (x * m[0] + y * m[2]); 2286 //tm.y -= y - (x * m[1] + y * m[3]); 2287 tm.xOffset += x * m[0] + y * m[2] - x; 2288 tm.yOffset += x * m[1] + y * m[3] - y; 2289 } else { 2290 tm.xOffset = tm.yOffset = 0; 2291 } 2292 } 2293 if (!skipRecord) { 2294 e.setAttribute("data-svg-origin", v.join(" ")); 2295 } 2296 }, 2297 _getBBoxHack2 = function _getBBoxHack(swapIfPossible) { 2298 //works around issues in some browsers (like Firefox) that don't correctly report getBBox() on SVG elements inside a <defs> element and/or <mask>. We try creating an SVG, adding it to the documentElement and toss the element in there so that it's definitely part of the rendering tree, then grab the bbox and if it works, we actually swap out the original getBBox() method for our own that does these extra steps whenever getBBox is needed. This helps ensure that performance is optimal (only do all these extra steps when absolutely necessary...most elements don't need it). 2299 var svg = _createElement("svg", this.ownerSVGElement && this.ownerSVGElement.getAttribute("xmlns") || "http://www.w3.org/2000/svg"), 2300 oldParent = this.parentNode, 2301 oldSibling = this.nextSibling, 2302 oldCSS = this.style.cssText, 2303 bbox; 2304 _docElement.appendChild(svg); 2305 svg.appendChild(this); 2306 this.style.display = "block"; 2307 if (swapIfPossible) { 2308 try { 2309 bbox = this.getBBox(); 2310 this._originalGetBBox = this.getBBox; 2311 this.getBBox = _getBBoxHack2; 2312 } catch (e) {} 2313 } else if (this._originalGetBBox) { 2314 bbox = this._originalGetBBox(); 2315 } 2316 if (oldSibling) { 2317 oldParent.insertBefore(this, oldSibling); 2318 } else { 2319 oldParent.appendChild(this); 2320 } 2321 _docElement.removeChild(svg); 2322 this.style.cssText = oldCSS; 2323 return bbox; 2324 }, 2325 _getBBox = function _getBBox(e) { 2326 try { 2327 return e.getBBox(); //Firefox throws errors if you try calling getBBox() on an SVG element that's not rendered (like in a <symbol> or <defs>). https://bugzilla.mozilla.org/show_bug.cgi?id=612118 2328 } catch (error) { 2329 return _getBBoxHack2.call(e, true); 2330 } 2331 }, 2332 _isSVG = function _isSVG(e) { 2333 //reports if the element is an SVG on which getBBox() actually works 2334 return !!(_SVGElement && e.getCTM && (!e.parentNode || e.ownerSVGElement) && _getBBox(e)); 2335 }, 2336 _identity2DMatrix = [1, 0, 0, 1, 0, 0], 2337 _getMatrix = function _getMatrix(e, force2D) { 2338 var tm = e._gsTransform || new Transform(), 2339 rnd = 100000, 2340 style = e.style, 2341 isDefault, 2342 s, 2343 m, 2344 n, 2345 dec, 2346 none; 2347 if (_transformProp) { 2348 s = _getStyle(e, _transformPropCSS, null, true); 2349 } else if (e.currentStyle) { 2350 //for older versions of IE, we need to interpret the filter portion that is in the format: progid:DXImageTransform.Microsoft.Matrix(M11=6.123233995736766e-17, M12=-1, M21=1, M22=6.123233995736766e-17, sizingMethod='auto expand') Notice that we need to swap b and c compared to a normal matrix. 2351 s = e.currentStyle.filter.match(_ieGetMatrixExp); 2352 s = s && s.length === 4 ? [s[0].substr(4), Number(s[2].substr(4)), Number(s[1].substr(4)), s[3].substr(4), tm.x || 0, tm.y || 0].join(",") : ""; 2353 }
2354 isDefault = !s || s === "none" || s === "matrix(1, 0, 0, 1, 0, 0)"; 2355 if (_transformProp && ((none = !_getComputedStyle(e) || _getComputedStyle(e).display === "none") || !e.parentNode)) { 2356 //note: Firefox returns null for getComputedStyle() if the element is in an iframe that has display:none. https://bugzilla.mozilla.org/show_bug.cgi?id=548397 2357 if (none) { 2358 //browsers don't report transforms accurately unless the element is in the DOM and has a display value that's not "none". Firefox and Microsoft browsers have a partial bug where they'll report transforms even if display:none BUT not any percentage-based values like translate(-50%, 8px) will be reported as if it's translate(0, 8px). 2359 n = style.display; 2360 style.display = "block"; 2361 } 2362 if (!e.parentNode) { 2363 dec = 1; //flag 2364 _docElement.appendChild(e); 2365 } 2366 s = _getStyle(e, _transformPropCSS, null, true); 2367 isDefault = !s || s === "none" || s === "matrix(1, 0, 0, 1, 0, 0)"; 2368 if (n) { 2369 style.display = n; 2370 } else if (none) { 2371 _removeProp(style, "display"); 2372 } 2373 if (dec) { 2374 _docElement.removeChild(e); 2375 } 2376 } 2377 if (tm.svg || e.getCTM && _isSVG(e)) { 2378 if (isDefault && (style[_transformProp] + "").indexOf("matrix") !== -1) { 2379 //some browsers (like Chrome 40) don't correctly report transforms that are applied inline on an SVG element (they don't get included in the computed style), so we double-check here and accept matrix values 2380 s = style[_transformProp]; 2381 isDefault = 0; 2382 } 2383 m = e.getAttribute("transform"); 2384 if (isDefault && m) { 2385 m = e.transform.baseVal.consolidate().matrix; //ensures that even complex values like "translate(50,60) rotate(135,0,0)" are parsed because it mashes it into a matrix. 2386 s = "matrix(" + m.a + "," + m.b + "," + m.c + "," + m.d + "," + m.e + "," + m.f + ")"; 2387 isDefault = 0; 2388 } 2389 } 2390 if (isDefault) { 2391 return _identity2DMatrix; 2392 } 2393 //split the matrix values out into an array (m for matrix) 2394 m = (s || "").match(_numExp) || []; 2395 i = m.length; 2396 while (--i > -1) { 2397 n = Number(m[i]); 2398 m[i] = (dec = n - (n |= 0)) ? (dec * rnd + (dec < 0 ? -0.5 : 0.5) | 0) / rnd + n : n; //convert strings to Numbers and round to 5 decimal places to avoid issues with tiny numbers. Roughly 20x faster than Number.toFixed(). We also must make sure to round before dividing so that values like 0.9999999999 become 1 to avoid glitches in browser rendering and interpretation of flipped/rotated 3D matrices. And don't just multiply the number by rnd, floor it, and then divide by rnd because the bitwise operations max out at a 32-bit signed integer, thus it could get clipped at a relatively low value (like 22,000.00000 for example). 2399 } 2400 return force2D && m.length > 6 ? [m[0], m[1], m[4], m[5], m[12], m[13]] : m; 2401 }, 2402 /** 2403 * Parses the transform values for an element, returning an object with x, y, z, scaleX, scaleY, scaleZ, rotation, rotationX, rotationY, skewX, and skewY properties. Note: by default (for performance reasons), all skewing is combined into skewX and rotation but skewY still has a place in the transform object so that we can record how much of the skew is attributed to skewX vs skewY. Remember, a skewY of 10 looks the same as a rotation of 10 and skewX of -10. 2404 * @param {!Object} t target element 2405 * @param {Object=} cs computed style object (optional) 2406 * @param {boolean=} rec if true, the transform values will be recorded to the target element's _gsTransform object, like target._gsTransform = {x:0, y:0, z:0, scaleX:1...} 2407 * @param {boolean=} parse if true, we'll ignore any _gsTransform values that already exist on the element, and force a reparsing of the css (calculated style) 2408 * @return {object}
2408 object containing all of the transform properties/values like {x:0, y:0, z:0, scaleX:1...} 2409 */ 2410 _getTransform = _internals.getTransform = function (t, cs, rec, parse) { 2411 if (t._gsTransform && rec && !parse) { 2412 return t._gsTransform; //if the element already has a _gsTransform, use that. Note: some browsers don't accurately return the calculated style for the transform (particularly for SVG), so it's almost always safest to just use the values we've already applied rather than re-parsing things. 2413 } 2414 var tm = rec ? t._gsTransform || new Transform() : new Transform(), 2415 invX = tm.scaleX < 0, 2416 //in order to interpret things properly, we need to know if the user applied a negative scaleX previously so that we can adjust the rotation and skewX accordingly. Otherwise, if we always interpret a flipped matrix as affecting scaleY and the user only wants to tween the scaleX on multiple sequential tweens, it would keep the negative scaleY without that being the user's intent. 2417 min = 0.00002, 2418 rnd = 100000, 2419 zOrigin = _supports3D ? parseFloat(_getStyle(t, _transformOriginProp, cs, false, "0 0 0").split(" ")[2]) || tm.zOrigin || 0 : 0, 2420 defaultTransformPerspective = parseFloat(_CSSPlugin.defaultTransformPerspective) || 0, 2421 m, 2422 i, 2423 scaleX, 2424 scaleY, 2425 rotation, 2426 skewX; 2427 tm.svg = !!(t.getCTM && _isSVG(t)); 2428 if (tm.svg) { 2429 _parseSVGOrigin(t, _getStyle(t, _transformOriginProp, cs, false, "50% 50%") + "", tm, t.getAttribute("data-svg-origin")); 2430 _useSVGTransformAttr = _CSSPlugin.useSVGTransformAttr || _forceSVGTransformAttr; 2431 } 2432 m = _getMatrix(t); 2433 if (m !== _identity2DMatrix) { 2434 if (m.length === 16) { 2435 //we'll only look at these position-related 6 variables first because if x/y/z all match, it's relatively safe to assume we don't need to re-parse everything which risks losing important rotational information (like rotationX:180 plus rotationY:180 would look the same as rotation:180 - there's no way to know for sure which direction was taken based solely on the matrix3d() values) 2436 var a11 = m[0], 2437 a21 = m[1], 2438 a31 = m[2], 2439 a41 = m[3], 2440 a12 = m[4], 2441 a22 = m[5], 2442 a32 = m[6], 2443 a42 = m[7], 2444 a13 = m[8], 2445 a23 = m[9], 2446 a33 = m[10], 2447 a14 = m[12], 2448 a24 = m[13], 2449 a34 = m[14], 2450 a43 = m[11], 2451 angle = Math.atan2(a32, a33), 2452 t1, 2453 t2, 2454 t3, 2455 t4, 2456 cos, 2457 sin; 2458 //we manually compensate for non-zero z component of transformOrigin to work around bugs in Safari 2459 if (tm.zOrigin) { 2460 a34 = -tm.zOrigin; 2461 a14 = a13 * a34 - m[12]; 2462 a24 = a23 * a34 - m[13]; 2463 a34 = a33 * a34 + tm.zOrigin - m[14]; 2464 } 2465 //note for possible future consolidation: rotationX: Math.atan2(a32, a33), rotationY: Math.atan2(-a31, Math.sqrt(a33 * a33 + a32 * a32)), rotation: Math.atan2(a21, a11), skew: Math.atan2(a12, a22). However, it doesn't seem to be quite as reliable as the full-on backwards rotation procedure. 2466 tm.rotationX = angle * _RAD2DEG; 2467 //rotationX 2468 if (angle) { 2469 cos = Math.cos(-angle); 2470 sin = Math.sin(-angle); 2471 t1 = a12 * cos + a13 * sin; 2472 t2 = a22 * cos + a23 * sin; 2473 t3 = a32 * cos + a33 * sin; 2474 a13 = a12 * -sin + a13 * cos; 2475 a23 = a22 * -sin + a23 * cos; 2476 a33 = a32 * -sin + a33 * cos; 2477 a43 = a42 * -sin + a43 * cos; 2478 a12 = t1; 2479 a22 = t2; 2480 a32 = t3; 2481 } 2482 //rotationY 2483 angle = Math.atan2(-a31, a33); 2484 tm.rotationY = angle * _RAD2DEG; 2485 if (angle) { 2486 cos = Math.cos(-angle); 2487 sin = Math.sin(-angle); 2488 t1 = a11 * cos - a13 * sin; 2489 t2 = a21 * cos - a23 * sin; 2490 t3 = a31 * cos - a33 * sin; 2491 a23 = a21 * sin + a23 * cos; 2492 a33 = a31 * sin + a33 * cos; 2493 a43 = a41 * sin + a43 * cos; 2494 a11 = t1; 2495 a21 = t2; 2496 a31 = t3; 2497 } 2498 //rotationZ 2499 angle = Math.atan2(a21, a11); 2500 tm.rotation = angle * _RAD2DEG; 2501 if (angle) { 2502 cos = Math.cos(angle); 2503 sin = Math.sin(angle); 2504 t1 = a11 * cos + a21 * sin; 2505 t2 = a12 * cos + a22 * sin; 2506 t3 = a13 * cos + a23 * sin; 2507 a21 = a21 * cos - a11 * sin; 2508 a22 = a22 * cos - a12 * sin; 2509 a23 = a23 * cos - a13 * sin; 2510 a11 = t1; 2511 a12 = t2; 2512 a13 = t3; 2513 } 2514 if (tm.rotationX && Math.abs(tm.rotationX) + Math.abs(tm.rotation) > 359.9) { 2515 //when rotationY is set, it will often be parsed as 180 degrees different than it should be, and rotationX and rotation both being 180 (it looks the same), so we adjust for that here. 2516 tm.rotationX = tm.rotation = 0; 2517 tm.rotationY = 180 - tm.rotationY; 2518 } 2519 2520 //skewX 2521 angle = Math.atan2(a12, a22); 2522 2523 //scales 2524 tm.scaleX = (Math.sqrt(a11 * a11 + a21 * a21 + a31 * a31) * rnd + 0.5 | 0) / rnd; 2525 tm.scaleY = (Math.sqrt(a22 * a22 + a32 * a32) * rnd + 0.5 | 0) / rnd; 2526 tm.scaleZ = (Math.sqrt(a13 * a13 + a23 * a23 + a33 * a33) * rnd + 0.5 | 0) / rnd; 2527 a11 /= tm.scaleX; 2528 a12 /= tm.scaleY; 2529 a21 /= tm.scaleX; 2530 a22 /= tm.scaleY; 2531 if (Math.abs(angle) > min) { 2532 tm.skewX = angle * _RAD2DEG; 2533 a12 = 0;
2533 //unskews 2534 if (tm.skewType !== "simple") { 2535 tm.scaleY *= 1 / Math.cos(angle); //by default, we compensate the scale based on the skew so that the element maintains a similar proportion when skewed, so we have to alter the scaleY here accordingly to match the default (non-adjusted) skewing that CSS does (stretching more and more as it skews). 2536 } 2537 } else { 2538 tm.skewX = 0; 2539 } 2540 2541 /* //for testing purposes 2542 var transform = "matrix3d(", 2543 comma = ",", 2544 zero = "0"; 2545 a13 /= tm.scaleZ; 2546 a23 /= tm.scaleZ; 2547 a31 /= tm.scaleX; 2548 a32 /= tm.scaleY; 2549 a33 /= tm.scaleZ; 2550 transform += ((a11 < min && a11 > -min) ? zero : a11) + comma + ((a21 < min && a21 > -min) ? zero : a21) + comma + ((a31 < min && a31 > -min) ? zero : a31); 2551 transform += comma + ((a41 < min && a41 > -min) ? zero : a41) + comma + ((a12 < min && a12 > -min) ? zero : a12) + comma + ((a22 < min && a22 > -min) ? zero : a22); 2552 transform += comma + ((a32 < min && a32 > -min) ? zero : a32) + comma + ((a42 < min && a42 > -min) ? zero : a42) + comma + ((a13 < min && a13 > -min) ? zero : a13); 2553 transform += comma + ((a23 < min && a23 > -min) ? zero : a23) + comma + ((a33 < min && a33 > -min) ? zero : a33) + comma + ((a43 < min && a43 > -min) ? zero : a43) + comma; 2554 transform += a14 + comma + a24 + comma + a34 + comma + (tm.perspective ? (1 + (-a34 / tm.perspective)) : 1) + ")"; 2555 console.log(transform); 2556 document.querySelector(".test").style[_transformProp] = transform; 2557 */ 2558 2559 tm.perspective = a43 ? 1 / (a43 < 0 ? -a43 : a43) : 0; 2560 tm.x = a14; 2561 tm.y = a24; 2562 tm.z = a34; 2563 if (tm.svg) { 2564 tm.x -= tm.xOrigin - (tm.xOrigin * a11 - tm.yOrigin * a12); 2565 tm.y -= tm.yOrigin - (tm.yOrigin * a21 - tm.xOrigin * a22); 2566 } 2567 } else if (!_supports3D || parse || !m.length || tm.x !== m[4] || tm.y !== m[5] || !tm.rotationX && !tm.rotationY) { 2568 //sometimes a 6-element matrix is returned even when we performed 3D transforms, like if rotationX and rotationY are 180. In cases like this, we still need to honor the 3D transforms. If we just rely on the 2D info, it could affect how the data is interpreted, like scaleY might get set to -1 or rotation could get offset by 180 degrees. For example, do a TweenLite.to(element, 1, {css:{rotationX:180, rotationY:180}}) and then later, TweenLite.to(element, 1, {css:{rotationX:0}}) and without this conditional logic in place, it'd jump to a state of being unrotated when the 2nd tween starts. Then again, we need to honor the fact that the user COULD alter the transforms outside of CSSPlugin, like by manually applying new css, so we try to sense that by looking at x and y because if those changed, we know the changes were made outside CSSPlugin and we force a reinterpretation of the matrix values. Also, in Webkit browsers, if the element's "display" is "none", its calculated style value will always return empty, so if we've already recorded the values in the _gsTransform object, we'll just rely on those. 2569 var k = m.length >= 6, 2570 a = k ? m[0] : 1, 2571 b = m[1] || 0, 2572 c = m[2] || 0, 2573 d = k ? m[3] : 1; 2574 tm.x = m[4] || 0; 2575 tm.y = m[5] || 0; 2576 scaleX = Math.sqrt(a * a + b * b); 2577 scaleY = Math.sqrt(d * d + c * c); 2578 rotation = a || b ? Math.atan2(b, a) * _RAD2DEG : tm.rotation || 0; //note: if scaleX is 0, we cannot accurately measure rotation. Same for skewX with a scaleY of 0. Therefore, we default to the previously recorded value (or zero if that doesn't exist). 2579 skewX = c || d ? Math.atan2(c, d) * _RAD2DEG + rotation : tm.skewX || 0; 2580 tm.scaleX = scaleX; 2581 tm.scaleY = scaleY; 2582 tm.rotation = rotation; 2583 tm.skewX = skewX; 2584 if (_supports3D) { 2585 tm.rotationX = tm.rotationY = tm.z = 0; 2586 tm.perspective = defaultTransformPerspective; 2587 tm.scaleZ = 1; 2588 } 2589 if (tm.svg) { 2590 tm.x -= tm.xOrigin - (tm.xOrigin * a + tm.yOrigin * c); 2591 tm.y -= tm.yOrigin - (tm.xOrigin * b + tm.yOrigin * d); 2592 } 2593 } 2594 if (Math.abs(tm.skewX) > 90 && Math.abs(tm.skewX) < 270) { 2595 if (invX) { 2596 tm.scaleX *= -1; 2597 tm.skewX += tm.rotation <= 0 ? 180 : -180; 2598 tm.rotation += tm.rotation <= 0 ? 180 : -180; 2599 } else { 2600 tm.scaleY *= -1; 2601 tm.skewX += tm.skewX <= 0 ? 180 : -180; 2602 } 2603 } 2604 tm.zOrigin = zOrigin;
2605 //some browsers have a hard time with very small values like 2.4492935982947064e-16 (notice the "e-" towards the end) and would render the object slightly off. So we round to 0 in these cases. The conditional logic here is faster than calling Math.abs(). Also, browsers tend to render a SLIGHTLY rotated object in a fuzzy way, so we need to snap to exactly 0 when appropriate. 2606 for (i in tm) { 2607 if (tm[i] < min) if (tm[i] > -min) { 2608 tm[i] = 0; 2609 } 2610 } 2611 } 2612 //DEBUG: _log("parsed rotation of " + t.getAttribute("id")+": "+(tm.rotationX)+", "+(tm.rotationY)+", "+(tm.rotation)+", scale: "+tm.scaleX+", "+tm.scaleY+", "+tm.scaleZ+", position: "+tm.x+", "+tm.y+", "+tm.z+", perspective: "+tm.perspective+ ", origin: "+ tm.xOrigin+ ","+ tm.yOrigin); 2613 if (rec) { 2614 t._gsTransform = tm; //record to the object's _gsTransform which we use so that tweens can control individual properties independently (we need all the properties to accurately recompose the matrix in the setRatio() method) 2615 if (tm.svg) { 2616 //if we're supposed to apply transforms to the SVG element's "transform" attribute, make sure there aren't any CSS transforms applied or they'll override the attribute ones. Also clear the transform attribute if we're using CSS, just to be clean. 2617 if (_useSVGTransformAttr && t.style[_transformProp]) { 2618 TweenLite.delayedCall(0.001, function () { 2619 //if we apply this right away (before anything has rendered), we risk there being no transforms for a brief moment and it also interferes with adjusting the transformOrigin in a tween with immediateRender:true (it'd try reading the matrix and it wouldn't have the appropriate data in place because we just removed it). 2620 _removeProp(t.style, _transformProp); 2621 }); 2622 } else if (!_useSVGTransformAttr && t.getAttribute("transform")) { 2623 TweenLite.delayedCall(0.001, function () { 2624 t.removeAttribute("transform"); 2625 }); 2626 } 2627 } 2628 } 2629 return tm; 2630 }, 2631 //for setting 2D transforms in IE6, IE7, and IE8 (must use a "filter" to emulate the behavior of modern day browser transforms) 2632 _setIETransformRatio = function _setIETransformRatio(v) { 2633 var t = this.data, 2634 //refers to the element's _gsTransform object 2635 ang = -t.rotation * _DEG2RAD, 2636 skew = ang + t.skewX * _DEG2RAD, 2637 rnd = 100000, 2638 a = (Math.cos(ang) * t.scaleX * rnd | 0) / rnd, 2639 b = (Math.sin(ang) * t.scaleX * rnd | 0) / rnd, 2640 c = (Math.sin(skew) * -t.scaleY * rnd | 0) / rnd, 2641 d = (Math.cos(skew) * t.scaleY * rnd | 0) / rnd, 2642 style = this.t.style, 2643 cs = this.t.currentStyle, 2644 filters, 2645 val; 2646 if (!cs) { 2647 return; 2648 } 2649 val = b; //just for swapping the variables an inverting them (reused "val" to avoid creating another variable in memory). IE's filter matrix uses a non-standard matrix configuration (angle goes the opposite way, and b and c are reversed and inverted) 2650 b = -c; 2651 c = -val; 2652 filters = cs.filter; 2653 style.filter = ""; //remove filters so that we can accurately measure offsetWidth/offsetHeight 2654 var w = this.t.offsetWidth, 2655 h = this.t.offsetHeight, 2656 clip = cs.position !== "absolute", 2657 m = "progid:DXImageTransform.Microsoft.Matrix(M11=" + a + ", M12=" + b + ", M21=" + c + ", M22=" + d, 2658 ox = t.x + w * t.xPercent / 100, 2659 oy = t.y + h * t.yPercent / 100, 2660 dx, 2661 dy; 2662 2663 //if transformOrigin is being used, adjust the offset x and y 2664 if (t.ox != null) { 2665 dx = (t.oxp ? w * t.ox * 0.01 : t.ox) - w / 2; 2666 dy = (t.oyp ? h * t.oy * 0.01 : t.oy) - h / 2; 2667 ox += dx - (dx * a + dy * b); 2668 oy += dy - (dx * c + dy * d); 2669 } 2670 if (!clip) { 2671 m += ", sizingMethod='auto expand')"; 2672 } else { 2673 dx = w / 2; 2674 dy = h / 2; 2675 //translate to ensure that transformations occur around the correct origin (default is center). 2676 m += ", Dx=" + (dx - (dx * a + dy * b) + ox) + ", Dy=" + (dy - (dx * c + dy * d) + oy) + ")"; 2677 } 2678 if (filters.indexOf("DXImageTransform.Microsoft.Matrix(") !== -1) {
2679 style.filter = filters.replace(_ieSetMatrixExp, m); 2680 } else { 2681 style.filter = m + " " + filters; //we must always put the transform/matrix FIRST (before alpha(opacity=xx)) to avoid an IE bug that slices part of the object when rotation is applied with alpha. 2682 } 2683 2684 //at the end or beginning of the tween, if the matrix is normal (1, 0, 0, 1) and opacity is 100 (or doesn't exist), remove the filter to improve browser performance. 2685 if (v === 0 || v === 1) if (a === 1) if (b === 0) if (c === 0) if (d === 1) if (!clip || m.indexOf("Dx=0, Dy=0") !== -1) if (!_opacityExp.test(filters) || parseFloat(RegExp.$1) === 100) if (filters.indexOf("gradient(" && filters.indexOf("Alpha")) === -1) { 2686 style.removeAttribute("filter"); 2687 } 2688 2689 //we must set the margins AFTER applying the filter in order to avoid some bugs in IE8 that could (in rare scenarios) cause them to be ignored intermittently (vibration). 2690 if (!clip) { 2691 var mult = _ieVers < 8 ? 1 : -1, 2692 //in Internet Explorer 7 and before, the box model is broken, causing the browser to treat the width/height of the actual rotated filtered image as the width/height of the box itself, but Microsoft corrected that in IE8. We must use a negative offset in IE8 on the right/bottom 2693 marg, 2694 prop, 2695 dif; 2696 dx = t.ieOffsetX || 0; 2697 dy = t.ieOffsetY || 0; 2698 t.ieOffsetX = Math.round((w - ((a < 0 ? -a : a) * w + (b < 0 ? -b : b) * h)) / 2 + ox); 2699 t.ieOffsetY = Math.round((h - ((d < 0 ? -d : d) * h + (c < 0 ? -c : c) * w)) / 2 + oy); 2700 for (i = 0; i < 4; i++) { 2701 prop = _margins[i]; 2702 marg = cs[prop]; 2703 //we need to get the current margin in case it is being tweened separately (we want to respect that tween's changes) 2704 val = marg.indexOf("px") !== -1 ? parseFloat(marg) : _convertToPixels(this.t, prop, parseFloat(marg), marg.replace(_suffixExp, "")) || 0; 2705 if (val !== t[prop]) { 2706 dif = i < 2 ? -t.ieOffsetX : -t.ieOffsetY; //if another tween is controlling a margin, we cannot only apply the difference in the ieOffsets, so we essentially zero-out the dx and dy here in that case. We record the margin(s) later so that we can keep comparing them, making this code very flexible. 2707 } else { 2708 dif = i < 2 ? dx - t.ieOffsetX : dy - t.ieOffsetY; 2709 } 2710 style[prop] = (t[prop] = Math.round(val - dif * (i === 0 || i === 2 ? 1 : mult))) + "px"; 2711 } 2712 } 2713 }, 2714 /* translates a super small decimal to a string WITHOUT scientific notation 2715 _safeDecimal = function(n) { 2716 var s = (n < 0 ? -n : n) + "", 2717 a = s.split("e-"); 2718 return (n < 0 ? "-0." : "0.") + new Array(parseInt(a[1], 10) || 0).join("0") + a[0].split(".").join(""); 2719 }, 2720 */ 2721 2722 _setTransformRatio = _internals.set3DTransformRatio = _internals.setTransformRatio = function (v) { 2723 var t = this.data, 2724 //refers to the element's _gsTransform object 2725 style = this.t.style, 2726 angle = t.rotation, 2727 rotationX = t.rotationX, 2728 rotationY = t.rotationY, 2729 sx = t.scaleX, 2730 sy = t.scaleY, 2731 sz = t.scaleZ, 2732 x = t.x, 2733 y = t.y, 2734 z = t.z, 2735 isSVG = t.svg, 2736 perspective = t.perspective, 2737 force3D = t.force3D, 2738 skewY = t.skewY, 2739 skewX = t.skewX, 2740 t1, 2741 a11, 2742 a12, 2743 a13, 2744 a21, 2745 a22, 2746 a23, 2747 a31, 2748 a32, 2749 a33, 2750 a41, 2751 a42, 2752 a43, 2753 zOrigin, 2754 min, 2755 cos, 2756 sin, 2757 t2, 2758 transform, 2759 comma, 2760 zero, 2761 skew, 2762 rnd; 2763 if (skewY) { 2764 //for performance reasons, we combine all skewing into the skewX and rotation values. Remember, a skewY of 10 degrees looks the same as a rotation of 10 degrees plus a skewX of 10 degrees. 2765 skewX += skewY; 2766 angle += skewY; 2767 } 2768 2769 //check to see if we should render as 2D (and SVGs must use 2D when _useSVGTransformAttr is true) 2770 if (((v === 1 || v === 0) && force3D === "auto" && (this.tween._totalTime === this.tween._totalDuration || !this.tween._totalTime) || !force3D) && !z && !perspective && !rotationY && !rotationX && sz === 1 || _useSVGTransformAttr && isSVG || !_supports3D) { 2771 //on the final render (which could be 0 for a from tween), if there are no 3D aspects, render in 2D to free up memory and improve performance especially on mobile devices. Check the tween's totalTime/totalDuration too in order to make sure it doesn't happen between repeats if it's a repeating tween. 2772 2773 //2D 2774 if (angle || skewX || isSVG) { 2775 angle *= _DEG2RAD; 2776 skew = skewX * _DEG2RAD; 2777 rnd = 100000; 2778 a11 = Math.cos(angle) * sx; 2779 a21 = Math.sin(angle) * sx; 2780 a12 = Math.sin(angle - skew) * -sy;
2781 a22 = Math.cos(angle - skew) * sy; 2782 if (skew && t.skewType === "simple") { 2783 //by default, we compensate skewing on the other axis to make it look more natural, but you can set the skewType to "simple" to use the uncompensated skewing that CSS does 2784 t1 = Math.tan(skew - skewY * _DEG2RAD); 2785 t1 = Math.sqrt(1 + t1 * t1); 2786 a12 *= t1; 2787 a22 *= t1; 2788 if (skewY) { 2789 t1 = Math.tan(skewY * _DEG2RAD); 2790 t1 = Math.sqrt(1 + t1 * t1); 2791 a11 *= t1; 2792 a21 *= t1; 2793 } 2794 } 2795 if (isSVG) { 2796 x += t.xOrigin - (t.xOrigin * a11 + t.yOrigin * a12) + t.xOffset; 2797 y += t.yOrigin - (t.xOrigin * a21 + t.yOrigin * a22) + t.yOffset; 2798 if (_useSVGTransformAttr && (t.xPercent || t.yPercent)) { 2799 //The SVG spec doesn't support percentage-based translation in the "transform" attribute, so we merge it into the matrix to simulate it. 2800 min = this.t.getBBox(); 2801 x += t.xPercent * 0.01 * min.width; 2802 y += t.yPercent * 0.01 * min.height; 2803 } 2804 min = 0.000001; 2805 if (x < min) if (x > -min) { 2806 x = 0; 2807 } 2808 if (y < min) if (y > -min) { 2809 y = 0; 2810 } 2811 } 2812 transform = (a11 * rnd | 0) / rnd + "," + (a21 * rnd | 0) / rnd + "," + (a12 * rnd | 0) / rnd + "," + (a22 * rnd | 0) / rnd + "," + x + "," + y + ")"; 2813 if (isSVG && _useSVGTransformAttr) {
2814 this.t.setAttribute("transform", "matrix(" + transform); 2815 } else { 2816 //some browsers have a hard time with very small values like 2.4492935982947064e-16 (notice the "e-" towards the end) and would render the object slightly off. So we round to 5 decimal places. 2817 style[_transformProp] = (t.xPercent || t.yPercent ? "translate(" + t.xPercent + "%," + t.yPercent + "%) matrix(" : "matrix(") + transform; 2818 } 2819 } else { 2820 style[_transformProp] = (t.xPercent || t.yPercent ? "translate(" + t.xPercent + "%," + t.yPercent + "%) matrix(" : "matrix(") + sx + ",0,0," + sy + "," + x + "," + y + ")"; 2821 } 2822 return; 2823 } 2824 if (_isFirefox) { 2825 //Firefox has a bug (at least in v25) that causes it to render the transparent part of 32-bit PNG images as black when displayed inside an iframe and the 3D scale is very small and doesn't change sufficiently enough between renders (like if you use a Power4.easeInOut to scale from 0 to 1 where the beginning values only change a tiny amount to begin the tween before accelerating). In this case, we force the scale to be 0.00002 instead which is visually the same but works around the Firefox issue. 2826 min = 0.0001; 2827 if (sx < min && sx > -min) { 2828 sx = sz = 0.00002; 2829 } 2830 if (sy < min && sy > -min) { 2831 sy = sz = 0.00002; 2832 } 2833 if (perspective && !t.z && !t.rotationX && !t.rotationY) { 2834 //Firefox has a bug that causes elements to have an odd super-thin, broken/dotted black border on elements that have a perspective set but aren't utilizing 3D space (no rotationX, rotationY, or z). 2835 perspective = 0; 2836 } 2837 } 2838 if (angle || skewX) { 2839 angle *= _DEG2RAD; 2840 cos = a11 = Math.cos(angle); 2841 sin = a21 = Math.sin(angle); 2842 if (skewX) { 2843 angle -= skewX * _DEG2RAD; 2844 cos = Math.cos(angle); 2845 sin = Math.sin(angle); 2846 if (t.skewType === "simple") { 2847 //by default, we compensate skewing on the other axis to make it look more natural, but you can set the skewType to "simple" to use the uncompensated skewing that CSS does 2848 t1 = Math.tan((skewX - skewY) * _DEG2RAD); 2849 t1 = Math.sqrt(1 + t1 * t1); 2850 cos *= t1; 2851 sin *= t1; 2852 if (t.skewY) { 2853 t1 = Math.tan(skewY * _DEG2RAD); 2854 t1 = Math.sqrt(1 + t1 * t1); 2855 a11 *= t1; 2856 a21 *= t1; 2857 } 2858 } 2859 } 2860 a12 = -sin; 2861 a22 = cos; 2862 } else if (!rotationY && !rotationX && sz === 1 && !perspective && !isSVG) { 2863 //if we're only translating and/or 2D scaling, this is faster... 2864 style[_transformProp] = (t.xPercent || t.yPercent ? "translate(" + t.xPercent + "%," + t.yPercent + "%) translate3d(" : "translate3d(") + x + "px," + y + "px," + z + "px)" + (sx !== 1 || sy !== 1 ? " scale(" + sx + "," + sy + ")" : ""); 2865 return; 2866 } else { 2867 a11 = a22 = 1; 2868 a12 = a21 = 0; 2869 } 2870 // KEY INDEX AFFECTS a[row][column] 2871 // a11 0 rotation, rotationY, scaleX 2872 // a21 1 rotation, rotationY, scaleX 2873 // a31 2 rotationY, scaleX 2874 // a41 3 rotationY, scaleX 2875 // a12 4 rotation, skewX, rotationX, scaleY 2876 // a22 5 rotation, skewX, rotationX, scaleY 2877 // a32 6 rotationX, scaleY 2878 // a42 7 rotationX, scaleY 2879 // a13 8 rotationY, rotationX, scaleZ 2880 // a23 9 rotationY, rotationX, scaleZ 2881 // a33 10 rotationY, rotationX, scaleZ 2882 // a43 11 rotationY, rotationX, perspective, scaleZ 2883 // a14 12 x, zOrigin, svgOrigin 2884 // a24 13 y, zOrigin, svgOrigin 2885 // a34 14 z, zOrigin 2886 // a44 15 2887 // rotation: Math.atan2(a21, a11) 2888 // rotationY: Math.atan2(a13, a33) (or Math.atan2(a13, a11)) 2889 // rotationX: Math.atan2(a32, a33) 2890 a33 = 1; 2891 a13 = a23 = a31 = a32 = a41 = a42 = 0; 2892 a43 = perspective ? -1 / perspective : 0; 2893 zOrigin = t.zOrigin; 2894 min = 0.000001; //threshold below which browsers use scientific notation which w
2894on't work. 2895 comma = ","; 2896 zero = "0"; 2897 angle = rotationY * _DEG2RAD; 2898 if (angle) { 2899 cos = Math.cos(angle); 2900 sin = Math.sin(angle); 2901 a31 = -sin; 2902 a41 = a43 * -sin; 2903 a13 = a11 * sin; 2904 a23 = a21 * sin; 2905 a33 = cos; 2906 a43 *= cos; 2907 a11 *= cos; 2908 a21 *= cos; 2909 } 2910 angle = rotationX * _DEG2RAD; 2911 if (angle) { 2912 cos = Math.cos(angle); 2913 sin = Math.sin(angle); 2914 t1 = a12 * cos + a13 * sin; 2915 t2 = a22 * cos + a23 * sin; 2916 a32 = a33 * sin; 2917 a42 = a43 * sin; 2918 a13 = a12 * -sin + a13 * cos; 2919 a23 = a22 * -sin + a23 * cos; 2920 a33 = a33 * cos; 2921 a43 = a43 * cos; 2922 a12 = t1; 2923 a22 = t2; 2924 } 2925 if (sz !== 1) { 2926 a13 *= sz; 2927 a23 *= sz; 2928 a33 *= sz; 2929 a43 *= sz; 2930 } 2931 if (sy !== 1) { 2932 a12 *= sy; 2933 a22 *= sy; 2934 a32 *= sy; 2935 a42 *= sy; 2936 } 2937 if (sx !== 1) { 2938 a11 *= sx; 2939 a21 *= sx; 2940 a31 *= sx; 2941 a41 *= sx; 2942 } 2943 if (zOrigin || isSVG) { 2944 if (zOrigin) { 2945 x += a13 * -zOrigin; 2946 y += a23 * -zOrigin; 2947 z += a33 * -zOrigin + zOrigin; 2948 } 2949 if (isSVG) { 2950 //due to bugs in some browsers, we need to manage the transform-origin of SVG manually 2951 x += t.xOrigin - (t.xOrigin * a11 + t.yOrigin * a12) + t.xOffset; 2952 y += t.yOrigin - (t.xOrigin * a21 + t.yOrigin * a22) + t.yOffset; 2953 } 2954 if (x < min && x > -min) { 2955 x = zero; 2956 } 2957 if (y < min && y > -min) { 2958 y = zero; 2959 } 2960 if (z < min && z > -min) { 2961 z = 0; //don't use string because we calculate perspective later and need the number. 2962 } 2963 } 2964 2965 //optimized way of concatenating all the values into a string. If we do it all in one shot, it's slower because of the way browsers have to create temp strings and the way it affects memory. If we do it piece-by-piece with +=, it's a bit slower too. We found that doing it in these sized chunks works best overall: 2966 transform = t.xPercent || t.yPercent ? "translate(" + t.xPercent + "%," + t.yPercent + "%) matrix3d(" : "matrix3d("; 2967 transform += (a11 < min && a11 > -min ? zero : a11) + comma + (a21 < min && a21 > -min ? zero : a21) + comma + (a31 < min && a31 > -min ? zero : a31); 2968 transform += comma + (a41 < min && a41 > -min ? zero : a41) + comma + (a12 < min && a12 > -min ? zero : a12) + comma + (a22 < min && a22 > -min ? zero : a22); 2969 if (rotationX || rotationY || sz !== 1) { 2970 //performance optimization (often there's no rotationX or rotationY, so we can skip these calculations) 2971 transform += comma + (a32 < min && a32 > -min ? zero : a32) + comma + (a42 < min && a42 > -min ? zero : a42) + comma + (a13 < min && a13 > -min ? zero : a13); 2972 transform += comma + (a23 < min && a23 > -min ? zero : a23) + comma + (a33 < min && a33 > -min ? zero : a33) + comma + (a43 < min && a43 > -min ? zero : a43) + comma; 2973 } else { 2974 transform += ",0,0,0,0,1,0,"; 2975 } 2976 transform += x + comma + y + comma + z + comma + (perspective ? 1 + -z / perspective : 1) + ")"; 2977 style[_transformProp] = transform; 2978 }; 2979 p = Transform.prototype; 2980 p.x = p.y = p.z = p.skewX = p.skewY = p.rotation = p.rotationX = p.rotationY = p.zOrigin = p.xPercent = p.yPercent = p.xOffset = p.yOffset = 0; 2981 p.scaleX = p.scaleY = p.scaleZ = 1; 2982 _registerComplexSpecialProp("transform,scale,scaleX,scaleY,scaleZ,x,y,z,rotation,rotationX,rotationY,rotationZ,skewX,skewY,shortRotation,shortRotationX,shortRotationY,shortRotationZ,transformOrigin,svgOrigin,transformPerspective,directionalRotation,parseTransform,force3D,skewType,xPercent,yPercent,smoothOrigin", { 2983 parser: function parser(t, e, parsingProp, cssp, pt, plugin, vars) { 2984 if (cssp._lastParsedTransform === vars) { 2985 return pt; 2986 } //only need to parse the transform once, and only if the browser supports it. 2987 cssp._lastParsedTransform = vars; 2988 var scaleFunc = vars.scale && typeof vars.scale === "function" ? vars.scale : 0, 2989 //if there's a function-based "scale" value, swap in the resulting numeric value temporarily. Otherwise, if it's called for both scaleX and scaleY independently, they may not match (like if the function uses Math.random()). 2990 swapFunc; 2991 if (typeof vars[parsingProp] === "function") { 2992 //whatever property triggers the initial parsing might be a function-based value in which case it already got called in parse(), thus we don't want to call it again in here. The most efficient way to avoid this is to temporarily swap the value directly into the vars object, and then after we do all our parsing in this function, we'll swap it back again. 2993 swapFunc = vars[parsingProp]; 2994 vars[parsingProp] = e; 2995 } 2996 if (scaleFunc) { 2997 vars.scale = scaleFunc(_index, t); 2998 } 2999 var originalGSTransform = t._gsTransform, 3000 style = t.style, 3001 min = 0.000001, 3002 i = _transformProps.length, 3003 v = vars, 3004 endRotations = {}, 3005 transformOriginString = "transformOrigin", 3006 m1 = _getTransform(t, _cs, true, v.parseTransform), 3007 orig = v.transform && (typeof v.transform === "function" ? v.transform(_index, _target) : v.transform), 3008 m2, 3009 copy, 3010 has3D, 3011 hasChange, 3012 dr, 3013 x, 3014 y, 3015 matrix, 3016 p; 3017 m1.skewType = v.skewType || m1.skewType || _CSSPlugin.defaultSkewType; 3018 cssp._transform = m1; 3019 if (orig && typeof orig === "string" && _transformProp) { 3020 //for values like transform:"rotate(60deg) scale(0.5, 0.8)" 3021 copy = _tempDiv.style; //don't use the original target because it might be SVG in which case some browsers don't report computed style correctly. 3022 copy[_transformProp] = orig; 3023 copy.display = "block"; //if display is "none", the browser often refuses to report the transform properties correctly. 3024 copy.position = "absolute"; 3025 _doc.body.appendChild(_tempDiv); 3026 m2 = _getTransform(_tempDiv, null, false); 3027 if (m1.skewType === "simple") { 3028 //the default _getTransform() reports the skewX/scaleY as if skewType is "compensated", thus we need to adjust that here if skewType is "simple". 3029 m2.scaleY *= Math.cos(m2.skewX * _DEG2RAD); 3030 } 3031 if (m1.svg) { 3032 //if it's an SVG element, x/y part of the matrix will be affected by whatever we use as the origin and the offsets, so compensate here... 3033 x = m1.xOrigin; 3034 y = m1.yOrigin; 3035 m2.x -= m1.xOffset; 3036 m2.y -= m1.yOffset; 3037 if (v.transformOrigin || v.svgOrigin) { 3038 //if this tween is altering the origin, we must factor that in here. The actual work of recording the transformOrigin values and setting up the PropTween is done later (still inside this function) so we cannot leave the changes intact here - we only want to update the x/y accordingly. 3039 orig = {}; 3040 _parseSVGOrigin(t, _parsePosition2(v.transformOrigin), orig, v.svgOrigin, v.smoothOrigin, true); 3041 x = orig.xOrigin; 3042 y = orig.yOrigin; 3043 m2.x -= orig.xOffset - m1.xOffset; 3044 m2.y -= orig.yOffset - m1.yOffset; 3045 } 3046 if (x || y) { 3047 matrix = _getMatrix(_tempDiv, true); 3048 m2.x -= x - (x * matrix[0] + y * matrix[2]); 3049 m2.y -= y - (x * matrix[1] + y * matrix[3]); 3050 } 3051 } 3052 _doc.body.removeChild(_tempDiv); 3053 if (!m2.perspective) { 3054 m2.perspective = m1.perspective; //tweening to no perspective gives very unintuitive results - just keep the same perspective in that case. 3055 } 3056 if (v.xPercent != null) { 3057 m2.xPercent = _parseVal(v.xPercent, m1.xPercent); 3058 } 3059 if (v.yPercent != null) { 3060 m2.yPercent = _parseVal(v.yPercent, m1.yPercent); 3061 } 3062 } else if (_typeof(v) === "object") { 3063 //for values like scaleX, scaleY, rotation, x, y, skewX, and skewY or transform:{...} (object) 3064 m2 = { 3065 scaleX: _parseVal(v.scaleX != null ? v.scaleX : v.scale, m1.scaleX), 3066 scaleY: _parseVal(v.scaleY != null ? v.scaleY : v.scale, m1.scaleY), 3067 scaleZ: _parseVal(v.scaleZ, m1.scaleZ), 3068 x: _parseVal(v.x, m1.x), 3069 y: _parseVal(v.y, m1.y), 3070 z: _parseVal(v.z, m1.z), 3071 xPercent: _parseVal(v.xPercent, m1.xPercent), 3072 yPercent: _parseVal(v.yPercent, m1.yPercent), 3073 perspective: _parseVal(v.transformPerspective, m1.perspective) 3074 }; 3075 dr = v.directionalRotation; 3076 if (dr != null) { 3077 if (_typeof(dr) === "object") { 3078 for (copy in dr) { 3079 v[copy] = dr[copy]; 3080 } 3081 } else { 3082 v.rotation = dr; 3083 } 3084 } 3085 if (typeof v.x === "string" && v.x.indexOf("%") !== -1) { 3086 m2.x = 0; 3087 m2.xPercent = _parseVal(v.x, m1.xPercent); 3088 } 3089 if (typeof v.y === "string" && v.y.indexOf("%") !== -1) { 3090 m2.y = 0; 3091 m2.yPercent = _parseVal(v.y, m1.yPercent); 3092 } 3093 m2.rotation = _parseAngle("rotation" in v ? v.rotation : "shortRotation" in v ? v.shortRotation + "_short" : "rotationZ" in v ? v.rotationZ : m1.rotation, m1.rotation, "rotation", endRotations); 3094 if (_supports3D) { 3095 m2.rotationX = _parseAngle("rotationX" in v ? v.rotationX : "shortRotationX" in v ? v.shortRotationX + "_short" : m1.rotationX || 0, m1.rotationX, "rotationX", endRotations); 3096 m2.rotationY = _parseAngle("rotationY" in v ? v.rotationY : "shortRotationY" in v ? v.shortRotationY + "_short" : m1.rotationY || 0, m1.rotationY, "rotationY", endRotations); 3097 }
3098 m2.skewX = _parseAngle(v.skewX, m1.skewX); 3099 m2.skewY = _parseAngle(v.skewY, m1.skewY); 3100 } 3101 if (_supports3D && v.force3D != null) { 3102 m1.force3D = v.force3D; 3103 hasChange = true; 3104 } 3105 has3D = m1.force3D || m1.z || m1.rotationX || m1.rotationY || m2.z || m2.rotationX || m2.rotationY || m2.perspective; 3106 if (!has3D && v.scale != null) { 3107 m2.scaleZ = 1; //no need to tween scaleZ. 3108 } 3109 while (--i > -1) { 3110 p = _transformProps[i]; 3111 orig = m2[p] - m1[p]; 3112 if (orig > min || orig < -min || v[p] != null || _forcePT[p] != null) { 3113 hasChange = true; 3114 pt = new CSSPropTween(m1, p, m1[p], orig, pt); 3115 if (p in endRotations) { 3116 pt.e = endRotations[p]; //directional rotations typically have compensated values during the tween, but we need to make sure they end at exactly what the user requested 3117 } 3118 pt.xs0 = 0; //ensures the value stays numeric in setRatio() 3119 pt.plugin = plugin; 3120 cssp._overwriteProps.push(pt.n); 3121 } 3122 } 3123 orig = v.transformOrigin; 3124 if (m1.svg && (orig || v.svgOrigin)) { 3125 x = m1.xOffset; //when we change the origin, in order to prevent things from jumping we adjust the x/y so we must record those here so that we can create PropTweens for them and flip them at the same time as the origin 3126 y = m1.yOffset; 3127 _parseSVGOrigin(t, _parsePosition2(orig), m2, v.svgOrigin, v.smoothOrigin); 3128 pt = _addNonTweeningNumericPT(m1, "xOrigin", (originalGSTransform ? m1 : m2).xOrigin, m2.xOrigin, pt, transformOriginString); //note: if there wasn't a transformOrigin defined yet, just start with the destination one; it's wasteful otherwise, and it causes problems with fromTo() tweens. For example, TweenLite.to("#wheel", 3, {rotation:180, transformOrigin:"50% 50%", delay:1}); TweenLite.fromTo("#wheel", 3, {scale:0.5, transformOrigin:"50% 50%"}, {scale:1, delay:2}); would cause a jump when the from values revert at the beginning of the 2nd tween. 3129 pt = _addNonTweeningNumericPT(m1, "yOrigin", (originalGSTransform ? m1 : m2).yOrigin, m2.yOrigin, pt, transformOriginString); 3130 if (x !== m1.xOffset || y !== m1.yOffset) { 3131 pt = _addNonTweeningNumericPT(m1, "xOffset", originalGSTransform ? x : m1.xOffset, m1.xOffset, pt, transformOriginString); 3132 pt = _addNonTweeningNumericPT(m1, "yOffset", originalGSTransform ? y : m1.yOffset, m1.yOffset, pt, transformOriginString); 3133 } 3134 orig = "0px 0px"; //certain browsers (like firefox) completely botch transform-origin, so we must remove it to prevent it from contaminating transforms. We manage it ourselves with xOrigin and yOrigin 3135 } 3136 if (orig || _supports3D && has3D && m1.zOrigin) { 3137 //if anything 3D is happening and there's a transformOrigin with a z component that's non-zero, we must ensure that the transformOrigin's z-component is set to 0 so that we can manually do those calculations to get around Safari bugs. Even if the user didn't specifically define a "transformOrigin" in this particular tween (maybe they did it via css directly). 3138 if (_transformProp) { 3139 hasChange = true; 3140 p = _transformOriginProp; 3141 orig = (orig || _getStyle(t, p, _cs, false, "50% 50%")) + ""; //cast as string to avoid errors 3142 pt = new CSSPropTween(style, p, 0, 0, pt, -1, transformOriginString); 3143 pt.b = style[p]; 3144 pt.plugin = plugin; 3145 if (_supports3D) { 3146 copy = m1.zOrigin; 3147 orig = orig.split(" "); 3148 m1.zOrigin = (orig.length > 2 && !(copy !== 0 && orig[2] === "0px") ? parseFloat(orig[2]) : copy) || 0; //Safari doesn't handle the z part of transformOrigin correctly, so we'll manually handle it in the _set3DTransformRatio() method. 3149 pt.xs0 = pt.e = orig[0] + " " + (orig[1] || "50%") + " 0px"; //we must define a z value of 0px specifically otherwise iOS 5 Safari will stick with the old one (if one was defined)! 3150 pt = new CSSPropTween(m1, "zOrigin", 0, 0, pt, -1, pt.n); //we must create a CSSPropTween for the _gsTransform.zOrigin so that it gets reset properly at the beginning if the tween runs backward (as opposed to just setting m1.zOrigin here) 3151 pt.b = copy; 3152 pt.xs0 = pt.e = m1.zOrigin; 3153 } else { 3154 pt.xs0 = pt.e = orig; 3155 } 3156 3157 //for older versions of IE (6-8), we need to manually calculate things inside the setRatio() function. We record origin x and y (ox and oy) and whether or not the values are percentages (oxp and oyp). 3158 } else { 3159 _parsePosition2(orig + "", m1); 3160 } 3161 } 3162 if (hasChange) { 3163 cssp._transformType = !(m1.svg && _useSVGTransformAttr) && (has3D || this._transformType === 3) ? 3 : 2; //quicker than calling cssp._enableTransforms(); 3164 } 3165 if (swapFunc) { 3166 vars[parsingProp] = swapFunc; 3167 } 3168 if (scaleFunc) { 3169 vars.scale = scaleFunc; 3170 } 3171 return pt; 3172 }, 3173 prefix: true 3174 }); 3175 _registerComplexSpecialProp("boxShadow", { 3176 defaultValue: "0px 0px 0px 0px #999", 3177 prefix: true, 3178 color: true, 3179 multi: true, 3180 keyword: "inset" 3181 }); 3182 _registerComplexSpecialProp("borderRadius", { 3183 defaultValue: "0px", 3184 parser: function parser(t, e, p, cssp, pt, plugin) { 3185 e = this.format(e); 3186 var props = ["borderTopLeftRadius", "borderTopRightRadius", "borderBottomRightRadius", "borderBottomLeftRadius"], 3187 style = t.style, 3188 ea1, 3189 i, 3190 es2, 3191 bs2, 3192 bs, 3193 es, 3194 bn, 3195 en, 3196 w, 3197 h, 3198 esfx, 3199 bsfx, 3200 rel, 3201 hn, 3202 vn, 3203 em; 3204 w = parseFloat(t.offsetWidth); 3205 h = parseFloat(t.offsetHeight); 3206 ea1 = e.split(" "); 3207 for (i = 0; i < props.length; i++) { 3208 //if we're dealing with percentages, we must convert things separately for the horizontal and vertical axis! 3209 if (this.p.indexOf("border")) { 3210 //older browsers used a prefix 3211 props[i] = _checkPropPrefix(props[i]); 3212 }
3213 bs = bs2 = _getStyle(t, props[i], _cs, false, "0px"); 3214 if (bs.indexOf(" ") !== -1) { 3215 bs2 = bs.split(" "); 3216 bs = bs2[0]; 3217 bs2 = bs2[1]; 3218 } 3219 es = es2 = ea1[i]; 3220 bn = parseFloat(bs); 3221 bsfx = bs.substr((bn + "").length); 3222 rel = es.charAt(1) === "="; 3223 if (rel) { 3224 en = parseInt(es.charAt(0) + "1", 10); 3225 es = es.substr(2); 3226 en *= parseFloat(es); 3227 esfx = es.substr((en + "").length - (en < 0 ? 1 : 0)) || ""; 3228 } else { 3229 en = parseFloat(es); 3230 esfx = es.substr((en + "").length); 3231 } 3232 if (esfx === "") { 3233 esfx = _suffixMap[p] || bsfx; 3234 } 3235 if (esfx !== bsfx) { 3236 hn = _convertToPixels(t, "borderLeft", bn, bsfx); //horizontal number (we use a bogus "borderLeft" property just because the _convertToPixels() method searches for the keywords "Left", "Right", "Top", and "Bottom" to determine of it's a horizontal or vertical property, and we need "border" in the name so that it knows it should measure relative to the element itself, not its parent. 3237 vn = _convertToPixels(t, "borderTop", bn, bsfx); //vertical number 3238 if (esfx === "%") { 3239 bs = hn / w * 100 + "%"; 3240 bs2 = vn / h * 100 + "%"; 3241 } else if (esfx === "em") { 3242 em = _convertToPixels(t, "borderLeft", 1, "em"); 3243 bs = hn / em + "em"; 3244 bs2 = vn / em + "em"; 3245 } else { 3246 bs = hn + "px"; 3247 bs2 = vn + "px"; 3248 } 3249 if (rel) { 3250 es = parseFloat(bs) + en + esfx; 3251 es2 = parseFloat(bs2) + en + esfx; 3252 } 3253 } 3254 pt = _parseComplex(style, props[i], bs + " " + bs2, es + " " + es2, false, "0px", pt); 3255 } 3256 return pt; 3257 }, 3258 prefix: true, 3259 formatter: _getFormatter("0px 0px 0px 0px", false, true) 3260 }); 3261 _registerComplexSpecialProp("borderBottomLeftRadius,borderBottomRightRadius,borderTopLeftRadius,borderTopRightRadius", { 3262 defaultValue: "0px", 3263 parser: function parser(t, e, p, cssp, pt, plugin) { 3264 return _parseComplex(t.style, p, this.format(_getStyle(t, p, _cs, false, "0px 0px")), this.format(e), false, "0px", pt); 3265 }, 3266 prefix: true, 3267 formatter: _getFormatter("0px 0px", false, true) 3268 }); 3269 _registerComplexSpecialProp("backgroundPosition", { 3270 defaultValue: "0 0", 3271 parser: function parser(t, e, p, cssp, pt, plugin) { 3272 var bp = "background-position", 3273 cs = _cs || _getComputedStyle(t, null), 3274 bs = this.format((cs ? _ieVers ? cs.getPropertyValue(bp + "-x") + " " + cs.getPropertyValue(bp + "-y") : cs.getPropertyValue(bp) : t.currentStyle.backgroundPositionX + " " + t.currentStyle.backgroundPositionY) || "0 0"), 3275 //Internet Explorer doesn't report background-position correctly - we must query background-position-x and background-position-y and combine them (even in IE10). Before IE9, we must do the same with the currentStyle object and use camelCase 3276 es = this.format(e), 3277 ba, 3278 ea, 3279 i, 3280 pct, 3281 overlap, 3282 src; 3283 if (bs.indexOf("%") !== -1 !== (es.indexOf("%") !== -1) && es.split(",").length < 2) { 3284 src = _getStyle(t, "backgroundImage").replace(_urlExp, ""); 3285 if (src && src !== "none") { 3286 ba = bs.split(" "); 3287 ea = es.split(" "); 3288 _tempImg.setAttribute("src", src); //set the temp IMG's src to the background-image so that we can measure its width/height 3289 i = 2; 3290 while (--i > -1) { 3291 bs = ba[i]; 3292 pct = bs.indexOf("%") !== -1; 3293 if (pct !== (ea[i].indexOf("%") !== -1)) { 3294 overlap = i === 0 ? t.offsetWidth - _tempImg.width : t.offsetHeight - _tempImg.height; 3295 ba[i] = pct ? parseFloat(bs) / 100 * overlap + "px" : parseFloat(bs) / overlap * 100 + "%"; 3296 } 3297 } 3298 bs = ba.join(" "); 3299 } 3300 } 3301 return this.parseComplex(t.style, bs, es, pt, plugin); 3302 }, 3303 formatter: _parsePosition2 3304 }); 3305 _registerComplexSpecialProp("backgroundSize", { 3306 defaultValue: "0 0", 3307 formatter: function formatter(v) { 3308 v += ""; //ensure it's a string 3309 return _parsePosition2(v.indexOf(" ") === -1 ? v + " " + v : v); //if set to something like "100% 100%", Safari typically reports the computed style as just "100%" (no 2nd value), but we should ensure that there are two values, so copy the first one. Otherwise, it'd be interpreted as "100% 0" (wrong). 3310 } 3311 }); 3312 _registerComplexSpecialProp("perspective", { 3313 defaultValue: "0px", 3314 prefix: true 3315 }); 3316 _registerComplexSpecialProp("perspectiveOrigin", { 3317 defaultValue: "50% 50%", 3318 prefix: true 3319 }); 3320 _registerComplexSpecialProp("transformStyle", { 3321 prefix: true 3322 }); 3323 _registerComplexSpecialProp("backfaceVisibility", { 3324 prefix: true 3325 }); 3326 _registerComplexSpecialProp("userSelect", { 3327 prefix: true 3328 }); 3329 _registerComplexSpecialProp("margin", { 3330 parser: _getEdgeParser("marginTop,marginRight,marginBottom,marginLeft") 3331 }); 3332 _registerComplexSpecialProp("padding", { 3333 parser: _getEdgeParser("paddingTop,paddingRight,paddingBottom,paddingLeft") 3334 }); 3335 _registerComplexSpecialProp("clip", { 3336 defaultValue: "rect(0px,0px,0px,0px)", 3337 parser: function parser(t, e, p, cssp, pt, plugin) { 3338 var b, cs, delim; 3339 if (_ieVers < 9) { 3340 //IE8 and earlier don't report a "clip" value in the currentStyle - instead, the values are split apart into clipTop, clipRight, clipBottom, and clipLeft. Also, in IE7 and earlier, the values inside rect() are space-delimited, not comma-delimited. 3341 cs = t.currentStyle; 3342 delim = _ieVers < 8 ? " " : ","; 3343 b = "rect(" + cs.clipTop + delim + cs.clipRight + delim + cs.clipBottom + delim + cs.clipLeft + ")"; 3344 e = this.format(e).split(",").join(delim); 3345 } else { 3346 b = this.format(_getStyle(t, this.p, _cs, false, this.dflt)); 3347 e = this.format(e); 3348 } 3349 return this.parseComplex(t.style, b, e, pt, plugin); 3350 } 3351 }); 3352 _registerComplexSpecialProp("textShadow", { 3353 defaultValue: "0px 0px 0px #999", 3354 color: true, 3355 multi: true 3356 }); 3357 _registerComplexSpecialProp("autoRound,strictUnits", { 3358 parser: function parser(t, e, p, cssp, pt) { 3359 return pt; 3360 } 3361 }); //just so that we can ignore these properties (not tween them) 3362 _registerComplexSpecialProp("border", { 3363 defaultValue: "0px solid #000", 3364 parser: function parser(t, e, p, cssp, pt, plugin) { 3365 var bw = _getStyle(t, "borderTopWidth", _cs, false, "0px"), 3366 end = this.format(e).split(" "), 3367 esfx = end[0].replace(_suffixExp, ""); 3368 if (esfx !== "px") { 3369 //if we're animating to a non-px value, we need to convert the beginning width to that unit. 3370 bw = parseFloat(bw) / _convertToPixels(t, "borderTopWidth", 1, esfx) + esfx; 3371 } 3372 return this.parseComplex(t.style, this.format(bw + " " + _getStyle(t, "borderTopStyle", _cs, false, "solid") + " " + _getStyle(t, "borderTopColor", _cs, false, "#000")), end.join(" "), pt, plugin); 3373 }, 3374 color: true, 3375 formatter: function formatter(v) { 3376 var a = v.split(" "); 3377 return a[0] + " " + (a[1] || "solid") + " " + (v.match(_colorExp) || ["#000"])[0]; 3378 } 3379 }); 3380 _registerComplexSpecialProp("borderWidth", { 3381 parser: _getEdgeParser("borderTopWidth,borderRightWidth,borderBottomWidth,borderLeftWidth") 3382 }); //Firefox doesn't pick up on borderWidth set in style sheets (only inline). 3383 _registerComplexSpecialProp("float,cssFloat,styleFloat", { 3384 parser: function parser(t, e, p, cssp, pt, plugin) { 3385 var s = t.style, 3386 prop = "cssFloat" in s ? "cssFloat" : "styleFloat"; 3387 return new CSSPropTween(s, prop, 0, 0, pt, -1, p, false, 0, s[prop], e); 3388 } 3389 }); 3390 3391 //opacity-related 3392 var _setIEOpacityRatio = function _setIEOpacityRatio(v) { 3393 var t = this.t, 3394 //refers to the element's style property 3395 filters = t.filter || _getStyle(this.data, "filter") || "", 3396 val = this.s + this.c * v | 0, 3397 skip; 3398 if (val === 100) { 3399 //for older versions of IE that need to use a filter to apply opacity, we should remove the filter if opacity hits 1 in order to improve performance, but make sure there isn't a transform (matrix) or gradient in the filters. 3400 if (filters.indexOf("atrix(") === -1 && filters.indexOf("radient(") === -1 && filters.indexOf("oader(") === -1) { 3401 t.removeAttribute("filter"); 3402 skip = !_getStyle(this.data, "filter"); //if a class is applied that has an alpha filter, it will take effect (we don't want that), so re-apply our alpha filter in that case. We must first remove it and then check. 3403 } else {
3404 t.filter = filters.replace(_alphaFilterExp, ""); 3405 skip = true; 3406 } 3407 } 3408 if (!skip) { 3409 if (this.xn1) { 3410 t.filter = filters = filters || "alpha(opacity=" + val + ")"; //works around bug in IE7/8 that prevents changes to "visibility" from being applied properly if the filter is changed to a different alpha on the same frame. 3411 } 3412 if (filters.indexOf("pacity") === -1) { 3413 //only used if browser doesn't support the standard opacity style property (IE 7 and 8). We omit the "O" to avoid case-sensitivity issues 3414 if (val !== 0 || !this.xn1) { 3415 //bugs in IE7/8 won't render the filter properly if opacity is ADDED on the same frame/render as "visibility" changes (this.xn1 is 1 if this tween is an "autoAlpha" tween) 3416 t.filter = filters + " alpha(opacity=" + val + ")"; //we round the value because otherwise, bugs in IE7/8 can prevent "visibility" changes from being applied properly. 3417 } 3418 } else { 3419 t.filter = filters.replace(_opacityExp, "opacity=" + val); 3420 } 3421 } 3422 }; 3423 _registerComplexSpecialProp("opacity,alpha,autoAlpha", { 3424 defaultValue: "1", 3425 parser: function parser(t, e, p, cssp, pt, plugin) { 3426 var b = parseFloat(_getStyle(t, "opacity", _cs, false, "1")), 3427 style = t.style, 3428 isAutoAlpha = p === "autoAlpha"; 3429 if (typeof e === "string" && e.charAt(1) === "=") { 3430 e = (e.charAt(0) === "-" ? -1 : 1) * parseFloat(e.substr(2)) + b; 3431 } 3432 if (isAutoAlpha && b === 1 && _getStyle(t, "visibility", _cs) === "hidden" && e !== 0) { 3433 //if visibility is initially set to "hidden", we should interpret that as intent to make opacity 0 (a convenience) 3434 b = 0; 3435 } 3436 if (_supportsOpacity) { 3437 pt = new CSSPropTween(style, "opacity", b, e - b, pt); 3438 } else { 3439 pt = new CSSPropTween(style, "opacity", b * 100, (e - b) * 100, pt); 3440 pt.xn1 = isAutoAlpha ? 1 : 0; //we need to record whether or not this is an autoAlpha so that in the setRatio(), we know to duplicate the setting of the alpha in order to work around a bug in IE7 and IE8 that prevents changes to "visibility" from taking effect if the filter is changed to a different alpha(opacity) at the same time. Setting it to the SAME value first, then the new value works around the IE7/8 bug. 3441 style.zoom = 1; //helps correct an IE issue. 3442 pt.type = 2; 3443 pt.b = "alpha(opacity=" + pt.s + ")"; 3444 pt.e = "alpha(opacity=" + (pt.s + pt.c) + ")"; 3445 pt.data = t; 3446 pt.plugin = plugin; 3447 pt.setRatio = _setIEOpacityRatio; 3448 } 3449 if (isAutoAlpha) { 3450 //we have to create the "visibility" PropTween after the opacity one in the linked list so that they run in the order that works properly in IE8 and earlier 3451 pt = new CSSPropTween(style, "visibility", 0, 0, pt, -1, null, false, 0, b !== 0 ? "inherit" : "hidden", e === 0 ? "hidden" : "inherit"); 3452 pt.xs0 = "inherit"; 3453 cssp._overwriteProps.push(pt.n); 3454 cssp._overwriteProps.push(p); 3455 } 3456 return pt; 3457 } 3458 }); 3459 var _removeProp = function _removeProp(s, p) { 3460 if (p) { 3461 if (s.removeProperty) { 3462 if (p.substr(0, 2) === "ms" || p.substr(0, 6) === "webkit") { 3463 //Microsoft and some Webkit browsers don't conform to the standard of capitalizing the first prefix character, so we adjust so that when we prefix the caps with a dash, it's correct (otherwise it'd be "ms-transform" instead of "-ms-transform" for IE9, for example) 3464 p = "-" + p; 3465 } 3466 s.removeProperty(p.replace(_capsExp, "-$1").toLowerCase()); 3467 } else { 3468 //note: old versions of IE use "removeAttribute()" instead of "removeProperty()" 3469 s.removeAttribute(p); 3470 } 3471 } 3472 }, 3473 _setClassNameRatio = function _setClassNameRatio(v) { 3474 this.t._gsClassPT = this; 3475 if (v === 1 || v === 0) { 3476 this.t.setAttribute("class", v === 0 ? this.b : this.e); 3477 var mpt = this.data, 3478 //first MiniPropTween 3479 s = this.t.style; 3480 while (mpt) { 3481 if (!mpt.v) { 3482 _removeProp(s, mpt.p); 3483 } else { 3484 s[mpt.p] = mpt.v; 3485 } 3486 mpt = mpt._next; 3487 } 3488 if (v === 1 && this.t._gsClassPT === this) { 3489 this.t._gsClassPT = null; 3490 } 3491 } else if (this.t.getAttribute("class") !== this.e) { 3492 this.t.setAttribute("class", this.e); 3493 } 3494 }; 3495 _registerComplexSpecialProp("className", { 3496 parser: function parser(t, e, p, cssp, pt, plugin, vars) { 3497 var b = t.getAttribute("class") || "", 3498 //don't use t.className because it doesn't work consistently on SVG elements; getAttribute("class") and setAttribute("class", value") is more reliable. 3499 cssText = t.style.cssText, 3500 difData, 3501 bs, 3502 cnpt, 3503 cnptLookup, 3504 mpt; 3505 pt = cssp._classNamePT = new CSSPropTween(t, p, 0, 0, pt, 2); 3506 pt.setRatio = _setClassNameRatio; 3507 pt.pr = -11; 3508 _hasPriority = true; 3509 pt.b = b; 3510 bs = _getAllStyles(t, _cs); 3511 //if there's a className tween already operating on the target, force it to its end so that the necessary inline styles are removed and the class name is applied before we determine the end state (we don't want inline styles interfer
3511ing that were there just for class-specific values) 3512 cnpt = t._gsClassPT; 3513 if (cnpt) { 3514 cnptLookup = {}; 3515 mpt = cnpt.data; //first MiniPropTween which stores the inline styles - we need to force these so that the inline styles don't contaminate things. Otherwise, there's a small chance that a tween could start and the inline values match the destination values and they never get cleaned. 3516 while (mpt) { 3517 cnptLookup[mpt.p] = 1; 3518 mpt = mpt._next; 3519 } 3520 cnpt.setRatio(1); 3521 } 3522 t._gsClassPT = pt; 3523 pt.e = e.charAt(1) !== "=" ? e : b.replace(new RegExp("(?:\\s|^)" + e.substr(2) + "(?![\\w-])"), "") + (e.charAt(0) === "+" ? " " + e.substr(2) : ""); 3524 t.setAttribute("class", pt.e); 3525 difData = _cssDif(t, bs, _getAllStyles(t), vars, cnptLookup); 3526 t.setAttribute("class", b); 3527 pt.data = difData.firstMPT; 3528 t.style.cssText = cssText; //we recorded cssText before we swapped classes and ran _getAllStyles() because in cases when a className tween is overwritten, we remove all the related tweening properties from that class change (otherwise class-specific stuff can't override properties we've directly set on the target's style object due to specificity). 3529 pt = pt.xfirst = cssp.parse(t, difData.difs, pt, plugin); //we record the CSSPropTween as the xfirst so that we can handle overwriting propertly (if "className" gets overwritten, we must kill all the properties associated with the className part of the tween, so we can loop through from xfirst to the pt itself) 3530 return pt; 3531 } 3532 }); 3533 var _setClearPropsRatio = function _setClearPropsRatio(v) { 3534 if (v === 1 || v === 0) if (this.data._totalTime === this.data._totalDuration && this.data.data !== "isFromStart") { 3535 //this.data refers to the tween. Only clear at the END of the tween (remember, from() tweens make the ratio go from 1 to 0, so we can't just check that and if the tween is the zero-duration one that's created internally to render the starting values in a from() tween, ignore that because otherwise, for example, from(...{height:100, clearProps:"height", delay:1}) would wipe the height at the beginning of the tween and after 1 second, it'd kick back in). 3536 var s = this.t.style, 3537 transformParse = _specialProps.transform.parse, 3538 a, 3539 p, 3540 i, 3541 clearTransform, 3542 transform; 3543 if (this.e === "all") { 3544 s.cssText = ""; 3545 clearTransform = true; 3546 } else { 3547 a = this.e.split(" ").join("").split(","); 3548 i = a.length; 3549 while (--i > -1) { 3550 p = a[i]; 3551 if (_specialProps[p]) { 3552 if (_specialProps[p].parse === transformParse) { 3553 clearTransform = true; 3554 } else { 3555 p = p === "transformOrigin" ? _transformOriginProp : _specialProps[p].p; //ensures that special properties use the proper browser-specific property name, like "scaleX" might be "-webkit-transform" or "boxShadow" might be "-moz-box-shadow" 3556 } 3557 } 3558 _removeProp(s, p); 3559 } 3560 } 3561 if (clearTransform) { 3562 _removeProp(s, _transformProp); 3563 transform = this.t._gsTransform; 3564 if (transform) { 3565 if (transform.svg) { 3566 this.t.removeAttribute("data-svg-origin"); 3567 this.t.removeAttribute("transform"); 3568 } 3569 delete this.t._gsTransform; 3570 } 3571 } 3572 } 3573 }; 3574 _registerComplexSpecialProp("clearProps", { 3575 parser: function parser(t, e, p, cssp, pt) { 3576 pt = new CSSPropTween(t, p, 0, 0, pt, 2); 3577 pt.setRatio = _setClearPropsRatio; 3578 pt.e = e; 3579 pt.pr = -10; 3580 pt.data = cssp._tween; 3581 _hasPriority = true; 3582 return pt; 3583 } 3584 }); 3585 p = "bezier,throwProps,physicsProps,physics2D".split(","); 3586 i = p.length; 3587 while (i--) { 3588 _registerPluginProp(p[i]); 3589 } 3590 p = _CSSPlugin.prototype; 3591 p._firstPT = p._lastParsedTransform = p._transform = null; 3592 3593 //gets called when the tween renders for the first time. This kicks everything off, recording start/end values, etc. 3594 p._onInitTween = function (target, vars, tween, index) { 3595 if (!target.nodeType) { 3596 //css is only for dom elements 3597 return false;
3598 } 3599 this._target = _target = target; 3600 this._tween = tween; 3601 this._vars = vars; 3602 _index = index; 3603 _autoRound = vars.autoRound; 3604 _hasPriority = false; 3605 _suffixMap = vars.suffixMap || _CSSPlugin.suffixMap; 3606 _cs = _getComputedStyle(target, ""); 3607 _overwriteProps = this._overwriteProps; 3608 var style = target.style, 3609 v, 3610 pt, 3611 pt2, 3612 first, 3613 last, 3614 next, 3615 zIndex, 3616 tpt, 3617 threeD; 3618 if (_reqSafariFix) if (style.zIndex === "") { 3619 v = _getStyle(target, "zIndex", _cs); 3620 if (v === "auto" || v === "") { 3621 //corrects a bug in [non-Android] Safari that prevents it from repainting elements in their new positions if they don't have a zIndex set. We also can't just apply this inside _parseTransform() because anything that's moved in any way (like using "left" or "top" instead of transforms like "x" and "y") can be affected, so it is best to ensure that anything that's tweening has a z-index. Setting "WebkitPerspective" to a non-zero value worked too except that on iOS Safari things would flicker randomly. Plus zIndex is less memory-intensive. 3622 this._addLazySet(style, "zIndex", 0); 3623 } 3624 } 3625 if (typeof vars === "string") { 3626 first = style.cssText; 3627 v = _getAllStyles(target, _cs); 3628 style.cssText = first + ";" + vars; 3629 v = _cssDif(target, v, _getAllStyles(target)).difs; 3630 if (!_supportsOpacity && _opacityValExp.test(vars)) { 3631 v.opacity = parseFloat(RegExp.$1); 3632 } 3633 vars = v; 3634 style.cssText = first; 3635 } 3636 if (vars.className) { 3637 //className tweens will combine any differences they find in the css with the vars that are passed in, so {className:"myClass", scale:0.5, left:20} would work. 3638 this._firstPT = pt = _specialProps.className.parse(target, vars.className, "className", this, null, null, vars); 3639 } else { 3640 this._firstPT = pt = this.parse(target, vars, null); 3641 } 3642 if (this._transformType) { 3643 threeD = this._transformType === 3; 3644 if (!_transformProp) { 3645 style.zoom = 1; //helps correct an IE issue. 3646 } else if (_isSafari) { 3647 _reqSafariFix = true; 3648 //if zIndex isn't set, iOS Safari doesn't repaint things correctly sometimes (seemingly at random). 3649 if (style.zIndex === "") { 3650 zIndex = _getStyle(target, "zIndex", _cs); 3651 if (zIndex === "auto" || zIndex === "") { 3652 this._addLazySet(style, "zIndex", 0); 3653 } 3654 } 3655 //Setting WebkitBackfaceVisibility corrects 3 bugs: 3656 // 1) [non-Android] Safari skips rendering changes to "top" and "left" that are made on the same frame/render as a transform update. 3657 // 2) iOS Safari sometimes neglects to repaint elements in their new positions. Setting "WebkitPerspective" to a non-zero value worked too except that on iOS Safari things would flicker randomly. 3658 // 3) Safari sometimes displayed odd artifacts when tweening the transform (or WebkitTransform) property, like ghosts of the edges of the element remained. Definitely a browser bug. 3659 //Note: we allow the user to override the auto-setting by defining WebkitBackfaceVisibility in the vars of the tween. 3660 if (_isSafariLT6) { 3661 this._addLazySet(style, "WebkitBackfaceVisibility", this._vars.WebkitBackfaceVisibility || (threeD ? "visible" : "hidden")); 3662 } 3663 } 3664 pt2 = pt; 3665 while (pt2 && pt2._next) { 3666 pt2 = pt2._next; 3667 } 3668 tpt = new CSSPropTween(target, "transform", 0, 0, null, 2); 3669 this._linkCSSP(tpt, null, pt2); 3670 tpt.setRatio = _transformProp ? _setTransformRatio : _setIETransformRatio; 3671 tpt.data = this._transform || _getTransform(target, _cs, true); 3672 tpt.tween = tween; 3673 tpt.pr = -1; //ensures that the transforms get applied after the components are updated. 3674 _overwriteProps.pop(); //we don't want to force the overwrite of all "transform" tweens of the target - we only care about individual transform properties like scaleX, rotation, etc. The CSSPropTween constructor automatically adds the property to _overwriteProps which is why we need to pop() here. 3675 } 3676 if (_hasPriority) { 3677 //reorders the linked list in order of pr (priority) 3678 while (pt) { 3679 next = pt._next; 3680 pt2 = first; 3681 while (pt2 && pt2.pr > pt.pr) { 3682 pt2 = pt2._next; 3683 } 3684 if (pt._prev = pt2 ? pt2._prev : last) { 3685 pt._prev._next = pt; 3686 } else { 3687 first = pt; 3688 } 3689 if (pt._next = pt2) { 3690 pt2._prev = pt; 3691 } else { 3692 last = pt; 3693 } 3694 pt = next; 3695 } 3696 this._firstPT = first; 3697 } 3698 return true; 3699 }; 3700 p.parse = function (target, vars, pt, plugin) { 3701 var style = target.style, 3702 p, 3703 sp, 3704 bn, 3705 en, 3706 bs, 3707 es, 3708 bsfx, 3709 esfx, 3710 isStr, 3711 rel; 3712 for (p in vars) { 3713 es = vars[p]; //ending value string 3714 if (typeof es === "function") { 3715 es = es(_index, _target); 3716 } 3717 sp = _specialProps[p]; //SpecialProp lookup. 3718 if (sp) { 3719 pt = sp.parse(target, es, p, this, pt, plugin, vars); 3720 } else if (p.substr(0, 2) === "--") { 3721 //for tweening CSS variables (which always start with "--"). To maximize performance and simplicity, we bypass CSSPlugin altogether and just add a normal property tween to the tween instance itself. 3722 this._tween._propLookup[p] = this._addTween.call(this._tween, target.style, "setProperty", _getComputedStyle(target).getPropertyValue(p) + "", es + "", p, false, p); 3723 continue; 3724 } else { 3725 bs = _getStyle(target, p, _cs) + ""; 3726 isStr = typeof es === "string"; 3727 if (p === "color" || p === "fill" || p === "stroke" || p.indexOf("Color") !== -1 || isStr && _rgbhslExp.test(es)) { 3728 //Opera uses background: to define color sometimes in addition to backgroundColor: 3729 if (!isStr) { 3730 es = _parseColor(es); 3731 es = (es.length > 3 ? "rgba(" : "rgb(") + es.join(",") + ")"; 3732 } 3733 pt = _parseComplex(style, p, bs, es, true, "transparent", pt, 0, plugin); 3734 } else if (isStr && _complexExp.test(es)) { 3735 pt = _parseComplex(style, p, bs, es, true, null, pt, 0, plugin); 3736 } else { 3737 bn = parseFloat(bs); 3738 bsfx = bn || bn === 0 ? bs.substr((bn + "").length) : ""; //remember, bs could be non-numeric like "normal" for fontWeight, so we should default to a blank suffix in that case. 3739 3740 if (bs === "" || bs === "auto") { 3741 if (p === "width" || p === "height") { 3742 bn = _getDimension(target, p, _cs); 3743 bsfx = "px"; 3744 } else if (p === "left" || p === "top") {
3745 bn = _calculateOffset(target, p, _cs); 3746 bsfx = "px"; 3747 } else { 3748 bn = p !== "opacity" ? 0 : 1; 3749 bsfx = ""; 3750 } 3751 } 3752 rel = isStr && es.charAt(1) === "="; 3753 if (rel) { 3754 en = parseInt(es.charAt(0) + "1", 10); 3755 es = es.substr(2); 3756 en *= parseFloat(es); 3757 esfx = es.replace(_suffixExp, ""); 3758 } else { 3759 en = parseFloat(es); 3760 esfx = isStr ? es.replace(_suffixExp, "") : ""; 3761 } 3762 if (esfx === "") { 3763 esfx = p in _suffixMap ? _suffixMap[p] : bsfx; //populate the end suffix, prioritizing the map, then if none is found, use the beginning suffix. 3764 } 3765 es = en || en === 0 ? (rel ? en + bn : en) + esfx : vars[p]; //ensures that any += or -= prefixes are taken care of. Record the end value before normalizing the suffix because we always want to end the tween on exactly what they intended even if it doesn't match the beginning value's suffix. 3766 //if the beginning/ending suffixes don't match, normalize them... 3767 if (bsfx !== esfx) if (esfx !== "" || p === "lineHeight") if (en || en === 0) if (bn) { 3768 //note: if the beginning value (bn) is 0, we don't need to convert units! 3769 bn = _convertToPixels(target, p, bn, bsfx); 3770 if (esfx === "%") { 3771 bn /= _convertToPixels(target, p, 100, "%") / 100; 3772 if (vars.strictUnits !== true) { 3773 //some browsers report only "px" values instead of allowing "%" with getComputedStyle(), so we assume that if we're tweening to a %, we should start there too unless strictUnits:true is defined. This approach is particularly useful for responsive designs that use from() tweens. 3774 bs = bn + "%"; 3775 } 3776 } else if (esfx === "em" || esfx === "rem" || esfx === "vw" || esfx === "vh") { 3777 bn /= _convertToPixels(target, p, 1, esfx); 3778 3779 //otherwise convert to pixels. 3780 } else if (esfx !== "px") { 3781 en = _convertToPixels(target, p, en, esfx); 3782 esfx = "px"; //we don't use bsfx after this, so we don't need to set it to px too. 3783 } 3784 if (rel) if (en || en === 0) { 3785 es = en + bn + esfx; //the changes we made affect relative calculations, so adjust the end value here. 3786 } 3787 } 3788 if (rel) { 3789 en += bn; 3790 } 3791 if ((bn || bn === 0) && (en || en === 0)) { 3792 //faster than isNaN(). Also, previously we required en !== bn but that doesn't really gain much performance and it prevents _parseToProxy() from working properly if beginning and ending values match but need to get tweened by an external plugin anyway. For example, a bezier tween where the target starts at left:0 and has these points: [{left:50},{left:0}] wouldn't work properly because when parsing the last point, it'd match the first (current) one and a non-tweening CSSPropTween would be recorded when we actually need a normal tween (type:0) so that things get updated during the tween properly. 3793 pt = new CSSPropTween(style, p, bn, en - bn, pt, 0, p, _autoRound !== false && (esfx === "px" || p === "zIndex"), 0, bs, es); 3794 pt.xs0 = esfx; 3795 //DEBUG: _log("tween "+p+" from "+pt.b+" ("+bn+esfx+") to "+pt.e+" with suffix: "+pt.xs0); 3796 } else if (style[p] === undefined || !es && (es + "" === "NaN" || es == null)) { 3797 _log("invalid " + p + " tween value: " + vars[p]); 3798 } else { 3799 pt = new CSSPropTween(style, p, en || bn || 0, 0, pt, -1, p, false, 0, bs, es); 3800 pt.xs0 = es === "none" && (p === "display" || p.indexOf("Style") !== -1) ? bs : es; //intermediate value should typically be set immediately (end value) except for "display" or things like borderTopStyle, borderBottomStyle, etc. which should use the beginning value during the tween. 3801 //DEBUG: _log("non-tweening value "+p+": "+pt.xs0); 3802 } 3803 } 3804 } 3805 if (plugin) if (pt && !pt.plugin) { 3806 pt.plugin = plugin; 3807 } 3808 } 3809 return pt; 3810 }; 3811 3812 //gets called every time the tween updates, passing the new ratio (typically a value between 0 and 1, but not always (for example, if an Elastic.easeOut is used, the value can jump above 1 mid-tween). It will always start and 0 and end at 1. 3813 p.setRatio = function (v) { 3814 var pt = this._firstPT, 3815 min = 0.000001, 3816 val, 3817 str, 3818 i; 3819 //at the end of the tween, we set the values to exactly what we received in order to make sure non-tweening values (like "position" or "float" or whatever) are set and so that if the beginning/ending suffixes (units) didn't match and we normalized to px, the value that the user passed in is used here. We check to see if the tween is at its beginning in case it's a from() tween in which case the ratio will actually go from 1 to 0 over the course of the tween (backwards). 3820 if (v === 1 && (this._tween._time === this._tween._duration || this._tween._time === 0)) { 3821 while (pt) { 3822 if (pt.type !== 2) { 3823 if (pt.r && pt.type !== -1) { 3824 val = Math.round(pt.s + pt.c); 3825 if (!pt.type) { 3826 pt.t[pt.p] = val + pt.xs0; 3827 } else if (pt.type === 1) { 3828 //complex value (one that typically has multiple numbers inside a string, like "rect(5px,10px,20px,25px)" 3829 i = pt.l; 3830 str = pt.xs0 + val + pt.xs1; 3831 for (i = 1; i < pt.l; i++) { 3832 str += pt["xn" + i] + pt["xs" + (i + 1)]; 3833 } 3834 pt.t[pt.p] = str; 3835 } 3836 } else { 3837 pt.t[pt.p] = pt.e; 3838 } 3839 } else { 3840 pt.setRatio(v); 3841 } 3842 pt = pt._next; 3843 } 3844 } else if (v || !(this._tween._time === this._tween._duration || this._tween._time === 0) || this._tween._rawPrevTime === -0.000001) { 3845 while (pt) { 3846 val = pt.c * v + pt.s; 3847 if (pt.r) { 3848 val = Math.round(val); 3849 } else if (val < min) if (val > -min) { 3850 val = 0; 3851 } 3852 if (!pt.type) { 3853 pt.t[pt.p] = val + pt.xs0; 3854 } else if (pt.type === 1) { 3855 //complex value (one that typically has multiple numbers inside a string, like "rect(5px,10px,20px,25px)" 3856 i = pt.l; 3857 if (i === 2) { 3858 pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2; 3859 } else if (i === 3) { 3860 pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3; 3861 } else if (i === 4) { 3862 pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3 + pt.xn3 + pt.xs4; 3863 } else if (i === 5) { 3864 pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3 + pt.xn3 + pt.xs4 + pt.xn4 + pt.xs5; 3865 } else { 3866 str = pt.xs0 + val + pt.xs1; 3867 for (i = 1; i < pt.l; i++) { 3868 str += pt["xn" + i] + pt["xs" + (i + 1)]; 3869 } 3870 pt.t[pt.p] = str; 3871 } 3872 } else if (pt.type === -1) { 3873 //non-tweening value 3874 pt.t[pt.p] = pt.xs0; 3875 }
3875 else if (pt.setRatio) { 3876 //custom setRatio() for things like SpecialProps, external plugins, etc. 3877 pt.setRatio(v); 3878 } 3879 pt = pt._next; 3880 } 3881 3882 //if the tween is reversed all the way back to the beginning, we need to restore the original values which may have different units (like % instead of px or em or whatever). 3883 } else { 3884 while (pt) { 3885 if (pt.type !== 2) { 3886 pt.t[pt.p] = pt.b; 3887 } else { 3888 pt.setRatio(v); 3889 } 3890 pt = pt._next; 3891 } 3892 } 3893 }; 3894 3895 /** 3896 * @private 3897 * Forces rendering of the target's transforms (rotation, scale, etc.) whenever the CSSPlugin's setRatio() is called. 3898 * Basically, this tells the CSSPlugin to create a CSSPropTween (type 2) after instantiation that runs last in the linked 3899 * list and calls the appropriate (3D or 2D) rendering function. We separate this into its own method so that we can call 3900 * it from other plugins like BezierPlugin if, for example, it needs to apply an autoRotation and this CSSPlugin 3901 * doesn't have any transform-related properties of its own. You can call this method as many times as you 3902 * want and it won't create duplicate CSSPropTweens. 3903 * 3904 * @param {boolean} threeD if true, it should apply 3D tweens (otherwise, just 2D ones are fine and typically faster) 3905 */ 3906 p._enableTransforms = function (threeD) { 3907 this._transform = this._transform || _getTransform(this._target, _cs, true); //ensures that the element has a _gsTransform property with the appropriate values. 3908 this._transformType = !(this._transform.svg && _useSVGTransformAttr) && (threeD || this._transformType === 3) ? 3 : 2; 3909 }; 3910 var lazySet = function lazySet(v) { 3911 this.t[this.p] = this.e; 3912 this.data._linkCSSP(this, this._next, null, true); //we purposefully keep this._next even though it'd make sense to null it, but this is a performance optimization, as this happens during the while (pt) {} loop in setRatio() at the bottom of which it sets pt = pt._next, so if we null it, the linked list will be broken in that loop. 3913 }; 3914 /** @private Gives us a way to set a value on the first render (and only the first render). **/ 3915 p._addLazySet = function (t, p, v) { 3916 var pt = this._firstPT = new CSSPropTween(t, p, 0, 0, this._firstPT, 2); 3917 pt.e = v; 3918 pt.setRatio = lazySet; 3919 pt.data = this; 3920 }; 3921 3922 /** @private **/ 3923 p._linkCSSP = function (pt, next, prev, remove) { 3924 if (pt) { 3925 if (next) { 3926 next._prev = pt; 3927 } 3928 if (pt._next) { 3929 pt._next._prev = pt._prev; 3930 } 3931 if (pt._prev) { 3932 pt._prev._next = pt._next; 3933 } else if (this._firstPT === pt) { 3934 this._firstPT = pt._next; 3935 remove = true; //just to prevent resetting this._firstPT 5 lines down in case pt._next is null. (optimized for speed) 3936 } 3937 if (prev) { 3938 prev._next = pt; 3939 } else if (!remove && this._firstPT === null) { 3940 this._firstPT = pt; 3941 } 3942 pt._next = next; 3943 pt._prev = prev; 3944 } 3945 return pt; 3946 }; 3947 p._mod = function (lookup) { 3948 var pt = this._firstPT; 3949 while (pt) { 3950 if (typeof lookup[pt.p] === "function" && lookup[pt.p] === Math.round) { 3951 //only gets called by RoundPropsPlugin (ModifyPlugin manages all the rendering internally for CSSPlugin properties that need modification). Remember, we handle rounding a bit differently in this plugin for performance reasons, leveraging "r" as an indicator that the value should be rounded internally.. 3952 pt.r = 1; 3953 } 3954 pt = pt._next; 3955 } 3956 }; 3957 3958 //we need to make sure that if alpha or autoAlpha is killed, opacity is too. And autoAlpha affects the "visibility" property. 3959 p._kill = function (lookup) { 3960 var copy = lookup, 3961 pt, 3962 p, 3963 xfirst; 3964 if (lookup.autoAlpha || lookup.alpha) { 3965 copy = {}; 3966 for (p in lookup) { 3967 //copy the lookup so that we're not changing the original which may be passed elsewhere. 3968 copy[p] = lookup[p]; 3969 } 3970 copy.opacity = 1; 3971 if (copy.autoAlpha) { 3972 copy.visibility = 1; 3973 } 3974 } 3975 if (lookup.className && (pt = this._classNamePT)) { 3976 //for className tweens, we need to kill any associated CSSPropTweens too; a linked list starts at the className's "xfirst". 3977 xfirst = pt.xfirst; 3978 if (xfirst && xfirst._prev) { 3979 this._linkCSSP(xfirst._prev, pt._next, xfirst._prev._prev); //break off the prev 3980 } else if (xfirst === this._firstPT) { 3981 this._firstPT = pt._next; 3982 } 3983 if (pt._next) { 3984 this._linkCSSP(pt._next, pt._next._next, xfirst._prev); 3985 } 3986 this._classNamePT = null; 3987 } 3988 pt = this._firstPT; 3989 while (pt) { 3990 if (pt.plugin && pt.plugin !== p && pt.plugin._kill) { 3991 //for plugins that are registered with CSSPlugin, we should notify them of the kill. 3992 pt.plugin._kill(lookup); 3993 p = pt.plugin; 3994 } 3995 pt = pt._next; 3996 } 3997 return TweenPlugin.prototype._kill.call(this, copy); 3998 }; 3999 4000 //used by cascadeTo() for gathering all the style properties of each child element into an array for c
4000omparison. 4001 var _getChildStyles2 = function _getChildStyles(e, props, targets) { 4002 var children, i, child, type; 4003 if (e.slice) { 4004 i = e.length; 4005 while (--i > -1) { 4006 _getChildStyles2(e[i], props, targets); 4007 } 4008 return; 4009 } 4010 children = e.childNodes; 4011 i = children.length; 4012 while (--i > -1) { 4013 child = children[i]; 4014 type = child.type; 4015 if (child.style) { 4016 props.push(_getAllStyles(child)); 4017 if (targets) { 4018 targets.push(child); 4019 } 4020 } 4021 if ((type === 1 || type === 9 || type === 11) && child.childNodes.length) { 4022 _getChildStyles2(child, props, targets); 4023 } 4024 } 4025 }; 4026 4027 /** 4028 * Typically only useful for className tweens that may affect child elements, this method creates a TweenLite 4029 * and then compares the style properties of all the target's child elements at the tween's start and end, and 4030 * if any are different, it also creates tweens for those and returns an array containing ALL of the resulting 4031 * tweens (so that you can easily add() them to a TimelineLite, for example). The reason this functionality is 4032 * wrapped into a separate static method of CSSPlugin instead of being integrated into all regular className tweens 4033 * is because it creates entirely new tweens that may have completely different targets than the original tween, 4034 * so if they were all lumped into the original tween instance, it would be inconsistent with the rest of the API 4035 * and it would create other problems. For example: 4036 * - If I create a tween of elementA, that tween instance may suddenly change its target to include 50 other elements (unintuitive if I specifically defined the target I wanted) 4037 * - We can't just create new independent tweens because otherwise, what happens if the original/parent tween is reversed or pause or dropped into a TimelineLite for tight control? You'd expect that tween's behavior to affect all the others. 4038 * - Analyzing every style property of every child before and after the tween is an expensive operation when there are many children, so this behavior shouldn't be imposed on all className tweens by default, especially since it's probably rare that this extra functionality is needed. 4039 * 4040 * @param {Object} target object to be tweened 4041 * @param {number} Duration in seconds (or frames for frames-based tweens) 4042 * @param {Object} Object containing the end values, like {className:"newClass", ease:Linear.easeNone} 4043 * @return {Array} An array of TweenLite instances 4044 */ 4045 _CSSPlugin.cascadeTo = function (target, duration, vars) { 4046 var tween = TweenLite.to(target, duration, vars), 4047 results = [tween], 4048 b = [], 4049 e = [], 4050 targets = [], 4051 _reservedProps = TweenLite._internals.reservedProps, 4052 i, 4053 difs, 4054 p, 4055 from; 4056 target = tween._targets || tween.target; 4057 _getChildStyles2(target, b, targets); 4058 tween.render(duration, true, true); 4059 _getChildStyles2(target, e); 4060 tween.render(0, true, true); 4061 tween._enabled(true); 4062 i = targets.length; 4063 while (--i > -1) { 4064 difs = _cssDif(targets[i], b[i], e[i]); 4065 if (difs.firstMPT) { 4066 difs = difs.difs; 4067 for (p in vars) { 4068 if (_reservedProps[p]) { 4069 difs[p] = vars[p]; 4070 } 4071 } 4072 from = {}; 4073 for (p in difs) { 4074 from[p] = b[i][p]; 4075 } 4076 results.push(TweenLite.fromTo(targets[i], duration, from, difs)); 4077 } 4078 } 4079 return results; 4080 }; 4081 TweenPlugin.activate([_CSSPlugin]); 4082 return _CSSPlugin; 4083 }, true); 4084}); 4085if (_gsScope._gsDefine) { 4086 _gsScope._gsQueue.pop()(); 4087} 4088 4089//export to AMD/RequireJS and CommonJS/Node (precursor to full modular build system coming at a later date) 4090(function (name) { 4091 "use strict"; 4092 4093 var getGlobal = function getGlobal() { 4094 return (_gsScope.GreenSockGlobals || _gsScope)[name]; 4095 }; 4096 if (typeof module !== "undefined" && module.exports) { 4097 //node 4098 require("gsap/TweenLite"); 4099 module.exports = getGlobal(); 4100 } else if (typeof define === "function" && define.amd) { 4101 //AMD 4102 define(["gsap/TweenLite"], getGlobal); 4103 } 4104})("CSSPlugin"); 4105 4106}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 4107},{"gsap/TweenLite":4}],3:[function(require,module,exports){ 4108(function (global){(function (){ 4109"use strict"; 4110 4111function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 4112/*! 4113 * VERSION: 0.16.2 4114 * DATE: 2018-02-15 4115 * UPDATES AND DOCS AT: http://greensock.com 4116 * 4117 * Requires TweenLite and CSSPlugin version 1.17.0 or later (TweenMax contains both TweenLite and CSSPlugin). ThrowPropsPlugin is required for momentum-based continuation of movement after the mouse/touch is released (ThrowPropsPlugin is a membership benefit of Club GreenSock - http://greensock.com/club/). 4118 * 4119 * @license Copyright (c) 2008-2018, GreenSock. All rights reserved. 4120 * This work is subject to the terms at http://greensock.com/standard-license or for
4121 * Club GreenSock members, the software agreement that was issued with your membership. 4122 * 4123 * @author: Jack Doyle, [email protected] 4124 */ 4125var _gsScope = typeof module !== "undefined" && module.exports && typeof global !== "undefined" ? global : void 0 || window; //helps ensure compatibility with AMD/RequireJS and CommonJS/Node 4126(_gsScope._gsQueue || (_gsScope._gsQueue = [])).push(function () { 4127 "use strict"; 4128 4129 _gsScope._gsDefine("utils.Draggable", ["events.EventDispatcher", "TweenLite", "plugins.CSSPlugin"], function (EventDispatcher, TweenLite, CSSPlugin) { 4130 var _tempVarsXY = { 4131 css: {}, 4132 data: "_draggable" 4133 }, 4134 //speed optimization - we reuse the same vars object for x/y TweenLite.set() calls to minimize garbage collection tasks and improve performance. 4135 _tempVarsX = { 4136 css: {}, 4137 data: "_draggable" 4138 }, 4139 _tempVarsY = { 4140 css: {}, 4141 data: "_draggable" 4142 }, 4143 _tempVarsRotation = { 4144 css: {} 4145 }, 4146 _globals = _gsScope._gsDefine.globals, 4147 _tempEvent = {}, 4148 //for populating with pageX/pageY in old versions of IE 4149 _dummyElement = { 4150 style: {} 4151 }, 4152 _doc = _gsScope.document || { 4153 createElement: function createElement() { 4154 return _dummyElement; 4155 } 4156 }, 4157 _docElement = _doc.documentElement || {}, 4158 _createElement = function _createElement(type) { 4159 return _doc.createElementNS ? _doc.createElementNS("http://www.w3.org/1999/xhtml", type) : _doc.createElement(type); 4160 }, 4161 _tempDiv = _createElement("div"), 4162 _emptyArray = [], 4163 _emptyFunc = function _emptyFunc() { 4164 return false; 4165 }, 4166 _RAD2DEG = 180 / Math.PI, 4167 _max = 999999999999999, 4168 _getTime = Date.now || function () { 4169 return new Date().getTime(); 4170 }, 4171 _isOldIE = !!(!_doc.addEventListener && _doc.all), 4172 _placeholderDiv = _doc.createElement("div"), 4173 _renderQueue = [], 4174 _lookup = {}, 4175 //when a Draggable is created, the target gets a unique _gsDragID property that allows gets associated with the Draggable instance for quick lookups in Draggable.get(). This avoids circular references that could cause gc problems. 4176 _lookupCount = 0, 4177 _clickableTagExp = /^(?:a|input|textarea|button|select)$/i, 4178 _dragCount = 0, 4179 //total number of elements currently being dragged 4180 _prefix, 4181 _isMultiTouching, 4182 _isAndroid = _gsScope.navigator && _gsScope.navigator.userAgent.toLowerCase().indexOf("android") !== -1, 4183 //Android handles touch events in an odd way and it's virtually impossible to "feature test" so we resort to UA sniffing 4184 _lastDragTime = 0, 4185 _temp1 = {}, 4186 // a simple object we reuse and populate (usually x/y properties) to conserve memory and improve performance. 4187 _windowProxy = {}, 4188 //memory/performance optimization - we reuse this object during autoScroll to store window-related bounds/offsets. 4189 _slice = function _slice(a) { 4190 //don't use Array.prototype.slice.call(target, 0) because that doesn't work in IE8 with a NodeList that's returned by querySelectorAll() 4191 if (typeof a === "string") { 4192 a = TweenLite.selector(a); 4193 } 4194 if (!a || a.nodeType) { 4195 //if it's not an array, wrap it in one. 4196 return [a]; 4197 } 4198 var b = [], 4199 l = a.length, 4200 i; 4201 for (i = 0; i !== l; b.push(a[i++])); 4202 return b; 4203 }, 4204 _copy = function _copy(obj, factor) { 4205 var copy = {}, 4206 p; 4207 if (factor) { 4208 for (p in obj) { 4209 copy[p] = obj[p] * factor; 4210 } 4211 } else { 4212 for (p in obj) { 4213 copy[p] = obj[p]; 4214 } 4215 } 4216 return copy; 4217 }, 4218 ThrowPropsPlugin, 4219 _renderQueueTick = function _renderQueueTick() { 4220 var i = _renderQueue.length; 4221 while (--i > -1) { 4222 _renderQueue[i](); 4223 } 4224 }, 4225 _addToRenderQueue = function _addToRenderQueue(func) { 4226 _renderQueue.push(func); 4227 if (_renderQueue.length === 1) { 4228 TweenLite.ticker.addEventListener("tick", _renderQueueTick, this, false, 1); 4229 } 4230 }, 4231 _removeFromRenderQueue = function _removeFromRenderQueue(func) { 4232 var i = _renderQueue.length; 4233 while (--i > -1) { 4234 if (_renderQueue[i] === func) { 4235 _renderQueue.splice(i, 1); 4236 } 4237 } 4238 TweenLite.to(_renderQueueTimeout, 0, { 4239 overwrite: "all", 4240 delay: 15, 4241 onComplete: _renderQueueTimeout, 4242 data: "_draggable" 4243 }); //remove the "tick" listener only after the render queue is empty for 15 seconds (to improve performance). Adding/removing it constantly for every click/touch wouldn't deliver optimal speed, and we also don't want the ticker to keep calling the render method when things are idle for long periods of time (we want to improve battery life on mobile devices). 4244 }, 4245 _renderQueueTimeout = function _renderQueueTimeout() { 4246 if (!_renderQueue.length) { 4247 TweenLite.ticker.removeEventListener("tick", _renderQueueTick); 4248 } 4249 }, 4250 _extend = function _extend(obj, defaults) { 4251 var p; 4252 for (p in defaults) { 4253 if (obj[p] === undefined) { 4254 obj[p] = defaults[p]; 4255 } 4256 } 4257 return obj; 4258 }, 4259 _getDocScrollTop = function _getDocScrollTop() { 4260 return window.pageYOffset != null ? window.pageYOffset : _doc.scrollTop != null ? _doc.scrollTop : _docElement.scrollTop || _doc.body.scrollTop || 0; 4261 }, 4262 _getDocScrollLeft = function _getDocScrollLeft() { 4263 return window.pageXOffset != null ? window.pageXOffset : _doc.scrollLeft != null ? _doc.scrollLeft : _docElement.scrollLeft || _doc.body.scrollLeft || 0; 4264 }, 4265 _addScrollListener2 = function _addScrollListener(e, callback) { 4266 _addListener(e, "scroll", callback); 4267 if (!_isRoot(e.parentNode)) { 4268 _addScrollListener2(e.parentNode, callback); 4269 } 4270 }, 4271 _removeScrollListener2 = function _removeScrollListener(e, callback) { 4272 _removeListener(e, "scroll", callback); 4273 if (!_isRoot(e.parentNode)) { 4274 _removeScrollListener2(e.parentNode, callback); 4275 } 4276 }, 4277 _isRoot = function _isRoot(e) { 4278 return !!(!e || e === _docElement || e === _doc || e === _doc.body || e === window || !e.nodeType || !e.parentNode); 4279 }, 4280 _getMaxScroll = function _getMaxScroll(element, axis) { 4281 var dim = axis === "x" ? "Width" : "Height", 4282 scroll = "scroll" + dim, 4283 client = "client" + dim, 4284 body = _doc.body; 4285 return Math.max(0, _isRoot(element) ? Math.max(_docElement[scroll], body[scroll]) - (window["inner" + dim] || _docElement[client] || body[client]) : element[scroll] - element[client]); 4286 }, 4287 _recordMaxScrolls2 = function _recordMaxScrolls(e) { 4288 //records _gsMaxScrollX and _gsMaxScrollY properties for the element and all ancestors up the chain so that we can cap it, otherwise dragging beyond the edges with autoScroll on can endlessly scroll.
4289 var isRoot = _isRoot(e), 4290 x = _getMaxScroll(e, "x"), 4291 y = _getMaxScroll(e, "y"); 4292 if (isRoot) { 4293 e = _windowProxy; 4294 } else { 4295 _recordMaxScrolls2(e.parentNode); 4296 } 4297 e._gsMaxScrollX = x; 4298 e._gsMaxScrollY = y; 4299 e._gsScrollX = e.scrollLeft || 0; 4300 e._gsScrollY = e.scrollTop || 0; 4301 }, 4302 //just used for IE8 and earlier to normalize events and populate pageX/pageY 4303 _populateIEEvent = function _populateIEEvent(e, preventDefault) { 4304 e = e || window.event; 4305 _tempEvent.pageX = e.clientX + _doc.body.scrollLeft + _docElement.scrollLeft; 4306 _tempEvent.pageY = e.clientY + _doc.body.scrollTop + _docElement.scrollTop; 4307 if (preventDefault) { 4308 e.returnValue = false; 4309 } 4310 return _tempEvent; 4311 }, 4312 //grabs the first element it finds (and we include the window as an element), so if it's selector text, it'll feed that value to TweenLite.selector, if it's a jQuery object or some other selector engine's result, it'll grab the first one, and same for an array. If the value doesn't contain a DOM element, it'll just return null. 4313 _unwrapElement = function _unwrapElement(value) { 4314 if (!value) { 4315 return value; 4316 } 4317 if (typeof value === "string") { 4318 value = TweenLite.selector(value); 4319 } 4320 if (value.length && value !== window && value[0] && value[0].style && !value.nodeType) { 4321 value = value[0]; 4322 } 4323 return value === window || value.nodeType && value.style ? value : null; 4324 }, 4325 _checkPrefix = function _checkPrefix(e, p) { 4326 var s = e.style, 4327 capped, 4328 i, 4329 a; 4330 if (s[p] === undefined) { 4331 a = ["O", "Moz", "ms", "Ms", "Webkit"]; 4332 i = 5; 4333 capped = p.charAt(0).toUpperCase() + p.substr(1); 4334 while (--i > -1 && s[a[i] + capped] === undefined) {} 4335 if (i < 0) { 4336 return ""; 4337 } 4338 _prefix = i === 3 ? "ms" : a[i]; 4339 p = _prefix + capped; 4340 } 4341 return p; 4342 }, 4343 _setStyle = function _setStyle(e, p, value) { 4344 var s = e.style; 4345 if (!s) { 4346 return; 4347 } 4348 if (s[p] === undefined) { 4349 p = _checkPrefix(e, p); 4350 } 4351 if (value == null) { 4352 if (s.removeProperty) { 4353 s.removeProperty(p.replace(/([A-Z])/g, "-$1").toLowerCase()); 4354 } else { 4355 //note: old versions of IE use "removeAttribute()" instead of "removeProperty()" 4356 s.removeAttribute(p); 4357 } 4358 } else if (s[p] !== undefined) { 4359 s[p] = value; 4360 } 4361 }, 4362 _getComputedStyle = _doc.defaultView ? _doc.defaultView.getComputedStyle : _emptyFunc, 4363 _horizExp = /(?:Left|Right|Width)/i, 4364 _suffixExp = /(?:\d|\-|\+|=|#|\.)*/g, 4365 _convertToPixels2 = function _convertToPixels(t, p, v, sfx, recurse) { 4366 if (sfx === "px" || !sfx) { 4367 return v; 4368 } 4369 if (sfx === "auto" || !v) { 4370 return 0; 4371 } 4372 var horiz = _horizExp.test(p), 4373 node = t, 4374 style = _tempDiv.style, 4375 neg = v < 0, 4376 pix; 4377 if (neg) { 4378 v = -v; 4379 } 4380 if (sfx === "%" && p.indexOf("border") !== -1) { 4381 pix = v / 100 * (horiz ? t.clientWidth : t.clientHeight); 4382 } else { 4383 style.cssText = "border:0 solid red;position:" + _getStyle(t, "position", true) + ";line-height:0;"; 4384 if (sfx === "%" || !node.appendChild) { 4385 node = t.parentNode || _doc.body; 4386 style[horiz ? "width" : "height"] = v + sfx; 4387 } else { 4388 style[horiz ? "borderLeftWidth" : "borderTopWidth"] = v + sfx; 4389 } 4390 node.appendChild(_tempDiv); 4391 pix = parseFloat(_tempDiv[horiz ? "offsetWidth" : "offsetHeight"]); 4392 node.removeChild(_tempDiv); 4393 if (pix === 0 && !recurse) { 4394 pix = _convertToPixels2(t, p, v, sfx, true); 4395 } 4396 } 4397 return neg ? -pix : pix; 4398 }, 4399 _calculateOffset = function _calculateOffset(t, p) { 4400 //for figuring out "top" or "left" in px when it's "auto". We need to factor in margin with the offsetLeft/offsetTop 4401 if (_getStyle(t, "position", true) !== "absolute") { 4402 return 0; 4403 } 4404 var dim = p === "left" ? "Left" : "Top",
4405 v = _getStyle(t, "margin" + dim, true); 4406 return t["offset" + dim] - (_convertToPixels2(t, p, parseFloat(v), (v + "").replace(_suffixExp, "")) || 0); 4407 }, 4408 _getStyle = function _getStyle(element, prop, keepUnits) { 4409 var rv = (element._gsTransform || {})[prop], 4410 cs; 4411 if (rv || rv === 0) { 4412 return rv; 4413 } else if (element.style[prop]) { 4414 rv = element.style[prop]; 4415 } else if (cs = _getComputedStyle(element)) { 4416 rv = cs.getPropertyValue(prop.replace(/([A-Z])/g, "-$1").toLowerCase()); 4417 rv = rv || cs.length ? rv : cs[prop]; //Opera behaves VERY strangely - length is usually 0 and cs[prop] is the only way to get accurate results EXCEPT when checking for -o-transform which only works with cs.getPropertyValue()! 4418 } else if (element.currentStyle) { 4419 rv = element.currentStyle[prop]; 4420 } 4421 if (rv === "auto" && (prop === "top" || prop === "left")) { 4422 rv = _calculateOffset(element, prop); 4423 } 4424 return keepUnits ? rv : parseFloat(rv) || 0; 4425 }, 4426 _dispatchEvent = function _dispatchEvent(instance, type, callbackName) { 4427 var vars = instance.vars, 4428 callback = vars[callbackName], 4429 listeners = instance._listeners[type]; 4430 if (typeof callback === "function") { 4431 callback.apply(vars[callbackName + "Scope"] || vars.callbackScope || instance, vars[callbackName + "Params"] || [instance.pointerEvent]); 4432 } 4433 if (listeners) { 4434 instance.dispatchEvent(type); 4435 } 4436 }, 4437 _getBounds = function _getBounds(obj, context) { 4438 //accepts any of the following: a DOM element, jQuery object, selector text, or an object defining bounds as {top, left, width, height} or {minX, maxX, minY, maxY}. Returns an object with left, top, width, and height properties. 4439 var e = _unwrapElement(obj), 4440 top, 4441 left, 4442 offset; 4443 if (!e) { 4444 if (obj.left !== undefined) { 4445 offset = _getOffsetTransformOrigin(context); //the bounds should be relative to the origin 4446 return { 4447 left: obj.left - offset.x, 4448 top: obj.top - offset.y, 4449 width: obj.width, 4450 height: obj.height 4451 }; 4452 } 4453 left = obj.min || obj.minX || obj.minRotation || 0; 4454 top = obj.min || obj.minY || 0; 4455 return { 4456 left: left, 4457 top: top, 4458 width: (obj.max || obj.maxX || obj.maxRotation || 0) - left, 4459 height: (obj.max || obj.maxY || 0) - top 4460 }; 4461 } 4462 return _getElementBounds(e, context); 4463 }, 4464 _svgBorderFactor, 4465 _svgBorderScales, 4466 _svgScrollOffset, 4467 _hasBorderBug, 4468 _hasReparentBug, 4469 //some browsers, like Chrome 49, alter the offsetTop/offsetLeft/offsetParent of elements when a non-identity transform is applied. 4470 _setEnvironmentVariables = function _setEnvironmentVariables() { 4471 //some browsers factor the border into the SVG coordinate space, some don't (like Firefox). Some apply transforms to them, some don't. We feature-detect here so we know how to handle the border(s). We can't do this immediately - we must wait for the document.body to exist. 4472 if (!_doc.createElementNS) { 4473 _svgBorderFactor = 0; 4474 _svgBorderScales = false; 4475 return; 4476 } 4477 var div = _createElement("div"), 4478 svg = _doc.createElementNS("http://www.w3.org/2000/svg", "svg"), 4479 wrapper = _createElement("div"), 4480 style = div.style, 4481 parent = _doc.body || _docElement, 4482 isFlex = _getStyle(parent, "display", true) === "flex", 4483 //Firefox bug causes getScreenCTM() to return null when parent is display:flex and the element isn't rendered inside the window (like if it's below the scroll position) 4484 matrix, 4485 e1, 4486 point, 4487 oldValue; 4488 if (_doc.body && _transformProp) { 4489 style.position = "absolute"; 4490 parent.appendChild(wrapper); 4491 wrapper.appendChild(div); 4492 oldValue = div.offsetParent; 4493 wrapper.style[_transformProp] = "rotate(1deg)"; 4494 _hasReparentBug = div.offsetParent === oldValue; 4495 wrapper.style.position = "absolute"; 4496 style.height = "10px"; 4497 oldValue = div.offsetTop; 4498 wrapper.style.border = "5px solid red"; 4499 _hasBorderBug = oldValue !== div.offsetTop; //some browsers, like Firefox 38, cause the offsetTop/Left to be affected by a parent's border. 4500 parent.removeChild(wrapper); 4501 } 4502 style = svg.style; 4503 svg.setAttributeNS(null, "width", "400px"); 4504 svg.setAttributeNS(null, "height", "400px"); 4505 svg.setAttributeNS(null, "viewBox", "0 0 400 400"); 4506 style.display = "block"; 4507 style.boxSizing = "border-box"; 4508 style.border = "0px solid red"; 4509 style.transform = "none"; 4510 // in some browsers (like certain flavors of Android), the getScreenCTM() matrix is contaminated by the scroll position. We can run some logic here to detect that condition, but we ended up not needing this because we found another workaround using getBoundingClientRect(). 4511 div.style.cssText = "width:100px;height:100px;overflow:scroll;-ms-overflow-style:none;"; 4512 parent.appendChild(div); 4513 div.appendChild(svg); 4514 point = svg.createSVGPoint().matrixTransform(svg.getScreenCTM()); 4515 e1 = point.y; 4516 div.scrollTop = 100; 4517 point.x = point.y = 0; 4518 point = point.matrixTransform(svg.getScreenCTM()); 4519 _svgScrollOffset = e1 - point.y < 100.1 ? 0 : e1 - point.y - 150; 4520 div.removeChild(svg); 4521 parent.removeChild(div); 4522 // -- end _svgScrollOffset calculation. 4523 parent.appendChild(svg); 4524 if (isFlex) { 4525 parent.style.display = "block"; //Firefox bug causes getScreenCTM() to return null when parent is display:flex and the element isn't rendered inside the window (like if it's below the scroll position) 4526 } 4527 matrix = svg.getScreenCTM(); 4528 e1 = matrix.e; 4529 style.border = "50px solid red"; 4530 matrix = svg.getScreenCTM(); 4531 if (e1 === 0 && matrix.e === 0 && matrix.f === 0 && matrix.a === 1) { 4532 //Opera has a bunch of bugs - it doesn't adjust the x/y of the matrix, nor does it scale when box-sizing is border-box but it does so elsewhere; to get the correct behavior we set _svgBorderScales to true. 4533 _svgBorderFactor = 1; 4534 _svgBorderScales = true; 4535 } else { 4536 _svgBorderFactor = e1 !== matrix.e ? 1 : 0; 4537 _svgBorderScales = matrix.a !== 1; 4538 } 4539 if (isFlex) { 4540 parent.style.display = "flex"; 4541 } 4542 parent.removeChild(svg); 4543 }, 4544 _supports3D = _checkPrefix(_tempDiv, "perspective") !== "", 4545 // start matrix and point conversion methods... 4546 _transformOriginProp = _checkPrefix(_tempDiv, "transformOrigin").replace(/^ms/g, "Ms").replace(/([A-Z])/g, "-$1").toLowerCase(), 4547 _transformProp = _checkPrefix(_tempDiv, "transform"), 4548 _transformPropCSS = _transformProp.replace(/^ms/g, "Ms").replace(/([A-Z])/g, "-$1").toLowerCase(), 4549 _point1 = {}, 4550 //we reuse _point1 and _point2 objects inside matrix and point conversion methods to conserve memory and minimize garbage collection tasks. 4551 _point2 = {}, 4552 _SVGElement = _gsScope.SVGElement, 4553 _isSVG = function _isSVG(e) { 4554 return !!(_SVGElement && typeof e.getBBox === "function" && e.getCTM && (!e.parentNode || e.parentNode.getBBox && e.parentNode.getCTM)); 4555 }, 4556 _isIE10orBelow = (/MSIE ([0-9]{1,}[\.0-9]{0,})/.exec(navigator.userAgent) || /Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/.exec(navigator.userAgent)) && parseFloat(RegExp.$1) < 11, 4557 //Ideally we'd avoid user agent sniffing, but there doesn't seem to be a way to feature-detect and sense a border-related bug that only affects IE10 and IE9. 4558 _tempTransforms = [], 4559 _tempElements = [], 4560 _getSVGOffsets2 = function _getSVGOffsets(e) { 4561 //SVG elements don't always report offsetTop/offsetLeft/offsetParent at all (I'm looking at you, Firefox 29 and Android), so we have to do some work to manufacture those values. You can pass any SVG element and it'll spit back an object with offsetTop, offsetLeft, offsetParent, scaleX, and scaleY properties. We need the scaleX and scaleY to handle the way SVG can resize itself based on the container. 4562 if (!e.getBoundingClientRect || !e.parentNode || !_transformProp) { 4563 return { 4564 offsetTop: 0, 4565 offsetLeft: 0, 4566 scaleX: 1, 4567 scaleY: 1, 4568 offsetParent: _docElement 4569 }; 4570 } 4571 if (_Draggable.cacheSVGData !== false && e._dCache && e._dCache.lastUpdate === TweenLite.ticker.frame) { 4572 //performance optimization. Assume that if the offsets are requested again on the same tick, we can just feed back the values we already calculated (no need to keep recalculating until another tick elapses). 4573 return e._dCache; 4574 } 4575 var curElement = e, 4576 cache = _cache(e), 4577 eRect, 4578 parentRect, 4579 offsetParent, 4580 cs, 4581 m, 4582 i, 4583 point1, 4584 point2, 4585 borderWidth, 4586 borderHeight, 4587 width, 4588 height; 4589 cache.lastUpdate = TweenLite.ticker.frame; 4590 if (e.getBBox && !cache.isSVGRoot) { 4591 //if it's a nested/child SVG element, we must find the parent SVG canvas and measure the offset from there. 4592 curElement = e.parentNode; 4593 eRect = e.getBBox(); 4594 while (curElement && (curElement.nodeName + "").toLowerCase() !== "svg") { 4595 curElement = curElement.parentNode; 4596 } 4597 cs = _getSVGOffsets2(curElement); 4598 cache.offsetTop = eRect.y * cs.scaleY; 4599 cache.offsetLeft = eRect.x * cs.scaleX; 4600 cache.scaleX = cs.scaleX; 4601 cache.scaleY = cs.scaleY; 4602 cache.offsetParent = curElement || _docElement; 4603 return cache; 4604 } 4605 //only root SVG elements continue here... 4606 offsetParent = cache.offsetParent; 4607 if (offsetParent === _doc.body) { 4608 offsetParent = _docElement; //avoids problems with margins/padding on the body 4609 } 4610 //walk up the ancestors and record any non-identity transforms (and reset them to "none") until we reach the offsetParent. We must do this so that the getBoundingClientRect() is accurate for measuring the offsetTop/offsetLeft. We'll revert the values later... 4611 _tempElements.length = _tempTransforms.length = 0; 4612 while (curElement) {
4613 m = _getStyle(curElement, _transformProp, true); 4614 if (m !== "matrix(1, 0, 0, 1, 0, 0)" && m !== "none" && m !== "translate3d(0px, 0px, 0px)") { 4615 _tempElements.push(curElement); 4616 _tempTransforms.push(curElement.style[_transformProp]); 4617 curElement.style[_transformProp] = "none"; 4618 } 4619 if (curElement === offsetParent) { 4620 break; 4621 } 4622 curElement = curElement.parentNode; 4623 } 4624 parentRect = offsetParent.getBoundingClientRect(); 4625 m = e.getScreenCTM(); 4626 point2 = e.createSVGPoint(); 4627 point1 = point2.matrixTransform(m); 4628 point2.x = point2.y = 10; 4629 point2 = point2.matrixTransform(m); 4630 cache.scaleX = (point2.x - point1.x) / 10; 4631 cache.scaleY = (point2.y - point1.y) / 10; 4632 if (_svgBorderFactor === undefined) { 4633 _setEnvironmentVariables(); 4634 } 4635 if (cache.borderBox && !_svgBorderScales && e.getAttribute("width")) { 4636 //some browsers (like Safari) don't properly scale the matrix to accommodate the border when box-sizing is border-box, so we must calculate it here... 4637 cs = _getComputedStyle(e) || {}; 4638 borderWidth = parseFloat(cs.borderLeftWidth) + parseFloat(cs.borderRightWidth) || 0; 4639 borderHeight = parseFloat(cs.borderTopWidth) + parseFloat(cs.borderBottomWidth) || 0; 4640 width = parseFloat(cs.width) || 0; 4641 height = parseFloat(cs.height) || 0; 4642 cache.scaleX *= (width - borderWidth) / width; 4643 cache.scaleY *= (height - borderHeight) / height; 4644 } 4645 if (_svgScrollOffset) { 4646 //some browsers (like Chrome for Android) have bugs in the way getScreenCTM() is reported (it doesn't factor in scroll position), so we must revert to a more expensive technique for calculating offsetTop/Left. 4647 eRect = e.getBoundingClientRect(); 4648 cache.offsetLeft = eRect.left - parentRect.left; 4649 cache.offsetTop = eRect.top - parentRect.top; 4650 } else { 4651 cache.offsetLeft = point1.x - parentRect.left; 4652 cache.offsetTop = point1.y - parentRect.top; 4653 } 4654 cache.offsetParent = offsetParent; 4655 i = _tempElements.length; 4656 while (--i > -1) { 4657 _tempElements[i].style[_transformProp] = _tempTransforms[i]; 4658 } 4659 return cache; 4660 }, 4661 _getOffsetTransformOrigin = function _getOffsetTransformOrigin(e, decoratee) { 4662 //returns the x/y position of the transformOrigin of the element, in its own local coordinate system (pixels), offset from the top left corner. 4663 decoratee = decoratee || {}; 4664 if (!e || e === _docElement || !e.parentNode || e === window) { 4665 return { 4666 x: 0, 4667 y: 0 4668 }; 4669 } 4670 var cs = _getComputedStyle(e), 4671 v = _transformOriginProp && cs ? cs.getPropertyValue(_transformOriginProp) : "50% 50%", 4672 a = v.split(" "), 4673 x = v.indexOf("left") !== -1 ? "0%" : v.indexOf("right") !== -1 ? "100%" : a[0], 4674 y = v.indexOf("top") !== -1 ? "0%" : v.indexOf("bottom") !== -1 ? "100%" : a[1]; 4675 if (y === "center" || y == null) { 4676 y = "50%"; 4677 } 4678 if (x === "center" || isNaN(parseFloat(x))) { 4679 //remember, the user could flip-flop the values and say "bottom center" or "center bottom", etc. "center" is ambiguous because it could be used to describe horizontal or vertical, hence the isNaN(). If there's an "=" sign in the value, it's relative. 4680 x = "50%"; 4681 } 4682 if (e.getBBox && _isSVG(e)) { 4683 //SVG elements must be handled in a special way because their origins are calculated from the top left. 4684 if (!e._gsTransform) { 4685 TweenLite.set(e, { 4686 x: "+=0", 4687 overwrite: false 4688 }); //forces creation of the _gsTransform where we store all the transform components including xOrigin and yOrigin for SVG elements, as of GSAP 1.15.0 which also takes care of calculating the origin from the upper left corner of the SVG canvas. 4689 if (e._gsTransform.xOrigin === undefined) { 4690 console.log("Draggable requires at least GSAP 1.17.0"); 4691 } 4692 } 4693 v = e.getBBox(); 4694 decoratee.x = e._gsTransform.xOrigin - v.x; 4695 decoratee.y = e._gsTransform.yOrigin - v.y; 4696 } else { 4697 if (e.getBBox && (x + y).indexOf("%") !== -1) { 4698 //Firefox doesn't report offsetWidth/height on <svg> elements. 4699 e = e.getBBox(); 4700 e = { 4701 offsetWidth: e.width, 4702 offsetHeight: e.height 4703 }; 4704 } 4705 decoratee.x = x.indexOf("%") !== -1 ? e.offsetWidth * parseFloat(x) / 100 : parseFloat(x); 4706 decoratee.y = y.indexOf("%") !== -1 ? e.offsetHeight * parseFloat(y) / 100 : parseFloat(y); 4707 } 4708 return decoratee; 4709 }, 4710 _cache = function _cache(e) { 4711 //computes some important values and stores them in a _dCache object attached to the element itself so that we can optimize performance 4712 if (_Draggable.cacheSVGData !== false && e._dCache && e._dCache.lastUpdate === TweenLite.ticker.frame) { 4713 //performance optimization. Assume that if the offsets are requested again on the same tick, we can just feed back the values we already calculated (no need to keep recalculating until another tick elapses). 4714 return e._dCache; 4715 } 4716 var cache = e._dCache = e._dCache || {}, 4717 cs = _getComputedStyle(e), 4718 isSVG = e.getBBox && _isSVG(e), 4719 isSVGRoot = (e.nodeName + "").toLowerCase() === "svg", 4720 curSVG; 4721 cache.isSVG = isSVG; 4722 cache.isSVGRoot = isSVGRoot; 4723 cache.borderBox = cs.boxSizing === "border-box"; 4724 cache.computedStyle = cs; 4725 if (isSVGRoot) { 4726 //some browsers don't report parentNode on SVG elements. 4727 curSVG = e.parentNode || _docElement; 4728 curSVG.insertBefore(_tempDiv, e); 4729 cache.offsetParent = _tempDiv.offsetParent || _docElement; //in some cases, Firefox still reports offsetParent as null. 4730 curSVG.removeChild(_tempDiv); 4731 } else if (isSVG) { 4732 curSVG = e.parentNode; 4733 while (curSVG && (curSVG.nodeName + "").toLowerCase() !== "svg") { 4734 //offsetParent is always the SVG canvas for SVG elements. 4735 curSVG = curSVG.parentNode; 4736 } 4737 cache.offsetParent = curSVG; 4738 } else { 4739 cache.offsetParent = e.offsetParent; 4740 } 4741 return cache; 4742 }, 4743 _getOffset2DMatrix2 = function _getOffset2DMatrix(e, offsetOrigin, parentOffsetOrigin, zeroOr
4743igin, isBase) { 4744 //"isBase" helps us discern context - it should only be true when the element is the base one (the one at which we're starting to walk up the chain). It only matters in cases when it's an <svg> element itself because that's a case when we don't apply scaling. 4745 if (e === window || !e || !e.style || !e.parentNode) { 4746 return [1, 0, 0, 1, 0, 0]; 4747 } 4748 var cache = e._dCache || _cache(e), 4749 parent = e.parentNode, 4750 parentCache = parent._dCache || _cache(parent), 4751 cs = cache.computedStyle, 4752 parentOffsetParent = cache.isSVG ? parentCache.offsetParent : parent.offsetParent, 4753 m, 4754 isRoot, 4755 offsets, 4756 rect, 4757 t, 4758 sx, 4759 sy, 4760 offsetX, 4761 offsetY, 4762 parentRect, 4763 borderTop, 4764 borderLeft, 4765 borderTranslateX, 4766 borderTranslateY; 4767 m = cache.isSVG && (e.style[_transformProp] + "").indexOf("matrix") !== -1 ? e.style[_transformProp] : cs ? cs.getPropertyValue(_transformPropCSS) : e.currentStyle ? e.currentStyle[_transformProp] : "1,0,0,1,0,0"; //some browsers (like Chrome 40) don't correctly report transforms that are applied inline on an SVG element (they don't get included in the computed style), so we double-check here and accept matrix values 4768 if (e.getBBox && (e.getAttribute("transform") + "").indexOf("matrix") !== -1) { 4769 //SVG can store transform data in its "transform" attribute instead of the CSS, so look for that here (only accept matrix()). 4770 m = e.getAttribute("transform"); 4771 } 4772 m = (m + "").match(/(?:\-|\.|\b)(\d|\.|e\-)+/g) || [1, 0, 0, 1, 0, 0]; 4773 if (m.length > 6) { 4774 m = [m[0], m[1], m[4], m[5], m[12], m[13]]; 4775 } 4776 if (zeroOrigin) { 4777 m[4] = m[5] = 0; 4778 } else if (cache.isSVG && (t = e._gsTransform) && (t.xOrigin || t.yOrigin)) { 4779 //SVGs handle origin very differently. Factor in GSAP's handling of origin values here: 4780 m[0] = parseFloat(m[0]); 4781 m[1] = parseFloat(m[1]); 4782 m[2] = parseFloat(m[2]); 4783 m[3] = parseFloat(m[3]); 4784 m[4] = parseFloat(m[4]) - (t.xOrigin - (t.xOrigin * m[0] + t.yOrigin * m[2])); 4785 m[5] = parseFloat(m[5]) - (t.yOrigin - (t.xOrigin * m[1] + t.yOrigin * m[3])); 4786 } 4787 if (offsetOrigin) { 4788 if (_svgBorderFactor === undefined) { 4789 _setEnvironmentVariables(); 4790 } 4791 offsets = cache.isSVG || cache.isSVGRoot ? _getSVGOffsets2(e) : e; 4792 if (cache.isSVG) { 4793 //don't just rely on "instanceof _SVGElement" because if the SVG is embedded via an object tag, it won't work (SVGElement is mapped to a different object)) 4794 rect = e.getBBox(); 4795 parentRect = parentCache.isSVGRoot ? { 4796 x: 0, 4797 y: 0 4798 } : parent.getBBox(); 4799 offsets = { 4800 offsetLeft: rect.x - parentRect.x, 4801 offsetTop: rect.y - parentRect.y, 4802 offsetParent: cache.offsetParent 4803 }; 4804 } else if (cache.isSVGRoot) { 4805 borderTop = parseInt(cs.borderTopWidth, 10) || 0; 4806 borderLeft = parseInt(cs.borderLeftWidth, 10) || 0; 4807 borderTranslateX = (m[0] - _svgBorderFactor) * borderLeft + m[2] * borderTop; 4808 borderTranslateY = m[1] * borderLeft + (m[3] - _svgBorderFactor) * borderTop; 4809 sx = offsetOrigin.x; 4810 sy = offsetOrigin.y; 4811 offsetX = sx - (sx * m[0] + sy * m[2]); //accommodate the SVG root's transforms when the origin isn't in the top left. 4812 offsetY = sy - (sx * m[1] + sy * m[3]); 4813 m[4] = parseFloat(m[4]) + offsetX; 4814 m[5] = parseFloat(m[5]) + offsetY; 4815 offsetOrigin.x -= offsetX; 4816 offsetOrigin.y -= offsetY; 4817 sx = offsets.scaleX; 4818 sy = offsets.scaleY; 4819 if (!isBase) { 4820 //when getting the matrix for a root <svg> element itself (NOT in the context of an SVG element that's nested inside of it like a <path>), we do NOT apply the scaling! 4821 offsetOrigin.x *= sx; 4822 offsetOrigin.y *= sy; 4823 } 4824 m[0] *= sx; 4825 m[1] *= sy; 4826 m[2] *= sx; 4827 m[3] *= sy; 4828 if (!_isIE10orBelow) { 4829 offsetOrigin.x += borderTranslateX; 4830 offsetOrigin.y += borderTranslateY; 4831 } 4832 if (parentOffsetParent === _doc.body && offsets.offsetParent === _docElement) { 4833 //to avoid issues with margin/padding on the <body>, we always set the offsetParent to _docElement in the _getSVGOffsets() function but there's a condition we check later in this function for (parentOffsetParent === offsets.offsetParent) which w
4833ould fail if we don't run this logic. In other words, parentOffsetParent may be <body> and the <svg>'s offsetParent is also <body> but artificially set to _docElement to avoid margin/padding issues. 4834 parentOffsetParent = _docElement; 4835 } 4836 } else if (!_hasBorderBug && e.offsetParent) { 4837 offsetOrigin.x += parseInt(_getStyle(e.offsetParent, "borderLeftWidth"), 10) || 0; 4838 offsetOrigin.y += parseInt(_getStyle(e.offsetParent, "borderTopWidth"), 10) || 0; 4839 } 4840 isRoot = parent === _docElement || parent === _doc.body; 4841 m[4] = Number(m[4]) + offsetOrigin.x + (offsets.offsetLeft || 0) - parentOffsetOrigin.x - (isRoot ? 0 : parent.scrollLeft || 0); 4842 m[5] = Number(m[5]) + offsetOrigin.y + (offsets.offsetTop || 0) - parentOffsetOrigin.y - (isRoot ? 0 : parent.scrollTop || 0); 4843 if (parent && _getStyle(e, "position", cs) === "fixed") { 4844 //fixed position elements should factor in the scroll position of the document. 4845 m[4] += _getDocScrollLeft(); 4846 m[5] += _getDocScrollTop(); 4847 } 4848 if (parent && parent !== _docElement && parentOffsetParent === offsets.offsetParent && !parentCache.isSVG && (!_hasReparentBug || _getOffset2DMatrix2(parent).join("") === "100100")) { 4849 offsets = parentCache.isSVGRoot ? _getSVGOffsets2(parent) : parent; 4850 m[4] -= offsets.offsetLeft || 0; 4851 m[5] -= offsets.offsetTop || 0; 4852 if (!_hasBorderBug && parentCache.offsetParent && !cache.isSVG && !cache.isSVGRoot) { 4853 m[4] -= parseInt(_getStyle(parentCache.offsetParent, "borderLeftWidth"), 10) || 0; 4854 m[5] -= parseInt(_getStyle(parentCache.offsetParent, "borderTopWidth"), 10) || 0; 4855 } 4856 } 4857 } 4858 return m; 4859 }, 4860 _getConcatenatedMatrix = function _getConcatenatedMatrix(e, invert) { 4861 if (!e || e === window || !e.parentNode) { 4862 return [1, 0, 0, 1, 0, 0]; 4863 } 4864 //note: we keep reusing _point1 and _point2 in order to minimize memory usage and garbage collection chores. 4865 var originOffset = _getOffsetTransformOrigin(e, _point1), 4866 parentOriginOffset = _getOffsetTransformOrigin(e.parentNode, _point2), 4867 m = _getOffset2DMatrix2(e, originOffset, parentOriginOffset, false, !invert), 4868 a, 4869 b, 4870 c, 4871 d, 4872 tx, 4873 ty, 4874 m2, 4875 determinant; 4876 while ((e = e.parentNode) && e.parentNode && e !== _docElement) { 4877 originOffset = parentOriginOffset; 4878 parentOriginOffset = _getOffsetTransformOrigin(e.parentNode, originOffset === _point1 ? _point2 : _point1); 4879 m2 = _getOffset2DMatrix2(e, originOffset, parentOriginOffset); 4880 a = m[0]; 4881 b = m[1]; 4882 c = m[2]; 4883 d = m[3]; 4884 tx = m[4]; 4885 ty = m[5]; 4886 m[0] = a * m2[0] + b * m2[2]; 4887 m[1] = a * m2[1] + b * m2[3]; 4888 m[2] = c * m2[0] + d * m2[2]; 4889 m[3] = c * m2[1] + d * m2[3]; 4890 m[4] = tx * m2[0] + ty * m2[2] + m2[4]; 4891 m[5] = tx * m2[1] + ty * m2[3] + m2[5]; 4892 } 4893 if (invert) { 4894 a = m[0]; 4895 b = m[1]; 4896 c = m[2]; 4897 d = m[3]; 4898 tx = m[4]; 4899 ty = m[5]; 4900 determinant = a * d - b * c; 4901 m[0] = d / determinant; 4902 m[1] = -b / determinant; 4903 m[2] = -c / determinant; 4904 m[3] = a / determinant; 4905 m[4] = (c * ty - d * tx) / determinant; 4906 m[5] = -(a * ty - b * tx) / determinant; 4907 } 4908 return m; 4909 }, 4910 _localToGlobal = function _localToGlobal(e, p, fromTopLeft, decoratee, zeroOrigin) { 4911 e = _unwrapElement(e); 4912 var m = _getConcatenatedMatrix(e, false, zeroOrigin), 4913 x = p.x, 4914 y = p.y; 4915 if (fromTopLeft) { 4916 _getOffsetTransformOrigin(e, p); 4917 x -= p.x; 4918 y -= p.y; 4919 } 4920 decoratee = decoratee === true ? p : decoratee || {}; 4921 decoratee.x = x * m[0] + y * m[2] + m[4]; 4922 decoratee.y = x * m[1] + y * m[3] + m[5]; 4923 return decoratee; 4924 }, 4925 _localizePoint = function _localizePoint(p, localToGlobal, globalToLocal) { 4926 var x = p.x * localToGlobal[0] + p.y * localToGlobal[2] + localToGlobal[4], 4927 y = p.x * localToGlobal[1] + p.y * localToGlobal[3] + localToGlobal[5]; 4928 p.x = x * globalToLocal[0] + y * globalToLocal[2] + globalToLocal[4]; 4929 p.y = x * globalToLocal[1] + y * globalToLocal[3] + globalToLocal[5]; 4930 return p; 4931 }, 4932 _getElementBounds = function _getElementBounds(e, context, fromTopLeft) { 4933 if (!(e = _unwrapElement(e))) { 4934 return null; 4935 } 4936 context = _unwrapElement(context); 4937 var isSVG = e.getBBox && _isSVG(e), 4938 origin, 4939 left, 4940 right, 4941 top, 4942 bottom, 4943 mLocalToGlobal, 4944 mGlobalToLocal, 4945 p1, 4946 p2, 4947 p3, 4948 p4, 4949 bbox, 4950 width, 4951 height, 4952 cache, 4953 borderLeft, 4954 borderTop,
4955 viewBox, 4956 viewBoxX, 4957 viewBoxY, 4958 computedDimensions, 4959 cs; 4960 if (e === window) { 4961 top = _getDocScrollTop(); 4962 left = _getDocScrollLeft(); 4963 right = left + (_docElement.clientWidth || e.innerWidth || _doc.body.clientWidth || 0); 4964 bottom = top + ((e.innerHeight || 0) - 20 < _docElement.clientHeight ? _docElement.clientHeight : e.innerHeight || _doc.body.clientHeight || 0); //some browsers (like Firefox) ignore absolutely positioned elements, and collapse the height of the documentElement, so it could be 8px, for example, if you have just an absolutely positioned div. In that case, we use the innerHeight to resolve this. 4965 } else if (context === undefined || context === window) { 4966 return e.getBoundingClientRect(); 4967 } else { 4968 origin = _getOffsetTransformOrigin(e); 4969 left = -origin.x; 4970 top = -origin.y; 4971 if (isSVG) { 4972 bbox = e.getBBox(); 4973 width = bbox.width; 4974 height = bbox.height; 4975 } else if ((e.nodeName + "").toLowerCase() !== "svg" && e.offsetWidth) { 4976 //Chrome dropped support for "offsetWidth" on SVG elements 4977 width = e.offsetWidth; 4978 height = e.offsetHeight; 4979 } else { 4980 computedDimensions = _getComputedStyle(e); 4981 width = parseFloat(computedDimensions.width); 4982 height = parseFloat(computedDimensions.height); 4983 } 4984 right = left + width; 4985 bottom = top + height; 4986 if (e.nodeName.toLowerCase() === "svg" && !_isOldIE) { 4987 //root SVG elements are a special beast because they have 2 types of scaling - transforms on themselves as well as the stretching of the SVG canvas itself based on the outer size and the viewBox. If, for example, the SVG's viewbox is "0 0 100 100" but the CSS is set to width:200px; height:200px, that'd make it appear at 2x scale even though the element itself has no CSS transforms but the offsetWidth/offsetHeight are based on that css, not the viewBox so we need to adjust them accordingly. 4988 cache = _getSVGOffsets2(e); 4989 cs = cache.computedStyle || {};
4990 viewBox = (e.getAttribute("viewBox") || "0 0").split(" "); 4991 viewBoxX = parseFloat(viewBox[0]); 4992 viewBoxY = parseFloat(viewBox[1]); 4993 borderLeft = parseFloat(cs.borderLeftWidth) || 0; 4994 borderTop = parseFloat(cs.borderTopWidth) || 0; 4995 right -= width - (width - borderLeft) / cache.scaleX - viewBoxX; 4996 bottom -= height - (height - borderTop) / cache.scaleY - viewBoxY; 4997 left -= borderLeft / cache.scaleX - viewBoxX; 4998 top -= borderTop / cache.scaleY - viewBoxY; 4999 if (computedDimensions) { 5000 //when we had to use computed styles, factor in the border now. 5001 right += (parseFloat(cs.borderRightWidth) + borderLeft) / cache.scaleX; 5002 bottom += (borderTop + parseFloat(cs.borderBottomWidth)) / cache.scaleY; 5003 } 5004 } 5005 } 5006 if (e === context) { 5007 return { 5008 left: left, 5009 top: top, 5010 width: right - left, 5011 height: bottom - top 5012 }; 5013 } 5014 mLocalToGlobal = _getConcatenatedMatrix(e); 5015 mGlobalToLocal = _getConcatenatedMatrix(context, true); 5016 p1 = _localizePoint({ 5017 x: left, 5018 y: top 5019 }, mLocalToGlobal, mGlobalToLocal); 5020 p2 = _localizePoint({ 5021 x: right, 5022 y: top 5023 }, mLocalToGlobal, mGlobalToLocal); 5024 p3 = _localizePoint({ 5025 x: right, 5026 y: bottom 5027 }, mLocalToGlobal, mGlobalToLocal); 5028 p4 = _localizePoint({ 5029 x: left, 5030 y: bottom 5031 }, mLocalToGlobal, mGlobalToLocal); 5032 left = Math.min(p1.x, p2.x, p3.x, p4.x); 5033 top = Math.min(p1.y, p2.y, p3.y, p4.y); 5034 _temp1.x = _temp1.y = 0; 5035 if (fromTopLeft) { 5036 _getOffsetTransformOrigin(context, _temp1); 5037 } 5038 return { 5039 left: left + _temp1.x, 5040 top: top + _temp1.y, 5041 width: Math.max(p1.x, p2.x, p3.x, p4.x) - left, 5042 height: Math.max(p1.y, p2.y, p3.y, p4.y) - top 5043 }; 5044 }, 5045 // end matrix and point conversion methods 5046 5047 _isArrayLike = function _isArrayLike(e) { 5048 return e && e.length && e[0] && (e[0].nodeType && e[0].style && !e.nodeType || e[0].length && e[0][0]) ? true : false; //could be an array of jQuery objects too, so accommodate that. 5049 }, 5050 _flattenArray = function _flattenArray(a) { 5051 var result = [], 5052 l = a.length, 5053 i, 5054 e, 5055 j; 5056 for (i = 0; i < l; i++) { 5057 e = a[i]; 5058 if (_isArrayLike(e)) { 5059 j = e.length; 5060 for (j = 0; j < e.length; j++) { 5061 result.push(e[j]); 5062 } 5063 } else if (e && e.length !== 0) { 5064 result.push(e); 5065 } 5066 } 5067 return result; 5068 }, 5069 _isTouchDevice = "ontouchstart" in _docElement && "orientation" in window, 5070 _touchEventLookup = function (types) { 5071 //we create an object that makes it easy to translate touch event types into their "pointer" counterparts if we're in a browser that uses those instead. Like IE10 uses "MSPointerDown" instead of "touchstart", for example. 5072 var standard = types.split(","), 5073 converted = (_tempDiv.onpointerdown !== undefined ? "pointerdown,pointermove,pointerup,pointercancel" : _tempDiv.onmspointerdown !== undefined ? "MSPointerDown,MSPointerMove,MSPointerUp,MSPointerCancel" : types).split(","), 5074 obj = {}, 5075 i = 4; 5076 while (--i > -1) { 5077 obj[standard[i]] = converted[i]; 5078 obj[converted[i]] = standard[i]; 5079 } 5080 return obj; 5081 }("touchstart,touchmove,touchend,touchcancel"), 5082 _addListener = function _addListener(element, type, func, capture) { 5083 if (element.addEventListener) { 5084 element.addEventListener(_touchEventLookup[type], func, capture); 5085 if (type !== _touchEventLookup[type]) { 5086 //some browsers actually support both, so must we. 5087 element.addEventListener(type, func, capture); 5088 } 5089 } else if (element.attachEvent) { 5090 element.attachEvent("on" + type, func); 5091 } 5092 }, 5093 _removeListener = function _removeListener(element, type, func) { 5094 if (element.removeEventListener) { 5095 element.removeEventListener(_touchEventLookup[type], func); 5096 if (type !== _touchEventLookup[type]) { 5097 element.removeEventListener(type, func); 5098 } 5099 } else if (element.detachEvent) { 5100 element.detachEvent("on" + type, func); 5101 } 5102 }, 5103 _hasTouchID = function _hasTouchID(list, ID) { 5104 var i = list.length; 5105 while (--i > -1) { 5106 if (list[i].identifier === ID) { 5107 return true; 5108 } 5109 } 5110 return false;
5111 }, 5112 _onMultiTouchDocumentEnd2 = function _onMultiTouchDocumentEnd(e) { 5113 _isMultiTouching = e.touches && _dragCount < e.touches.length; 5114 _removeListener(e.target, "touchend", _onMultiTouchDocumentEnd2); 5115 }, 5116 _onMultiTouchDocument = function _onMultiTouchDocument(e) { 5117 _isMultiTouching = e.touches && _dragCount < e.touches.length; 5118 _addListener(e.target, "touchend", _onMultiTouchDocumentEnd2); 5119 }, 5120 _parseThrowProps = function _parseThrowProps(draggable, snap, max, min, factor, forceZeroVelocity) { 5121 var vars = {}, 5122 a, 5123 i, 5124 l; 5125 if (snap) { 5126 if (factor !== 1 && snap instanceof Array) { 5127 //some data must be altered to make sense, like if the user passes in an array of rotational values in degrees, we must convert it to radians. Or for scrollLeft and scrollTop, we invert the values. 5128 vars.end = a = []; 5129 l = snap.length; 5130 if (_typeof(snap[0]) === "object") { 5131 //if the array is populated with objects, like points ({x:100, y:200}), make copies before multiplying by the factor, otherwise we'll mess up the originals and the user may reuse it elsewhere. 5132 for (i = 0; i < l; i++) { 5133 a[i] = _copy(snap[i], factor); 5134 } 5135 } else { 5136 for (i = 0; i < l; i++) { 5137 a[i] = snap[i] * factor; 5138 } 5139 } 5140 max += 1.1; //allow 1.1 pixels of wiggle room when snapping in order to work around some browser inconsistencies in the way bounds are reported which can make them roughly a pixel off. For example, if "snap:[-$('#menu').width(), 0]" was defined and #menu had a wrapper that was used as the bounds, some browsers would be one pixel off, making the minimum -752 for example when snap was [-753,0], thus instead of snapping to -753, it would snap to 0 since -753 was below the minimum. 5141 min -= 1.1; 5142 } else if (typeof snap === "function") { 5143 vars.end = function (value) { 5144 var result = snap.call(draggable, value), 5145 copy, 5146 p; 5147 if (factor !== 1) { 5148 if (_typeof(result) === "object") { 5149 copy = {}; 5150 for (p in result) { 5151 copy[p] = result[p] * factor; 5152 } 5153 result = copy; 5154 } else { 5155 result *= factor; 5156 } 5157 } 5158 return result; //we need to ensure that we can scope the function call to the Draggable instance itself so that users can access important values like maxX, minX, maxY, minY, x, and
5158y from within that function. 5159 }; 5160 } else { 5161 vars.end = snap; 5162 } 5163 } 5164 if (max || max === 0) { 5165 vars.max = max; 5166 } 5167 if (min || min === 0) { 5168 vars.min = min; 5169 } 5170 if (forceZeroVelocity) { 5171 vars.velocity = 0; 5172 } 5173 return vars; 5174 }, 5175 _isClickable2 = function _isClickable(e) { 5176 //sometimes it's convenient to mark an element as clickable by adding a data-clickable="true" attribute (in which case we won't preventDefault() the mouse/touch event). This method checks if the element is an <a>, <input>, or <button> or has an onclick or has the data-clickable or contentEditable attribute set to true (or any of its parent elements). 5177 var data; 5178 return !e || !e.getAttribute || e.nodeName === "BODY" ? false : (data = e.getAttribute("data-clickable")) === "true" || data !== "false" && (e.onclick || _clickableTagExp.test(e.nodeName + "") || e.getAttribute("contentEditable") === "true") ? true : _isClickable2(e.parentNode); 5179 }, 5180 _setSelectable = function _setSelectable(elements, selectable) { 5181 var i = elements.length, 5182 e; 5183 while (--i > -1) { 5184 e = elements[i]; 5185 e.ondragstart = e.onselectstart = selectable ? null : _emptyFunc; 5186 _setStyle(e, "userSelect", selectable ? "text" : "none"); 5187 } 5188 }, 5189 _addPaddingBR, 5190 _addPaddingLeft = function () { 5191 //this function is in charge of analyzing browser behavior related to padding. It sets the _addPaddingBR to true if the browser doesn't normally factor in the bottom or right padding on the element inside the scrolling area, and it sets _addPaddingLeft to true if it's a browser that requires the extra offset (offsetLeft) to be added to the paddingRight (like Opera). 5192 var div = _doc.createElement("div"), 5193 child = _doc.createElement("div"), 5194 childStyle = child.style, 5195 parent = _doc.body || _tempDiv, 5196 val; 5197 childStyle.display = "inline-block"; 5198 childStyle.position = "relative"; 5199 div.style.cssText = child.innerHTML = "width:90px; height:40px; padding:10px; overflow:auto; visibility: hidden"; 5200 div.appendChild(child); 5201 parent.appendChild(div); 5202 _addPaddingBR = child.offsetHeight + 18 > div.scrollHeight; //div.scrollHeight should be child.offsetHeight + 20 because of the 10px of padding on each side, but some browsers ignore one side. We allow a 2px margin of error. 5203 childStyle.width = "100%"; 5204 if (!_transformProp) { 5205 childStyle.paddingRight = "500px"; 5206 val = div.scrollLeft = div.scrollWidth - div.clientWidth; 5207 childStyle.left = "-90px"; 5208 val = val !== div.scrollLeft; 5209 } 5210 parent.removeChild(div); 5211 return val; 5212 }(), 5213 //The ScrollProxy class wraps an element's contents into another div (we call it "content") that we either add padding when necessary or apply a translate3d() transform in order to overscroll (scroll past the boundaries). This allows us to simply set the scrollTop/scrollLeft (or top/left for easier reverse-axis orientation, which is what we do in Draggable) and it'll do all the work for us. For example, if we tried setting scrollTop to -100 on a normal DOM element, it wouldn't work - it'd look the same as setting it to 0, but if we set scrollTop of a ScrollProxy to -100, it'll give the correct appearance by either setting paddingTop of the wrapper to 100 or applying a 100-pixel translateY. 5214 ScrollProxy = function ScrollProxy(element, vars) { 5215 element = _unwrapElement(element); 5216 vars = vars || {}; 5217 var content = _doc.createElement("div"), 5218 style = content.style, 5219 node = element.firstChild, 5220 offsetTop = 0, 5221 offsetLeft = 0, 5222 prevTop = element.scrollTop, 5223 prevLeft = element.scrollLeft, 5224 scrollWidth = element.scrollWidth, 5225 scrollHeight = element.scrollHeight, 5226 extraPadRight = 0, 5227 maxLeft = 0, 5228 maxTop = 0, 5229 elementWidth, 5230 elementHeight, 5231 contentHeight, 5232 nextNode, 5233 transformStart, 5234 transformEnd; 5235 if (_supports3D && vars.force3D !== false) { 5236 transformStart = "translate3d("; 5237 transformEnd = "px,0px)"; 5238 } else if (_transformProp) { 5239 transformStart = "translate("; 5240 transformEnd = "px)"; 5241 } 5242 this.scrollTop = function (value, force) { 5243 if (!arguments.length) { 5244 return -this.top(); 5245 } 5246 this.top(-value, force); 5247 }; 5248 this.scrollLeft = function (value, force) { 5249 if (!arguments.length) { 5250 return -this.left(); 5251 } 5252 this.left(-value, force); 5253 }; 5254 this.left = function (value, force) { 5255 if (!arguments.length) { 5256 return -(element.scrollLeft + offsetLeft); 5257 } 5258 var dif = element.scrollLeft - prevLeft, 5259 oldOffset = offsetLeft; 5260 if ((dif > 2 || dif < -2) && !force) { 5261 //if the user interacts with the scrollbar (or something else scrolls it, like the mouse wheel), we should kill any tweens of the ScrollProxy. 5262 prevLeft = element.scrollLeft; 5263 TweenLite.killTweensOf(this, true, { 5264 left: 1, 5265 scrollLeft: 1 5266 }); 5267 this.left(-prevLeft); 5268 if (vars.onKill) { 5269 vars.onKill(); 5270 } 5271 return; 5272 } 5273 value = -value; //invert because scrolling works in the opposite direction 5274 if (value < 0) { 5275 offsetLeft = value - 0.5 | 0; 5276 value = 0; 5277 } else if (value > maxLeft) { 5278 offsetLeft = value - maxLeft | 0; 5279 value = maxLeft; 5280 } else { 5281 offsetLeft = 0; 5282 } 5283 if (offsetLeft || oldOffset) { 5284 if (transformStart) { 5285 if (!this._suspendTransforms) { 5286 style[_transformProp] = transformStart + -offsetLeft + "px," + -offsetTop + transformEnd; 5287 } 5288 } else { 5289 style.left = -offsetLeft + "px"; 5290 } 5291 if (_addPaddingLeft && offsetLeft + extraPadRight >= 0) { 5292 style.paddingRight = offsetLeft + extraPadRight + "px"; 5293 } 5294 } 5295 element.scrollLeft = value | 0; 5296 prevLeft = element.scrollLeft; //don't merge this with the line above because some browsers adjsut the scrollLeft after it's set, so in order to be 100% accurate in tracking it, we need to ask the browser to report it. 5297 }; 5298 this.top = function (value, force) { 5299 if (!arguments.length) { 5300 return -(element.scrollTop + offsetTop); 5301 } 5302 var dif = element.scrollTop - prevTop, 5303 oldOffset = offsetTop; 5304 if ((dif > 2 || dif < -2) && !force) { 5305 //if the user interacts with the scrollbar (or something else scrolls it, like the mouse wheel), we should kill any tweens of the ScrollProxy. 5306 prevTop = element.scrollTop; 5307 TweenLite.killTweensOf(this, true, { 5308 top: 1, 5309 scrollTop: 1 5310 }); 5311 this.top(-prevTop); 5312 if (vars.onKill) { 5313 vars.onKill(); 5314 } 5315 return; 5316 } 5317 value = -value; //invert because scrolling works in the opposite direction 5318 if (value < 0) { 5319 offsetTop = value - 0.5 | 0; 5320 value = 0; 5321 } else if (value > maxTop) { 5322 offsetTop = value - maxTop | 0; 5323 value = maxTop; 5324 } else { 5325 offsetTop = 0; 5326 } 5327 if (offsetTop || oldOffset) { 5328 if (transformStart) { 5329 if (!this._suspendTransforms) { 5330 style[_transformProp] = transformStart + -offsetLeft + "px," + -offsetTop + transformEnd; 5331 } 5332 } else { 5333 style.top = -offsetTop + "px"; 5334 } 5335 } 5336 element.scrollTop = value | 0; 5337 prevTop = element.scrollTop; 5338 }; 5339 this.maxScrollTop = function () { 5340 return maxTop; 5341 }; 5342 this.maxScrollLeft = function () { 5343 return maxLeft; 5344 }; 5345 this.disable = function () { 5346 node = content.firstChild; 5347 while (node) { 5348 nextNode = node.nextSibling; 5349 element.appendChild(node); 5350 node = nextNode; 5351 } 5352 if (element === content.parentNode) { 5353 //in case disable() is called when it's already disabled. 5354 element.removeChild(content); 5355 } 5356 }; 5357 this.enable = function () { 5358 node = element.firstChild; 5359 if (node === content) { 5360 return; 5361 } 5362 while (node) { 5363 nextNode = node.nextSibling; 5364 content.appendChild(node); 5365 node = nextNode; 5366 } 5367 element.appendChild(content); 5368 this.calibrate(); 5369 }; 5370 this.calibrate = function (force) { 5371 var widthMatches = element.clientWidth === elementWidth, 5372 x, 5373 y; 5374 prevTop = element.scrollTop; 5375 prevLeft = element.scrollLeft; 5376 if (widthMatches && element.clientHeight === elementHeight && content.offsetHeight === contentHeight && scrollWidth === element.scrollWidth && scrollHeight === element.scrollHeight && !force) { 5377 return; //no need to recalculate things if the width and height haven't changed. 5378 } 5379 if (offsetTop || offsetLeft) { 5380 x = this.left(); 5381 y = this.top(); 5382 this.left(-element.scrollLeft); 5383 this.top(-element.scrollTop); 5384 } 5385 //first, we need to remove any width constraints to see how the content naturally flows so that we can see if it's wider than the containing element. If so, we've got to re
5385cord the amount of overage so that we can apply that as padding in order for browsers to correctly handle things. Then we switch back to a width of 100% (without that, some browsers don't flow the content correctly) 5386 if (!widthMatches || force) { 5387 style.display = "block"; 5388 style.width = "auto"; 5389 style.paddingRight = "0px"; 5390 extraPadRight = Math.max(0, element.scrollWidth - element.clientWidth); 5391 //if the content is wider than the container, we need to add the paddingLeft and paddingRight in order for things to behave correctly. 5392 if (extraPadRight) { 5393 extraPadRight += _getStyle(element, "paddingLeft") + (_addPaddingBR ? _getStyle(element, "paddingRight") : 0); 5394 } 5395 } 5396 style.display = "inline-block"; 5397 style.position = "relative"; 5398 style.overflow = "visible"; 5399 style.verticalAlign = "top"; 5400 style.width = "100%"; 5401 style.paddingRight = extraPadRight + "px"; 5402 //some browsers neglect to factor in the bottom padding when calculating the scrollHeight, so we need to add that padding to the content when that happens. Allow a 2px margin for error 5403 if (_addPaddingBR) { 5404 style.paddingBottom = _getStyle(element, "paddingBottom", true); 5405 } 5406 if (_isOldIE) { 5407 style.zoom = "1"; 5408 } 5409 elementWidth = element.clientWidth; 5410 elementHeight = element.clientHeight; 5411 scrollWidth = element.scrollWidth; 5412 scrollHeight = element.scrollHeight; 5413 maxLeft = element.scrollWidth - elementWidth; 5414 maxTop = element.scrollHeight - elementHeight; 5415 contentHeight = content.offsetHeight; 5416 style.display = "block"; 5417 if (x || y) { 5418 this.left(x); 5419 this.top(y); 5420 } 5421 }; 5422 this.content = content; 5423 this.element = element; 5424 this._suspendTransforms = false; 5425 this.enable(); 5426 }, 5427 _Draggable = function Draggable(target, vars) { 5428 EventDispatcher.call(this, target); 5429 target = _unwrapElement(target); //in case the target is a selector object or selector text 5430 if (!ThrowPropsPlugin) { 5431 ThrowPropsPlugin = _globals.com.greensock.plugins.ThrowPropsPlugin; 5432 } 5433 this.vars = vars = _copy(vars || {}); 5434 this.target = target; 5435 this.x = this.y = this.rotation = 0; 5436 this.dragResistance = parseFloat(vars.dragResistance) || 0; 5437 this.edgeResistance = isNaN(vars.edgeResistance) ? 1 : parseFloat(vars.edgeResistance) || 0; 5438 this.lockAxis = vars.lockAxis; 5439 this.autoScroll = vars.autoScroll || 0; 5440 this.lockedAxis = null; 5441 this.allowEventDefault = !!vars.allowEventDefault; 5442 var type = (vars.type || (_isOldIE ? "top,left" : "x,y")).toLowerCase(), 5443 xyMode = type.indexOf("x") !== -1 || type.indexOf("y") !== -1, 5444 rotationMode = type.indexOf("rotation") !== -1, 5445 xProp = rotationMode ? "rotation" : xyMode ? "x" : "left", 5446 yProp = xyMode ? "y" : "top", 5447 allowX = type.indexOf("x") !== -1 || type.indexOf("left") !== -1 || type === "scroll", 5448 allowY = type.indexOf("y") !== -1 || type.indexOf("top") !== -1 || type === "scroll", 5449 minimumMovement = vars.minimumMovement || 2, 5450 self = this, 5451 triggers = _slice(vars.trigger || vars.handle || target), 5452 killProps = {}, 5453 dragEndTime = 0, 5454 checkAutoScrollBounds = false, 5455 autoScrollMarginTop = vars.autoScrollMarginTop || 40, 5456 autoScrollMarginRight = vars.autoScrollMarginRight || 40, 5457 autoScrollMarginBottom = vars.autoScrollMarginBottom || 40, 5458 autoScrollMarginLeft = vars.autoScrollMarginLeft || 40, 5459 isClickable = vars.clickableTest || _isClickable2, 5460 clickTime = 0, 5461 enabled, 5462 scrollProxy, 5463 startPointerX, 5464 startPointerY, 5465 startElementX, 5466 startElementY, 5467 hasBounds, 5468 hasDragCallback, 5469 maxX, 5470 minX, 5471 maxY, 5472 minY, 5473 tempVars, 5474 cssVars, 5475 touch, 5476 touchID, 5477 rotationOrigin, 5478 dirty, 5479 old, 5480 snapX, 5481 snapY, 5482 snapXY, 5483 isClicking, 5484 touchEventTarget, 5485 matrix, 5486 interrupted, 5487 startScrollTop, 5488 startScrollLeft, 5489 applyObj, 5490 allowNativeTouchScrolling, 5491 touchDragAxis, 5492 isDispatching, 5493 clickDispatch, 5494 trustedClickDispatch, 5495 onContextMenu = function onContextMenu(e) { 5496 //used to prevent long-touch from triggering a context menu. 5497 if (self.isPressed && e.which < 2) {
vendor: 4,204 bytes, lines 5498-5571
5498 self.endDrag(); 5499 } else { 5500 e.preventDefault(); 5501 e.stopPropagation(); 5502 return false; 5503 } 5504 }, 5505 //this method gets called on every tick of TweenLite.ticker which allows us to synchronize the renders to the core engine (which is typically synchronized with the display refresh via requestAnimationFrame). This is an optimization - it's better than applying the values inside the "mousemove" or "touchmove" event handler which may get called many times inbetween refreshes. 5506 render = function render(suppressEvents) { 5507 if (self.autoScroll && self.isDragging && (checkAutoScrollBounds || dirty)) { 5508 var e = target, 5509 autoScrollFactor = self.autoScroll * 15, 5510 //multiplying by 15 just gives us a better "feel" speed-wise. 5511 parent, 5512 isRoot, 5513 rect, 5514 pointerX, 5515 pointerY, 5516 changeX, 5517 changeY, 5518 gap; 5519 checkAutoScrollBounds = false; 5520 _windowProxy.scrollTop = window.pageYOffset != null ? window.pageYOffset : _docElement.scrollTop != null ? _docElement.scrollTop : _doc.body.scrollTop; 5521 _windowProxy.scrollLeft = window.pageXOffset != null ? window.pageXOffset : _docElement.scrollLeft != null ? _docElement.scrollLeft : _doc.body.scrollLeft; 5522 pointerX = self.pointerX - _windowProxy.scrollLeft; 5523 pointerY = self.pointerY - _windowProxy.scrollTop; 5524 while (e && !isRoot) { 5525 //walk up the chain and sense wherever the pointer is within 40px of an edge that's scrollable. 5526 isRoot = _isRoot(e.parentNode); 5527 parent = isRoot ? _windowProxy : e.parentNode; 5528 rect = isRoot ? { 5529 bottom: Math.max(_docElement.clientHeight, window.innerHeight || 0), 5530 right: Math.max(_docElement.clientWidth, window.innerWidth || 0), 5531 left: 0, 5532 top: 0 5533 } : parent.getBoundingClientRect(); 5534 changeX = changeY = 0; 5535 if (allowY) { 5536 gap = parent._gsMaxScrollY - parent.scrollTop; 5537 if (gap < 0) { 5538 changeY = gap; 5539 } else if (pointerY > rect.bottom - autoScrollMarginBottom && gap) { 5540 checkAutoScrollBounds = true; 5541 changeY = Math.min(gap, autoScrollFactor * (1 - Math.max(0, rect.bottom - pointerY) / autoScrollMarginBottom) | 0); 5542 } else if (pointerY < rect.top + autoScrollMarginTop && parent.scrollTop) { 5543 checkAutoScrollBounds = true; 5544 changeY = -Math.min(parent.scrollTop, autoScrollFactor * (1 - Math.max(0, pointerY - rect.top) / autoScrollMarginTop) | 0); 5545 } 5546 if (changeY) { 5547 parent.scrollTop += changeY; 5548 } 5549 } 5550 if (allowX) { 5551 gap = parent._gsMaxScrollX - parent.scrollLeft; 5552 if (gap < 0) { 5553 changeX = gap; 5554 } else if (pointerX > rect.right - autoScrollMarginRight && gap) { 5555 checkAutoScrollBounds = true; 5556 changeX = Math.min(gap, autoScrollFactor * (1 - Math.max(0, rect.right - pointerX) / autoScrollMarginRight) | 0); 5557 } else if (pointerX < rect.left + autoScrollMarginLeft && parent.scrollLeft) { 5558 checkAutoScrollBounds = true; 5559 changeX = -Math.min(parent.scrollLeft, autoScrollFactor * (1 - Math.max(0, pointerX - rect.left) / autoScrollMarginLeft) | 0); 5560 } 5561 if (changeX) { 5562 parent.scrollLeft += changeX; 5563 } 5564 } 5565 if (isRoot && (changeX || changeY)) { 5566 window.scrollTo(parent.scrollLeft, parent.scrollTop); 5567 setPointerPosition(self.pointerX + changeX, self.pointerY + changeY); 5568 } 5569 e = parent; 5570 } 5571 }
5572 if (dirty) { 5573 var x = self.x, 5574 y = self.y, 5575 min = 0.000001; 5576 if (x < min && x > -min) { 5577 //browsers don't handle super small decimals well. 5578 x = 0; 5579 } 5580 if (y < min && y > -min) { 5581 y = 0; 5582 } 5583 if (rotationMode) { 5584 self.deltaX = x - applyObj.data.rotation; 5585 applyObj.data.rotation = self.rotation = x; 5586 applyObj.setRatio(1); //note: instead of doing TweenLite.set(), as a performance optimization we skip right to the method that renders the transforms inside CSSPlugin. For old versions of IE, though, we do a normal TweenLite.set() to leverage its ability to re-reroute to an IE-specific 2D renderer. 5587 } else { 5588 if (scrollProxy) { 5589 if (allowY) { 5590 self.deltaY = y - scrollProxy.top(); 5591 scrollProxy.top(y); 5592 } 5593 if (allowX) { 5594 self.deltaX = x - scrollProxy.left(); 5595 scrollProxy.left(x); 5596 } 5597 } else if (xyMode) { 5598 if (allowY) { 5599 self.deltaY = y - applyObj.data.y; 5600 applyObj.data.y = y; 5601 } 5602 if (allowX) { 5603 self.deltaX = x - applyObj.data.x; 5604 applyObj.data.x = x; 5605 } 5606 applyObj.setRatio(1); //note: instead of doing TweenLite.set(), as a performance optimization we skip right to the method that renders the transforms inside CSSPlugin. For old versions of IE, though, we do a normal TweenLite.set() to leverage its ability to re-reroute to an IE-specific 2D renderer. 5607 } else { 5608 if (allowY) { 5609 self.deltaY = y - parseFloat(target.style.top || 0); 5610 target.style.top = y + "px"; 5611 } 5612 if (allowX) { 5613 self.deltaY = x - parseFloat(target.style.left || 0); 5614 target.style.left = x + "px"; 5615 } 5616 } 5617 } 5618 if (hasDragCallback && !suppressEvents && !isDispatching) { 5619 isDispatching = true; //in case onDrag has an update() call (avoid endless loop) 5620 _dispatchEvent(self, "drag", "onDrag"); 5621 isDispatching = false; 5622 } 5623 } 5624 dirty = false; 5625 }, 5626 //copies the x/y from the element (whether that be transforms, top/left, or ScrollProxy's top/left) to the Draggable's x and y (and rotation if necessary) properties so that they reflect reality and it also (optionally) applies any snapping necessary. This is used by the ThrowPropsPlugin tween in an onUpdate to ensure things are synced and snapped. 5627 syncXY = function syncXY(skipOnUpdate, skipSnap) { 5628 var x = self.x, 5629 y = self.y, 5630 snappedValue; 5631 if (!target._gsTransform && (xyMode || rotationMode)) { 5632 //just in case the _gsTransform got wiped, like if the user called clearProps on the transform or something (very rare), doing an x tween forces a re-parsing of the transforms and population of the _gsTransform. 5633 TweenLite.set(target, { 5634 x: "+=0", 5635 overwrite: false, 5636 data: "_draggable" 5637 }); 5638 } 5639 if (xyMode) { 5640 self.y = target._gsTransform.y; 5641 self.x = target._gsTransform.x; 5642 } else if (rotationMode) { 5643 self.x = self.rotation = target._gsTransform.rotation; 5644 } else if (scrollProxy) { 5645 self.y = scrollProxy.top(); 5646 self.x = scrollProxy.left(); 5647 } else { 5648 self.y = parseInt(target.style.top, 10) || 0; 5649 self.x = parseInt(target.style.left, 10) || 0; 5650 } 5651 if ((snapX || snapY || snapXY) && !skipSnap && (self.isDragging || self.isThrowing)) { 5652 if (snapXY) { 5653 _temp1.x = self.x; 5654 _temp1.y = self.y; 5655 snappedValue = snapXY(_temp1); 5656 if (snappedValue.x !== self.x) { 5657 self.x = snappedValue.x; 5658 dirty = true; 5659 } 5660 if (snappedValue.y !== self.y) { 5661 self.y = snappedValue.y; 5662 dirty = true; 5663 } 5664 } 5665 if (snapX) { 5666 snappedValue = snapX(self.x); 5667 if (snappedValue !== self.x) { 5668 self.x = snappedValue; 5669 if (rotationMode) { 5670 self.rotation = snappedValue; 5671 } 5672 dirty = true; 5673 } 5674 } 5675 if (snapY) { 5676 snappedValue = snapY(self.y); 5677 if (snappedValue !== self.y) { 5678 self.y = snappedValue; 5679 } 5680 dirty = true; 5681 } 5682 }
5683 if (dirty) { 5684 render(true); 5685 } 5686 if (!skipOnUpdate) { 5687 self.deltaX = self.x - x; 5688 self.deltaY = self.y - y; 5689 _dispatchEvent(self, "throwupdate", "onThrowUpdate"); 5690 } 5691 }, 5692 calculateBounds = function calculateBounds() { 5693 var bounds, targetBounds, snap, snapIsRaw; 5694 hasBounds = false; 5695 if (scrollProxy) { 5696 scrollProxy.calibrate(); 5697 self.minX = minX = -scrollProxy.maxScrollLeft(); 5698 self.minY = minY = -scrollProxy.maxScrollTop(); 5699 self.maxX = maxX = self.maxY = maxY = 0; 5700 hasBounds = true; 5701 } else if (!!vars.bounds) { 5702 bounds = _getBounds(vars.bounds, target.parentNode); //could be a selector/jQuery object or a DOM element or a generic object like {top:0, left:100, width:1000, height:800} or {minX:100, maxX:1100, minY:0, maxY:800} 5703 if (rotationMode) { 5704 self.minX = minX = bounds.left; 5705 self.maxX = maxX = bounds.left + bounds.width; 5706 self.minY = minY = self.maxY = maxY = 0; 5707 } else if (vars.bounds.maxX !== undefined || vars.bounds.maxY !== undefined) { 5708 bounds = vars.bounds; 5709 self.minX = minX = bounds.minX; 5710 self.minY = minY = bounds.minY; 5711 self.maxX = maxX = bounds.maxX; 5712 self.maxY = maxY = bounds.maxY; 5713 } else { 5714 targetBounds = _getBounds(target, target.parentNode); 5715 self.minX = minX = _getStyle(target, xProp) + bounds.left - targetBounds.left; 5716 self.minY = minY = _getStyle(target, yProp) + bounds.top - targetBounds.top; 5717 self.maxX = maxX = minX + (bounds.width - targetBounds.width); 5718 self.maxY = maxY = minY + (bounds.height - targetBounds.height); 5719 } 5720 if (minX > maxX) { 5721 self.minX = maxX; 5722 self.maxX = maxX = minX; 5723 minX = self.minX; 5724 } 5725 if (minY > maxY) { 5726 self.minY = maxY; 5727 self.maxY = maxY = minY; 5728 minY = self.minY; 5729 } 5730 if (rotationMode) { 5731 self.minRotation = minX; 5732 self.maxRotation = maxX; 5733 } 5734 hasBounds = true; 5735 } 5736 if (vars.liveSnap) { 5737 snap = vars.liveSnap === true ? vars.snap || {} : vars.liveSnap; 5738 snapIsRaw = snap instanceof Array || typeof snap === "function"; 5739 if (rotationMode) { 5740 snapX = buildSnapFunc(snapIsRaw ? snap : snap.rotation, minX, maxX, 1); 5741 snapY = null; 5742 } else { 5743 if (snap.points) { 5744 snapXY = buildPointSnapFunc(snapIsRaw ? snap : snap.points, minX, maxX, minY, maxY, snap.radius, scrollProxy ? -1 : 1); 5745 } else { 5746 if (allowX) { 5747 snapX = buildSnapFunc(snapIsRaw ? snap : snap.x || snap.left || snap.scrollLeft, minX, maxX, scrollProxy ? -1 : 1); 5748 } 5749 if (allowY) { 5750 snapY = buildSnapFunc(snapIsRaw ? snap : snap.y || snap.top || snap.scrollTop, minY, maxY, scrollProxy ? -1 : 1); 5751 } 5752 } 5753 } 5754 } 5755 }, 5756 onThrowComplete = function onThrowComplete() { 5757 self.isThrowing = false; 5758 _dispatchEvent(self, "throwcomplete", "onThrowComplete"); 5759 }, 5760 onThrowOverwrite = function onThrowOverwrite() { 5761 self.isThrowing = false; 5762 }, 5763 animate = function animate(throwProps, forceZeroVelocity) { 5764 var snap, snapIsRaw, tween, overshootTolerance; 5765 if (throwProps && ThrowPropsPlugin) { 5766 if (throwProps === true) { 5767 snap = vars.snap || vars.liveSnap || {}; 5768 snapIsRaw = snap instanceof Array || typeof snap === "function"; 5769 throwProps = { 5770 resistance: (vars.throwResistance || vars.resistance || 1000) / (rotationMode ? 10 : 1) 5771 }; 5772 if (rotationMode) { 5773 throwProps.rotation = _parseThrowProps(self, snapIsRaw ? snap : snap.rotation, maxX, minX, 1, forceZeroVelocity); 5774 } else { 5775 if (allowX) { 5776 throwProps[xProp] = _parseThrowProps(self, snapIsRaw ? snap : snap.points || snap.x || snap.left || snap.scrollLeft, maxX, minX, scrollProxy ? -1 : 1, forceZeroVelocity || self.lockedAxis === "x"); 5777 } 5778 if (allowY) { 5779 throwProps[yProp] = _parseThrowProps(self, snapIsRaw ? snap : snap.points || snap.y || snap.top || snap.scrollTop, maxY, minY, scrollProxy ? -1 : 1, forceZeroVelocity || self.lockedAxis === "y"); 5780 } 5781 if (snap.points || snap instanceof Array && _typeof(snap[0]) === "object") { 5782 throwProps.linkedProps = xProp + "," + yProp; 5783 throwProps.radius = snap.radius; //note: we also disable liveSnapping while throwing if there's a "radius" defined, otherwise it looks weird to have the item thrown past a snapping point but live-snapping mid-tween. We do this by altering the onUpdateParams so that "skipSnap" parameter is true for syncXY. 5784 } 5785 } 5786 } 5787 self.isThrowing = true; 5788 overshootTolerance = !isNaN(vars.overshootTolerance) ? vars.overshootTolerance : vars.edgeResistance === 1 ? 0 : 1 - self.edgeResistance + 0.2; 5789 self.tween = tween = ThrowPropsPlugin.to(scrollProxy || target, { 5790 throwProps: throwProps, 5791 data: "_draggable", 5792 ease: vars.ease || _globals.Power3.easeOut, 5793 onComplete: onThrowComplete, 5794 onOverwrite: onThrowOverwrite, 5795 onUpdate: vars.fastMode ? _dispatchEvent : syncXY, 5796 onUpdateParams: vars.fastMode ? [self, "onthrowupdate", "onThrowUpdate"] : snap && snap.radius ? [false, true] : _emptyArray 5797 }, isNaN(vars.maxDuration) ? 2 : vars.maxDuration, !isNaN(vars.minDuration) ? vars.minDuration : overshootTolerance === 0 || _typeof(throwProps) === "object" && throwProps.resistance > 1000 ? 0 : 0.5, overshootTolerance); 5798 if (!vars.fastMode) { 5799 //to populate the end values, we just scrub the tween to the end, record the values, and then jump back to the beginning. 5800 if (scrollProxy) { 5801 scrollProxy._suspendTransforms = true; //Microsoft browsers have a bug that causes them to briefly render the position incorrectly (it flashes to the end state when we seek() the tween even though we jump right back to the current position, and this only seems to happen when we're affecting both top and left), so we set a _suspendTransforms flag to prevent it from actually applying the values in the ScrollProxy. 5802 } 5803 tween.render(tween.duration(), true, true); 5804 syncXY(true, true); 5805 self.endX = self.x; 5806 self.endY = self.y; 5807 if (rotationMode) { 5808 self.endRotation = self.x; 5809 } 5810 tween.play(0); 5811 syncXY(true, true); 5812 if (scrollProxy) { 5813 scrollProxy._suspendTransforms = false;
5814 } 5815 } 5816 } else if (hasBounds) { 5817 self.applyBounds(); 5818 } 5819 }, 5820 updateMatrix = function updateMatrix(shiftStart) { 5821 var start = matrix || [1, 0, 0, 1, 0, 0], 5822 a, 5823 b, 5824 c, 5825 d, 5826 tx, 5827 ty, 5828 determinant, 5829 pointerX, 5830 pointerY; 5831 matrix = _getConcatenatedMatrix(target.parentNode, true); 5832 if (shiftStart && self.isPressed && start.join(",") !== matrix.join(",")) { 5833 //if the matrix changes WHILE the element is pressed, we must adjust the startPointerX and startPointerY accordingly, so we invert the original matrix and figure out where the pointerX and pointerY were in the global space, then apply the new matrix to get the updated coordinates. 5834 a = start[0]; 5835 b = start[1]; 5836 c = start[2]; 5837 d = start[3]; 5838 tx = start[4]; 5839 ty = start[5]; 5840 determinant = a * d - b * c; 5841 pointerX = startPointerX * (d / determinant) + startPointerY * (-c / determinant) + (c * ty - d * tx) / determinant; 5842 pointerY = startPointerX * (-b / determinant) + startPointerY * (a / determinant) + -(a * ty - b * tx) / determinant; 5843 startPointerY = pointerX * matrix[1] + pointerY * matrix[3] + matrix[5]; 5844 startPointerX = pointerX * matrix[0] + pointerY * matrix[2] + matrix[4]; 5845 } 5846 if (!matrix[1] && !matrix[2] && matrix[0] == 1 && matrix[3] == 1 && matrix[4] == 0 && matrix[5] == 0) { 5847 //if there are no transforms, we can optimize performance by not factoring in the matrix 5848 matrix = null; 5849 } 5850 }, 5851 recordStartPositions = function recordStartPositions() { 5852 var edgeTolerance = 1 - self.edgeResistance; 5853 updateMatrix(false); 5854 if (matrix) { 5855 startPointerX = self.pointerX * matrix[0] + self.pointerY * matrix[2] + matrix[4]; //translate to local coordinate system 5856 startPointerY = self.pointerX * matrix[1] + self.pointerY * matrix[3] + matrix[5]; 5857 } 5858 if (dirty) { 5859 setPointerPosition(self.pointerX, self.pointerY); 5860 render(true); 5861 } 5862 if (scrollProxy) { 5863 calculateBounds(); 5864 startElementY = scrollProxy.top(); 5865 startElementX = scrollProxy.left(); 5866 } else { 5867 //if the element is in the process of tweening, don't force snapping to occur because it could make it jump. Imagine the user throwing, then before it's done, clicking on the element in its inbetween state. 5868 if (isTweening()) { 5869 syncXY(true, true); 5870 calculateBounds(); 5871 } else { 5872 self.applyBounds(); 5873 } 5874 if (rotationMode) { 5875 rotationOrigin = self.rotationOrigin = _localToGlobal(target, { 5876 x: 0, 5877 y: 0 5878 }); 5879 syncXY(true, true); 5880 startElementX = self.x; //starting rotation (x always refers to rotation in type:"rotation", measured in degrees) 5881 startElementY = self.y = Math.atan2(rotationOrigin.y - self.pointerY, self.pointerX - rotationOrigin.x) * _RAD2DEG; 5882 } else { 5883 startScrollTop = target.parentNode ? target.parentNode.scrollTop || 0 : 0; 5884 startScrollLeft = target.parentNode ? target.parentNode.scrollLeft || 0 : 0; 5885 startElementY = _getStyle(target, yProp); //record the starting top and left values so that we can just add the mouse's movement to them later. 5886 startElementX = _getStyle(target, xProp); 5887 } 5888 } 5889 if (hasBounds && edgeTolerance) { 5890 if (startElementX > maxX) { 5891 startElementX = maxX + (startElementX - maxX) / edgeTolerance; 5892 } else if (startElementX < minX) { 5893 startElementX = minX - (minX - startElementX) / edgeTolerance; 5894 } 5895 if (!rotationMode) { 5896 if (startElementY > maxY) { 5897 startElementY = maxY + (startElementY - maxY) / edgeTolerance; 5898 } else if (startElementY < minY) { 5899 startElementY = minY - (minY - startElementY) / edgeTolerance; 5900 } 5901 } 5902 } 5903 self.startX = startElementX; 5904 self.startY = startElementY; 5905 }, 5906 isTweening = function isTweening() { 5907 return self.tween && self.tween.isActive(); 5908 }, 5909 removePlaceholder = function removePlaceholder() { 5910 if (_placeholderDiv.parentNode && !isTweening() && !self.isDragging) { 5911 //_placeholderDiv just props open auto-scrolling containers so they don't collapse as the user drags left/up. We remove it after dragging (and throwing, if necessary) finishes. 5912 _placeholderDiv.parentNode.removeChild(_placeholderDiv); 5913 } 5914 }, 5915 buildSnapFunc = function buildSnapFunc(snap, min, max, factor) { 5916 if (typeof snap === "function") { 5917 return function (n) { 5918 var edgeTolerance = !self.isPressed ? 1 : 1 - self.edgeResistance; //if we're tweening, disable the edgeTolerance because it's already factored
5918into the tweening values (we don't want to apply it multiple times) 5919 return snap.call(self, n > max ? max + (n - max) * edgeTolerance : n < min ? min + (n - min) * edgeTolerance : n) * factor; 5920 }; 5921 } 5922 if (snap instanceof Array) { 5923 return function (n) { 5924 var i = snap.length, 5925 closest = 0, 5926 absDif = _max, 5927 val, 5928 dif; 5929 while (--i > -1) { 5930 val = snap[i]; 5931 dif = val - n; 5932 if (dif < 0) { 5933 dif = -dif; 5934 } 5935 if (dif < absDif && val >= min && val <= max) { 5936 closest = i; 5937 absDif = dif; 5938 } 5939 } 5940 return snap[closest]; 5941 }; 5942 } 5943 return isNaN(snap) ? function (n) { 5944 return n; 5945 } : function () { 5946 return snap * factor; 5947 }; 5948 }, 5949 buildPointSnapFunc = function buildPointSnapFunc(snap, minX, maxX, minY, maxY, radius, factor) { 5950 radius = radius && radius < _max ? radius * radius : _max; //so we don't have to Math.sqrt() in the functions. Performance optimization. 5951 if (typeof snap === "function") { 5952 return function (point) { 5953 var edgeTolerance = !self.isPressed ? 1 : 1 - self.edgeResistance, 5954 x = point.x, 5955 y = point.y, 5956 result, 5957 dx, 5958 dy; //if we're tweening, disable the edgeTolerance because it's already factored into the tweening values (we don't want to apply it multiple times) 5959 point.x = x = x > maxX ? maxX + (x - maxX) * edgeTolerance : x < minX ? minX + (x - minX) * edgeTolerance : x; 5960 point.y = y = y > maxY ? maxY + (y - maxY) * edgeTolerance : y < minY ? minY + (y - minY) * edgeTolerance : y; 5961 result = snap.call(self, point); 5962 if (result !== point) { 5963 point.x = result.x; 5964 point.y = result.y; 5965 } 5966 if (factor !== 1) { 5967 point.x *= factor; 5968 point.y *= factor; 5969 } 5970 if (radius < _max) { 5971 dx = point.x - x; 5972 dy = point.y - y; 5973 if (dx * dx + dy * dy > radius) { 5974 point.x = x; 5975 point.y = y; 5976 } 5977 } 5978 return point; 5979 }; 5980 } 5981 if (snap instanceof Array) { 5982 return function (p) { 5983 var i = snap.length, 5984 closest = 0, 5985 minDist = _max, 5986 x, 5987 y, 5988 point, 5989 dist; 5990 while (--i > -1) { 5991 point = snap[i]; 5992 x = point.x - p.x; 5993 y = point.y - p.y; 5994 dist = x * x + y * y; 5995 if (dist < minDist) { 5996 closest = i; 5997 minDist = dist; 5998 } 5999 } 6000 return minDist <= radius ? snap[closest] : p; 6001 }; 6002 } 6003 return function (n) { 6004 return n; 6005 }; 6006 }, 6007 //called when the mouse is pressed (or touch starts) 6008 onPress = function onPress(e, force) { 6009 var i; 6010 if (!enabled || self.isPressed || !e || (e.type === "mousedown" || e.type === "pointerdown") && !force && _getTime() - clickTime < 30 && _touchEventLookup[self.pointerEvent.type]) { 6011 //when we DON'T preventDefault() in order to accommodate touch-scrolling and the user just taps, many browsers also fire a mousedown/mouseup sequence AFTER the touchstart/touchend sequence, thus it'd result in two quick "click" events being dispatched. This line senses that condition and halts it on the subsequent mousedown. 6012 return; 6013 } 6014 interrupted = isTweening(); 6015 self.pointerEvent = e; 6016 if (_touchEventLookup[e.type]) { 6017 //note: on iOS, BOTH touchmove and mousemove are dispatched, but the mousemove has pageY and pageX of 0 which w
6017ould mess up the calculations and needlessly hurt performance. 6018 touchEventTarget = e.type.indexOf("touch") !== -1 ? e.currentTarget || e.target : _doc; //pointer-based touches (for Microsoft browsers) don't remain locked to the original target like other browsers, so we must use the document instead. The event type would be "MSPointerDown" or "pointerdown". 6019 _addListener(touchEventTarget, "touchend", _onRelease); 6020 _addListener(touchEventTarget, "touchmove", onMove); 6021 _addListener(touchEventTarget, "touchcancel", _onRelease); 6022 _addListener(_doc, "touchstart", _onMultiTouchDocument); 6023 } else { 6024 touchEventTarget = null; 6025 _addListener(_doc, "mousemove", onMove); //attach these to the document instead of the box itself so that if the user's mouse moves too quickly (and off of the box), things still work. 6026 } 6027 touchDragAxis = null; 6028 _addListener(_doc, "mouseup", _onRelease); 6029 if (e && e.target) { 6030 _addListener(e.target, "mouseup", _onRelease); //we also have to listen directly on the element because some browsers don't bubble up the event to the _doc on elements with contentEditable="true" 6031 } 6032 isClicking = isClickable.call(self, e.target) && !vars.dragClickables && !force; 6033 if (isClicking) { 6034 _addListener(e.target, "change", _onRelease); //in some browsers, when you mousedown on a <select> element, no mouseup gets dispatched! So we listen for a "change" event instead. 6035 _dispatchEvent(self, "press", "onPress"); 6036 _setSelectable(triggers, true); //accommodates things like inputs and elements with contentEditable="true" (otherwise user couldn't drag to select text) 6037 return; 6038 } 6039 allowNativeTouchScrolling = !touchEventTarget || allowX === allowY || self.vars.allowNativeTouchScrolling === false ? false : allowX ? "y" : "x"; 6040 if (_isOldIE) { 6041 e = _populateIEEvent(e, true); 6042 } else if (!allowNativeTouchScrolling && !self.allowEventDefault) { 6043 e.preventDefault(); 6044 if (e.preventManipulation) { 6045 e.preventManipulation(); //for some Microsoft browsers 6046 } 6047 } 6048 if (e.changedTouches) { 6049 //touch events store the data slightly differently 6050 e = touch = e.changedTouches[0]; 6051 touchID = e.identifier; 6052 } else if (e.pointerId) { 6053 touchID = e.pointerId; //for some Microsoft browsers 6054 } else { 6055 touch = touchID = null; 6056 } 6057 _dragCount++; 6058 _addToRenderQueue(render); //causes the Draggable to render on each "tick" of TweenLite.ticker (performance optimization - updating values in a mousemove can cause them to happen too frequently, like multiple times between frame redraws which is wasteful, and it also prevents values from updating properly in IE8) 6059 startPointerY = self.pointerY = e.pageY; //record the starting x and y so that we can calculate the movement from the original in _onMouseMove 6060 startPointerX = self.pointerX = e.pageX; 6061 if (allowNativeTouchScrolling || self.autoScroll) { 6062 _recordMaxScrolls2(target.parentNode); 6063 } 6064 if (target.parentNode && self.autoScroll && !scrollProxy && !rotationMode && target.parentNode._gsMaxScrollX && !_placeholderDiv.parentNode && !target.getBBox) { 6065 //add a placeholder div to prevent the parent container from collapsing when the user drags the element left. 6066 _placeholderDiv.style.width = target.parentNode.scrollWidth + "px"; 6067 target.parentNode.appendChild(_placeholderDiv); 6068 } 6069 recordStartPositions(); 6070 if (self.tween) { 6071 self.tween.kill(); 6072 } 6073 self.isThrowing = false; 6074 TweenLite.killTweensOf(scrollProxy || target, true, killProps); //in case the user tries to drag it before the last tween is done. 6075 if (scrollProxy) { 6076 TweenLite.killTweensOf(target, true, { 6077 scrollTo: 1 6078 }); //just in case the original target's scroll position is being tweened somewhere else. 6079 } 6080 self.tween = self.lockedAxis = null; 6081 if (vars.zIndexBoost || !rotationMode && !scrollProxy && vars.zIndexBoost !== false) { 6082 target.style.zIndex = _Draggable.zIndex++; 6083 } 6084 self.isPressed = true; 6085 hasDragCallback = !!(vars.onDrag || self._listeners.drag); 6086 if (!rotationMode) { 6087 i = triggers.length; 6088 while (--i > -1) {
6089 _setStyle(triggers[i], "cursor", vars.cursor || "move"); 6090 } 6091 } 6092 _dispatchEvent(self, "press", "onPress"); 6093 }, 6094 //called every time the mouse/touch moves 6095 onMove = function onMove(e) { 6096 var originalEvent = e, 6097 touches, 6098 pointerX, 6099 pointerY, 6100 i, 6101 dx, 6102 dy; 6103 if (!enabled || _isMultiTouching || !self.isPressed || !e) { 6104 return; 6105 } 6106 self.pointerEvent = e; 6107 touches = e.changedTouches; 6108 if (touches) { 6109 //touch events store the data slightly differently 6110 e = touches[0]; 6111 if (e !== touch && e.identifier !== touchID) { 6112 //Usually changedTouches[0] will be what we're looking for, but in case it's not, look through the rest of the array...(and Android browsers don't reuse the event like iOS) 6113 i = touches.length; 6114 while (--i > -1 && (e = touches[i]).identifier !== touchID) {} 6115 if (i < 0) { 6116 return; 6117 } 6118 } 6119 } else if (e.pointerId && touchID && e.pointerId !== touchID) { 6120 //for some Microsoft browsers, we must attach the listener to the doc rather than the trigger so that when the finger moves outside the bounds of the trigger, things still work. So if the event we're receiving has a pointerId that doesn't match the touchID, ignore it (for multi-touch) 6121 return; 6122 } 6123 if (_isOldIE) { 6124 e = _populateIEEvent(e, true); 6125 } else { 6126 if (touchEventTarget && allowNativeTouchScrolling && !touchDragAxis) { 6127 //Android browsers force us to decide on the first "touchmove" event if we should allow the default (scrolling) behavior or preventDefault(). Otherwise, a "touchcancel" will be fired and then no "touchmove" or "touchend" will fire during the scrolling (no good). 6128 pointerX = e.pageX; 6129 pointerY = e.pageY; 6130 if (matrix) { 6131 i = pointerX * matrix[0] + pointerY * matrix[2] + matrix[4]; 6132 pointerY = pointerX * matrix[1] + pointerY * matrix[3] + matrix[5]; 6133 pointerX = i; 6134 } 6135 dx = Math.abs(pointerX - startPointerX); 6136 dy = Math.abs(pointerY - startPointerY); 6137 if (dx !== dy && (dx > minimumMovement || dy > minimumMovement) || _isAndroid && allowNativeTouchScrolling === touchDragAxis) { 6138 touchDragAxis = dx > dy && allowX ? "x" : "y"; 6139 if (self.vars.lockAxisOnTouchScroll !== false) { 6140 self.lockedAxis = touchDragAxis === "x" ? "y" : "x"; 6141 if (typeof self.vars.onLockAxis === "function") { 6142 self.vars.onLockAxis.call(self, originalEvent); 6143 } 6144 } 6145 if (_isAndroid && allowNativeTouchScrolling === touchDragAxis) { 6146 _onRelease(originalEvent); 6147 return; 6148 } 6149 } 6150 } 6151 if (!self.allowEventDefault && (!allowNativeTouchScrolling || touchDragAxis && allowNativeTouchScrolling !== touchDragAxis) && originalEvent.cancelable !== false) { 6152 originalEvent.preventDefault(); 6153 if (originalEvent.preventManipulation) { 6154 //for some Microsoft browsers 6155 originalEvent.preventManipulation(); 6156 } 6157 } 6158 } 6159 if (self.autoScroll) { 6160 checkAutoScrollBounds = true; 6161 } 6162 setPointerPosition(e.pageX, e.pageY); 6163 }, 6164 setPointerPosition = function setPointerPosition(pointerX, pointerY) { 6165 var dragTolerance = 1 - self.dragResistance, 6166 edgeTolerance = 1 - self.edgeResistance, 6167 xChange, 6168 yChange, 6169 x, 6170 y, 6171 dif, 6172 temp; 6173 self.pointerX = pointerX; 6174 self.pointerY = pointerY; 6175 if (rotationMode) { 6176 y = Math.atan2(rotationOrigin.y - pointerY, pointerX - rotationOrigin.x) * _RAD2DEG; 6177 dif = self.y - y; 6178 if (dif > 180) { 6179 startElementY -= 360; 6180 self.y = y; 6181 } else if (dif < -180) { 6182 startElementY += 360; 6183 self.y = y; 6184 } 6185 if (self.x !== startElementX || Math.abs(startElementY - y) > minimumMovement) { 6186 self.y = y; 6187 x = startElementX + (startElementY - y) * dragTolerance; 6188 } else { 6189 x = startElementX; 6190 } 6191 } else { 6192 if (matrix) { 6193 temp = pointerX * matrix[0] + pointerY * matrix[2] + matrix[4]; 6194 pointerY = pointerX * matrix[1] + pointerY * matrix[3] + matrix[5]; 6195 pointerX = temp; 6196 } 6197 yChange = pointerY - startPointerY; 6198 xChange = pointerX - startPointerX; 6199 if (yChange < minimumMovement && yChange > -minimumMovement) { 6200 yChange = 0; 6201 } 6202 if (xChange < minimumMovement && xChange > -minimumMovement) { 6203 xChange = 0; 6204 } 6205 if ((self.lockAxis || self.lockedAxis) && (xChange || yChange)) { 6206 temp = self.lockedAxis; 6207 if (!temp) { 6208 self.lockedAxis = temp = allowX && Math.abs(xChange) > Math.abs(yChange) ? "y" : allowY ? "x" : null; 6209 if (temp && typeof self.vars.onLockAxis === "function") { 6210 self.vars.onLockAxis.call(self, self.pointerEvent); 6211 } 6212 } 6213 if (temp === "y") { 6214 yChange = 0; 6215 } else if (temp === "x") { 6216 xChange = 0; 6217 } 6218 } 6219 x = startElementX + xChange * dragTolerance; 6220 y = startElementY + yChange * dragTolerance; 6221 } 6222 if ((snapX || snapY || snapXY) && (self.x !== x || self.y !== y && !rotationMode)) { 6223 if (snapXY) { 6224 _temp1.x = x; 6225 _temp1.y = y; 6226 temp = snapXY(_temp1); 6227 x = temp.x; 6228 y = temp.y; 6229 } 6230 if (snapX) { 6231 x = snapX(x); 6232 } 6233 if (snapY) { 6234 y = snapY(y); 6235 } 6236 } else if (hasBounds) { 6237 if (x > maxX) { 6238 x = maxX + (x - maxX) * edgeTolerance; 6239 } else if (x < minX) { 6240 x = minX + (x - minX) * edgeTolerance; 6241 } 6242 if (!rotationMode) { 6243 if (y > maxY) { 6244 y = maxY + (y - maxY) * edgeTolerance; 6245 } else if (y < minY) { 6246 y = minY + (y - minY) * edgeTolerance; 6247 } 6248 } 6249 } 6250 if (!rotationMode && !matrix) { 6251 x = Math.round(x); //helps work around an issue with some Win Touch devices 6252 y = Math.round(y); 6253 } 6254 if (self.x !== x || self.y !== y && !rotationMode) { 6255 if (rotationMode) { 6256 self.endRotation = self.x = self.endX = x; 6257 dirty = true; 6258 } else { 6259 if (allowY) { 6260 self.y = self.endY = y; 6261 dirty = true; //a flag that indicates we need to render the target next time the TweenLite.ticker dispatches a "tick" event (typically on a requestAnimationFrame) - this is a performance optimization (we shouldn't render on every move because sometimes many move events can get dispatched between screen refreshes, and that'd be wasteful to render every time) 6262 } 6263 if (allowX) { 6264 self.x = self.endX = x; 6265 dirty = true; 6266 } 6267 } 6268 if (!self.isDragging && self.isPressed) { 6269 self.isDragging = true; 6270 _dispatchEvent(self, "dragstart", "onDragStart"); 6271 } 6272 } 6273 }, 6274 //called when the mouse/touch is released 6275 _onRelease = function onRelease(e, force) { 6276 if (!enabled || !self.isPressed || e && touchID != null && !force && (e.pointerId && e.pointerId !== touchID || e.changedTouches && !_hasTouchID(e.changedTouches, touchID))) { 6277 //for some Microsoft browsers, we must attach the listener to the doc rather than the trigger so that when the finger moves outside the bounds of the trigger, things still work. So if the event we're receiving has a pointerId that doesn't match the touchID, ignore it (for multi-touch) 6278 return; 6279 } 6280 self.isPressed = false;
6281 var originalEvent = e, 6282 wasDragging = self.isDragging, 6283 placeholderDelayedCall = TweenLite.delayedCall(0.001, removePlaceholder), 6284 touches, 6285 i, 6286 syntheticEvent, 6287 eventTarget, 6288 syntheticClick; 6289 if (touchEventTarget) { 6290 _removeListener(touchEventTarget, "touchend", _onRelease); 6291 _removeListener(touchEventTarget, "touchmove", onMove); 6292 _removeListener(touchEventTarget, "touchcancel", _onRelease); 6293 _removeListener(_doc, "touchstart", _onMultiTouchDocument); 6294 } else { 6295 _removeListener(_doc, "mousemove", onMove); 6296 } 6297 _removeListener(_doc, "mouseup", _onRelease); 6298 if (e && e.target) { 6299 _removeListener(e.target, "mouseup", _onRelease); 6300 } 6301 dirty = false; 6302 if (isClicking) { 6303 if (e) { 6304 _removeListener(e.target, "change", _onRelease); 6305 self.pointerEvent = originalEvent; 6306 } 6307 _setSelectable(triggers, false); 6308 _dispatchEvent(self, "release", "onRelease"); 6309 _dispatchEvent(self, "click", "onClick"); 6310 isClicking = false; 6311 return; 6312 } 6313 _removeFromRenderQueue(render); 6314 if (!rotationMode) { 6315 i = triggers.length; 6316 while (--i > -1) { 6317 _setStyle(triggers[i], "cursor", vars.cursor || "move"); 6318 } 6319 } 6320 if (wasDragging) { 6321 dragEndTime = _lastDragTime = _getTime(); 6322 self.isDragging = false; 6323 } 6324 _dragCount--; 6325 if (e) { 6326 if (_isOldIE) { 6327 e = _populateIEEvent(e, false); 6328 } 6329 touches = e.changedTouches; 6330 if (touches) { 6331 //touch events store the data slightly differently 6332 e = touches[0]; 6333 if (e !== touch && e.identifier !== touchID) { 6334 //Usually changedTouches[0] will be what we're looking for, but in case it's not, look through the rest of the array...(and Android browsers don't reuse the event like iOS) 6335 i = touches.length; 6336 while (--i > -1 && (e = touches[i]).identifier !== touchID) {} 6337 if (i < 0) { 6338 return; 6339 } 6340 } 6341 } 6342 self.pointerEvent = originalEvent; 6343 self.pointerX = e.pageX; 6344 self.pointerY = e.pageY; 6345 } 6346 if (originalEvent && !wasDragging) { 6347 if (interrupted && (vars.snap || vars.bounds)) { 6348 //otherwise, if the user clicks on the object while it's animating to a snapped position, and then releases without moving 3 pixels, it will just stay there (it should animate/snap) 6349 animate(vars.throwProps); 6350 } 6351 _dispatchEvent(self, "release", "onRelease"); 6352 if ((!_isAndroid || originalEvent.type !== "touchmove") && originalEvent.type.indexOf("cancel") === -1) { 6353 //to accommodate native scrolling on Android devices, we have to immediately call onRelease() on the first touchmove event, but that shouldn't trigger a "click". 6354 _dispatchEvent(self, "click", "onClick"); 6355 if (_getTime() - clickTime < 300) { 6356 _dispatchEvent(self, "doubleclick", "onDoubleClick"); 6357 } 6358 eventTarget = originalEvent.target || originalEvent.srcElement || target; //old IE uses srcElement 6359 clickTime = _getTime(); 6360 syntheticClick = function syntheticClick() { 6361 // some browsers (like Firefox) won't trust script-generated clicks, so if the user tries to click on a video to play it, for example, it simply won't work. Since a regular "click" event will most likely be generated anyway (one that has its isTrusted flag set to true), we must slightly delay our script-generated click so that the "real"/trusted one is prioritized. Remember, when there are duplicate events in quick succession, we suppress all but the first one. Some browsers don't even trigger the "real" one at all, so our synthetic one is a safety valve that ensures that no matter what, a click event does get dispatched. 6362 if (clickTime !== clickDispatch && self.enabled() && !self.isPressed) { 6363 if (eventTarget.click) { 6364 //some browsers (like mobile Safari) don't properly trigger the click event 6365 eventTarget.click(); 6366 } else if (_doc.createEvent) { 6367 syntheticEvent = _doc.createEvent("MouseEvents"); 6368 syntheticEvent.initMouseEvent("click", true, true, window, 1, self.pointerEvent.
6368screenX, self.pointerEvent.screenY, self.pointerX, self.pointerY, false, false, false, false, 0, null); 6369 eventTarget.dispatchEvent(syntheticEvent); 6370 } 6371 } 6372 }; 6373 if (!_isAndroid && !originalEvent.defaultPrevented) { 6374 //iOS Safari requires the synthetic click to happen immediately or else it simply won't work, but Android doesn't play nice. 6375 TweenLite.delayedCall(0.00001, syntheticClick); //in addition to the iOS bug workaround, there's a Firefox issue with clicking on things like a video to play, so we must fake a click event in a slightly delayed fashion. Previously, we listened for the "click" event with "capture" false which solved the video-click-to-play issue, but it would allow the "click" event to be dispatched twice like if you were using a jQuery.click() because that was handled in the capture phase, thus we had to switch to the capture phase to avoid the double-dispatching, but do the delayed synthetic click. 6376 } 6377 } 6378 } else { 6379 animate(vars.throwProps); //will skip if throwProps isn't defined or ThrowPropsPlugin isn't loaded. 6380 if (!_isOldIE && !self.allowEventDefault && originalEvent && (vars.dragClickables || !isClickable.call(self, originalEvent.target)) && wasDragging && (!allowNativeTouchScrolling || touchDragAxis && allowNativeTouchScrolling === touchDragAxis) && originalEvent.cancelable !== false) { 6381 originalEvent.preventDefault(); 6382 if (originalEvent.preventManipulation) { 6383 originalEvent.preventManipulation(); //for some Microsoft browsers 6384 } 6385 } 6386 _dispatchEvent(self, "release", "onRelease"); 6387 } 6388 if (isTweening()) { 6389 placeholderDelayedCall.duration(self.tween.duration()); //sync the timing so that the placeholder DIV gets 6390 } 6391 if (wasDragging) { 6392 _dispatchEvent(self, "dragend", "onDragEnd"); 6393 } 6394 return true; 6395 }, 6396 updateScroll = function updateScroll(e) { 6397 if (e && self.isDragging && !scrollProxy) { 6398 var parent = e.target || e.srcElement || target.parentNode, 6399 deltaX = parent.scrollLeft - parent._gsScrollX, 6400 deltaY = parent.scrollTop - parent._gsScrollY; 6401 if (deltaX || deltaY) { 6402 if (matrix) { 6403 startPointerX -= deltaX * matrix[0] + deltaY * matrix[2]; 6404 startPointerY -= deltaY * matrix[3] + deltaX * matrix[1]; 6405 } else { 6406 startPointerX -= deltaX; 6407 startPointerY -= deltaY; 6408 } 6409 parent._gsScrollX += deltaX; 6410 parent._gsScrollY += deltaY; 6411 setPointerPosition(self.pointerX, self.pointerY); 6412 } 6413 } 6414 }, 6415 onClick = function onClick(e) { 6416 //this was a huge pain in the neck to align all the various browsers and their behaviors. Chrome, Firefox, Safari, Opera, Android, and Microsoft Edge all handle events differently! Some will only trigger native behavior (like checkbox toggling) from trusted events. Others don't even support isTrusted, but require 2 events to flow through before triggering native behavior. Edge treats everything as trusted but also mandates that 2 flow through to trigger the correct native behavior. 6417 var time = _getTime(), 6418 recentlyClicked = time - clickTime < 40, 6419 recentlyDragged = time - dragEndTime < 40, 6420 alreadyDispatched = recentlyClicked && clickDispatch === clickTime, 6421 isModern = !!e.preventDefault, 6422 defaultPrevented = self.pointerEvent && self.pointerEvent.defaultPrevented, 6423 alreadyDispatchedTrusted = recentlyClicked && trustedClickDispatch === clickTime, 6424 trusted = e.isTrusted || e.isTrusted == null && recentlyClicked && alreadyDispatched; //note: Safari doesn't support isTrusted, and it won't properly execute native behavior (like toggling checkboxes) on the first synthetic "click" event - we must wait for the 2nd and treat it as trusted (but stop propagation at that point). Confusing, I know. Don't you love cross-browser compatibility challenges? 6425 if (isModern && (alreadyDispatched || recentlyDragged && self.vars.suppressClickOnDrag !== false)) { 6426 e.stopImmediatePropagation(); 6427 } 6428 if (recentlyClicked && !(self.pointerEvent && self.pointerEvent.defaultPrevented) && (!alreadyDispatched || trusted !== alreadyDispatchedTrusted)) { 6429 //let the first click pass through unhindered. Let the next one only if it's trusted, then no more (stop quick-succession ones) 6430 if (trusted && alreadyDispatched) { 6431 trustedClickDispatch = clickTime; 6432 } 6433 clickDispatch = clickTime; 6434 return; 6435 } 6436 if (self.isPressed || recentlyDragged || recentlyClicked) { 6437 if (!isModern) { 6438 e.returnValue = false;
6439 } else if (!trusted || !e.detail || !recentlyClicked || defaultPrevented) { 6440 e.preventDefault(); 6441 if (e.preventManipulation) { 6442 e.preventManipulation(); //for some Microsoft browsers 6443 } 6444 } 6445 } 6446 }, 6447 localizePoint = function localizePoint(p) { 6448 return matrix ? { 6449 x: p.x * matrix[0] + p.y * matrix[2] + matrix[4], 6450 y: p.x * matrix[1] + p.y * matrix[3] + matrix[5] 6451 } : { 6452 x: p.x, 6453 y: p.y 6454 }; 6455 }; 6456 old = _Draggable.get(this.target); 6457 if (old) { 6458 old.kill(); // avoids duplicates (an element can only be controlled by one Draggable) 6459 } 6460 6461 //give the user access to start/stop dragging... 6462 this.startDrag = function (e, align) { 6463 var r1, r2, p1, p2; 6464 onPress(e || self.pointerEvent, true); 6465 //if the pointer isn't on top of the element, adjust things accordingly 6466 if (align && !self.hitTest(e || self.pointerEvent)) { 6467 r1 = _parseRect(e || self.pointerEvent); 6468 r2 = _parseRect(target); 6469 p1 = localizePoint({ 6470 x: r1.left + r1.width / 2, 6471 y: r1.top + r1.height / 2 6472 }); 6473 p2 = localizePoint({ 6474 x: r2.left + r2.width / 2, 6475 y: r2.top + r2.height / 2 6476 }); 6477 startPointerX -= p1.x - p2.x; 6478 startPointerY -= p1.y - p2.y; 6479 } 6480 if (!self.isDragging) { 6481 self.isDragging = true; 6482 _dispatchEvent(self, "dragstart", "onDragStart"); 6483 } 6484 }; 6485 this.drag = onMove; 6486 this.endDrag = function (e) { 6487 _onRelease(e || self.pointerEvent, true); 6488 }; 6489 this.timeSinceDrag = function () { 6490 return self.isDragging ? 0 : (_getTime() - dragEndTime) / 1000; 6491 }; 6492 this.timeSinceClick = function () { 6493 return (_getTime() - clickTime) / 1000; 6494 }; 6495 this.hitTest = function (target, threshold) { 6496 return _Draggable.hitTest(self.target, target, threshold); 6497 }; 6498 this.getDirection = function (from, diagonalThreshold) { 6499 //from can be "start" (default), "velocity", or an element 6500 var mode = from === "velocity" && ThrowPropsPlugin ? from : _typeof(from) === "object" && !rotationMode ? "element" : "start", 6501 xChange, 6502 yChange, 6503 ratio, 6504 direction, 6505 r1, 6506 r2; 6507 if (mode === "element") { 6508 r1 = _parseRect(self.target); 6509 r2 = _parseRect(from); 6510 } 6511 xChange = mode === "start" ? self.x - startElementX : mode === "velocity" ? ThrowPropsPlugin.getVelocity(this.target, xProp) : r1.left + r1.width / 2 - (r2.left + r2.width / 2); 6512 if (rotationMode) { 6513 return xChange < 0 ? "counter-clockwise" : "clockwise"; 6514 } else { 6515 diagonalThreshold = diagonalThreshold || 2; 6516 yChange = mode === "start" ? self.y - startElementY : mode === "velocity" ? ThrowPropsPlugin.getVelocity(this.target, yProp) : r1.top + r1.height / 2 - (r2.top + r2.height / 2); 6517 ratio = Math.abs(xChange / yChange); 6518 direction = ratio < 1 / diagonalThreshold ? "" : xChange < 0 ? "left" : "right"; 6519 if (ratio < diagonalThreshold) { 6520 if (direction !== "") { 6521 direction += "-"; 6522 } 6523 direction += yChange < 0 ? "up" : "down"; 6524 } 6525 } 6526 return direction; 6527 }; 6528 this.applyBounds = function (newBounds) { 6529 var x, y, forceZeroVelocity, e, parent, isRoot; 6530 if (newBounds && vars.bounds !== newBounds) { 6531 vars.bounds = newBounds; 6532 return self.update(true); 6533 } 6534 syncXY(true); 6535 calculateBounds(); 6536 if (hasBounds) { 6537 x = self.x; 6538 y = self.y; 6539 if (x > maxX) { 6540 x = maxX; 6541 } else if (x < minX) { 6542 x = minX; 6543 } 6544 if (y > maxY) { 6545 y = maxY; 6546 } else if (y < minY) { 6547 y = minY; 6548 } 6549 if (self.x !== x || self.y !== y) { 6550 forceZeroVelocity = true; 6551 self.x = self.endX = x; 6552 if (rotationMode) { 6553 self.endRotation = x; 6554 } else { 6555 self.y = self.endY = y; 6556 } 6557 dirty = true; 6558 render(true); 6559 if (self.autoScroll && !self.isDragging) { 6560 _recordMaxScrolls2(target.parentNode); 6561 e = target; 6562 _windowProxy.scrollTop = window.pageYOffset != null ? window.pageYOffset : _docElement.scrollTop != null ? _docElement.scrollTop : _doc.body.scrollTop; 6563 _windowProxy.scrollLeft = window.pageXOffset != null ? window.pageXOffset : _docElement.scrollLeft != null ? _docElement.scrollLeft : _doc.body.scrollLeft; 6564 while (e && !isRoot) { 6565 //walk up the chain and sense wherever the scrollTop/scrollLeft exceeds the maximum. 6566 isRoot = _isRoot(e.parentNode); 6567 parent = isRoot ? _windowProxy : e.parentNode; 6568 if (allowY && parent.scrollTop > parent._gsMaxScrollY) { 6569 parent.scrollTop = parent._gsMaxScrollY; 6570 } 6571 if (allowX && parent.scrollLeft > parent._gsMaxScrollX) { 6572 parent.scrollLeft = parent._gsMaxScrollX; 6573 } 6574 e = parent; 6575 } 6576 } 6577 } 6578 if (self.isThrowing && (forceZeroVelocity || self.endX > maxX || self.endX < minX || self.endY > maxY || self.endY < minY)) { 6579 animate(vars.throwProps, forceZeroVelocity); 6580 } 6581 } 6582 return self; 6583 }; 6584 this.update = function (applyBounds, sticky, ignoreExternalChanges) { 6585 var x = self.x, 6586 y = self.y; 6587 updateMatrix(!sticky);
6588 if (applyBounds) { 6589 self.applyBounds(); 6590 } else { 6591 if (dirty && ignoreExternalChanges) { 6592 render(true); 6593 } 6594 syncXY(true); 6595 } 6596 if (sticky) { 6597 setPointerPosition(self.pointerX, self.pointerY); 6598 if (dirty) { 6599 render(true); 6600 } 6601 } 6602 if (self.isPressed && !sticky && (allowX && Math.abs(x - self.x) > 0.01 || allowY && Math.abs(y - self.y) > 0.01 && !rotationMode)) { 6603 recordStartPositions(); 6604 } 6605 if (self.autoScroll) { 6606 _recordMaxScrolls2(target.parentNode); 6607 checkAutoScrollBounds = self.isDragging; 6608 render(true); 6609 } 6610 if (self.autoScroll) { 6611 //in case reparenting occurred. 6612 _removeScrollListener2(target, updateScroll); 6613 _addScrollListener2(target, updateScroll); 6614 } 6615 return self; 6616 }; 6617 this.enable = function (type) { 6618 var id, i, trigger; 6619 if (type !== "soft") { 6620 i = triggers.length; 6621 while (--i > -1) { 6622 trigger = triggers[i]; 6623 _addListener(trigger, "mousedown", onPress); 6624 _addListener(trigger, "touchstart", onPress); 6625 _addListener(trigger, "click", onClick, true); //note: used to pass true for capture but it prevented click-to-play-video functionality in Firefox. 6626 if (!rotationMode) { 6627 _setStyle(trigger, "cursor", vars.cursor || "move"); 6628 } 6629 _setStyle(trigger, "touchCallout", "none"); 6630 _setStyle(trigger, "touchAction", allowX === allowY ? "none" : allowX ? "pan-y" : "pan-x"); 6631 if (_isSVG(trigger)) { 6632 // a bug in chrome doesn't respect touch-action on SVG elements - it only works if we set it on the parent SVG. 6633 _setStyle(trigger.ownerSVGElement || trigger, "touchAction", allowX === allowY ? "none" : allowX ? "pan-y" : "pan-x"); 6634 } 6635 if (!this.vars.allowContextMenu) { 6636 _addListener(trigger, "contextmenu", onContextMenu); 6637 } 6638 } 6639 _setSelectable(triggers, false); 6640 } 6641 _addScrollListener2(target, updateScroll); 6642 enabled = true; 6643 if (ThrowPropsPlugin && type !== "soft") { 6644 ThrowPropsPlugin.track(scrollProxy || target, xyMode ? "x,y" : rotationMode ? "rotation" : "top,left"); 6645 } 6646 if (scrollProxy) { 6647 scrollProxy.enable(); 6648 } 6649 target._gsDragID = id = "d" + _lookupCount++; 6650 _lookup[id] = this; 6651 if (scrollProxy) { 6652 scrollProxy.element._gsDragID = id; 6653 } 6654 TweenLite.set(target, { 6655 x: "+=0", 6656 overwrite: false, 6657 data: "_draggable" 6658 }); //simply ensures that there's a _gsTransform on the element. 6659 applyObj = { 6660 t: target, 6661 data: _isOldIE ? cssVars : target._gsTransform, 6662 tween: {}, 6663 setRatio: _isOldIE ? function () { 6664 TweenLite.set(target, tempVars); 6665 } : CSSPlugin._internals.setTransformRatio || CSSPlugin._internals.set3DTransformRatio 6666 }; 6667 recordStartPositions(); 6668 self.update(true); 6669 return self; 6670 }; 6671 this.disable = function (type) { 6672 var dragging = self.isDragging, 6673 i, 6674 trigger; 6675 if (!rotationMode) { 6676 i = triggers.length; 6677 while (--i > -1) { 6678 _setStyle(triggers[i], "cursor", null); 6679 } 6680 } 6681 if (type !== "soft") { 6682 i = triggers.length; 6683 while (--i > -1) { 6684 trigger = triggers[i]; 6685 _setStyle(trigger, "touchCallout", null); 6686 _setStyle(trigger, "touchAction", null); 6687 _removeListener(trigger, "mousedown", onPress); 6688 _removeListener(trigger, "touchstart", onPress); 6689 _removeListener(trigger, "click", onClick); 6690 _removeListener(trigger, "contextmenu", onContextMenu); 6691 } 6692 _setSelectable(triggers, true); 6693 if (touchEventTarget) { 6694 _removeListener(touchEventTarget, "touchcancel", _onRelease); 6695 _removeListener(touchEventTarget, "touchend", _onRelease); 6696 _removeListener(touchEventTarget, "touchmove", onMove); 6697 } 6698 _removeListener(_doc, "mouseup", _onRelease); 6699 _removeListener(_doc, "mousemove", onMove); 6700 } 6701 _removeScrollListener2(target, updateScroll); 6702 enabled = false;
6703 if (ThrowPropsPlugin && type !== "soft") { 6704 ThrowPropsPlugin.untrack(scrollProxy || target, xyMode ? "x,y" : rotationMode ? "rotation" : "top,left"); 6705 } 6706 if (scrollProxy) { 6707 scrollProxy.disable(); 6708 } 6709 _removeFromRenderQueue(render); 6710 self.isDragging = self.isPressed = isClicking = false; 6711 if (dragging) { 6712 _dispatchEvent(self, "dragend", "onDragEnd"); 6713 } 6714 return self; 6715 }; 6716 this.enabled = function (value, type) { 6717 return arguments.length ? value ? self.enable(type) : self.disable(type) : enabled; 6718 }; 6719 this.kill = function () { 6720 self.isThrowing = false; 6721 TweenLite.killTweensOf(scrollProxy || target, true, killProps); 6722 self.disable(); 6723 delete _lookup[target._gsDragID]; 6724 return self; 6725 }; 6726 if (type.indexOf("scroll") !== -1) { 6727 scrollProxy = this.scrollProxy = new ScrollProxy(target, _extend({ 6728 onKill: function onKill() { 6729 //ScrollProxy's onKill() gets called if/when the ScrollProxy senses that the user interacted with the scroll position manually (like using the scrollbar). IE9 doesn't fire the "mouseup" properly when users drag the scrollbar of an element, so this works around that issue. 6730 if (self.isPressed) { 6731 _onRelease(null); 6732 } 6733 } 6734 }, vars)); 6735 //a bug in many Android devices' stock browser causes scrollTop to get forced back to 0 after it is altered via JS, so we set overflow to "hidden" on mobile/touch devices (they hide the scroll bar anyway). That works around the bug. (This bug is discussed at https://code.google.com/p/android/issues/detail?id=19625) 6736 target.style.overflowY = allowY && !_isTouchDevice ? "auto" : "hidden"; 6737 target.style.overflowX = allowX && !_isTouchDevice ? "auto" : "hidden"; 6738 target = scrollProxy.content; 6739 } 6740 if (vars.force3D !== false) { 6741 TweenLite.set(target, { 6742 force3D: true 6743 }); //improve performance by forcing a GPU layer when possible 6744 } 6745 if (rotationMode) { 6746 killProps.rotation = 1; 6747 } else { 6748 if (allowX) { 6749 killProps[xProp] = 1; 6750 } 6751 if (allowY) { 6752 killProps[yProp] = 1; 6753 } 6754 } 6755 if (rotationMode) { 6756 tempVars = _tempVarsRotation; 6757 cssVars = tempVars.css; 6758 tempVars.overwrite = false; 6759 } else if (xyMode) { 6760 tempVars = allowX && allowY ? _tempVarsXY : allowX ? _tempVarsX : _tempVarsY; 6761 cssVars = tempVars.css; 6762 tempVars.overwrite = false; 6763 } 6764 this.enable(); 6765 }, 6766 p = _Draggable.prototype = new EventDispatcher(); 6767 p.constructor = _Draggable; 6768 p.pointerX = p.pointerY = p.startX = p.startY = p.deltaX = p.deltaY = 0; 6769 p.isDragging = p.isPressed = false; 6770 _Draggable.version = "0.16.1"; 6771 _Draggable.zIndex = 1000; 6772 _addListener(_doc, "touchcancel", function () { 6773 //some older Android devices intermittently stop dispatching "touchmove" events if we don't listen for "touchcancel" on the document. Very strange indeed. 6774 }); 6775 _addListener(_doc, "contextmenu", function (e) { 6776 var p; 6777 for (p in _lookup) { 6778 if (_lookup[p].isPressed) { 6779 _lookup[p].endDrag(); 6780 } 6781 } 6782 }); 6783 _Draggable.create = function (targets, vars) { 6784 if (typeof targets === "string") { 6785 targets = TweenLite.selector(targets); 6786 } 6787 var a = !targets || targets.length === 0 ? [] : _isArrayLike(targets) ? _flattenArray(targets) : [targets], 6788 i = a.length; 6789 while (--i > -1) { 6790 a[i] = new _Draggable(a[i], vars); 6791 } 6792 return a; 6793 }; 6794 _Draggable.get = function (target) { 6795 return _lookup[(_unwrapElement(target) || {})._gsDragID]; 6796 }; 6797 _Draggable.timeSinceDrag = function () { 6798 return (_getTime() - _lastDragTime) / 1000; 6799 }; 6800 var _tempRect = {}, 6801 //reuse to reduce garbage collection tasks 6802 _oldIERect = function _oldIERect(e) { 6803 //IE8 doesn't support getBoundingClientRect(), so we use this as a backup. 6804 var top = 0, 6805 left = 0, 6806 width, 6807 height; 6808 e = _unwrapElement(e); 6809 width = e.offsetWidth; 6810 height = e.offsetHeight; 6811 while (e) { 6812 top += e.offsetTop; 6813 left += e.offsetLeft; 6814 e = e.offsetParent; 6815 } 6816 return { 6817 top: top, 6818 left: left, 6819 width: width, 6820 height: height 6821 }; 6822 }, 6823 _parseRect = function _parseRect(e, undefined) { 6824 //accepts a DOM element, a mouse event, or a rectangle object and returns the corresponding rectangle with left, right, width, height, top, and bottom properties 6825 if (e === window) { 6826 _tempRect.left = _tempRect.top = 0; 6827 _tempRect.width = _tempRect.right = _docElement.clientWidth || e.innerWidth || _doc.body.clientWidth || 0;
6828 _tempRect.height = _tempRect.bottom = (e.innerHeight || 0) - 20 < _docElement.clientHeight ? _docElement.clientHeight : e.innerHeight || _doc.body.clientHeight || 0; 6829 return _tempRect; 6830 } 6831 var r = e.pageX !== undefined ? { 6832 left: e.pageX - _getDocScrollLeft(), 6833 top: e.pageY - _getDocScrollTop(), 6834 right: e.pageX - _getDocScrollLeft() + 1, 6835 bottom: e.pageY - _getDocScrollTop() + 1 6836 } : !e.nodeType && e.left !== undefined && e.top !== undefined ? e : _isOldIE ? _oldIERect(e) : _unwrapElement(e).getBoundingClientRect(); 6837 if (r.right === undefined && r.width !== undefined) { 6838 r.right = r.left + r.width; 6839 r.bottom = r.top + r.height; 6840 } else if (r.width === undefined) { 6841 //some browsers don't include width and height properties. We can't just set them directly on r because some browsers throw errors, so create a new generic object. 6842 r = { 6843 width: r.right - r.left, 6844 height: r.bottom - r.top, 6845 right: r.right, 6846 left: r.left, 6847 bottom: r.bottom, 6848 top: r.top 6849 }; 6850 } 6851 return r; 6852 }; 6853 _Draggable.hitTest = function (obj1, obj2, threshold) { 6854 if (obj1 === obj2) { 6855 return false; 6856 } 6857 var r1 = _parseRect(obj1), 6858 r2 = _parseRect(obj2), 6859 isOutside = r2.left > r1.right || r2.right < r1.left || r2.top > r1.bottom || r2.bottom < r1.top, 6860 overlap, 6861 area, 6862 isRatio; 6863 if (isOutside || !threshold) { 6864 return !isOutside; 6865 } 6866 isRatio = (threshold + "").indexOf("%") !== -1; 6867 threshold = parseFloat(threshold) || 0; 6868 overlap = { 6869 left: Math.max(r1.left, r2.left), 6870 top: Math.max(r1.top, r2.top) 6871 }; 6872 overlap.width = Math.min(r1.right, r2.right) - overlap.left; 6873 overlap.height = Math.min(r1.bottom, r2.bottom) - overlap.top; 6874 if (overlap.width < 0 || overlap.height < 0) { 6875 return false; 6876 } 6877 if (isRatio) { 6878 threshold *= 0.01; 6879 area = overlap.width * overlap.height; 6880 return area >= r1.width * r1.height * threshold || area >= r2.width * r2.height * threshold; 6881 } 6882 return overlap.width > threshold && overlap.height > threshold; 6883 }; 6884 _placeholderDiv.style.cssText = "visibility:hidden;height:1px;top:-1px;pointer-events:none;position:relative;clear:both;"; 6885 return _Draggable; 6886 }, true); 6887}); 6888if (_gsScope._gsDefine) { 6889 _gsScope._gsQueue.pop()(); 6890} 6891 6892//export to AMD/RequireJS and CommonJS/Node (precursor to full modular build system coming at a later date) 6893(function (name) { 6894 "use strict"; 6895 6896 var getGlobal = function getGlobal() { 6897 return (_gsScope.GreenSockGlobals || _gsScope)[name]; 6898 }; 6899 if (typeof module !== "undefined" && module.exports) { 6900 //node 6901 require("gsap/TweenLite"); 6902 require("gsap/CSSPlugin"); 6903 module.exports = getGlobal(); 6904 } else if (typeof define === "function" && define.amd) { 6905 //AMD 6906 define(["gsap/TweenLite", "gsap/CSSPlugin"], getGlobal); 6907 } 6908})("Draggable"); 6909 6910}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 6911},{"gsap/CSSPlugin":2,"gsap/TweenLite":4}],4:[function(require,module,exports){ 6912(function (global){(function (){ 6913"use strict"; 6914 6915function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 6916/*! 6917 * VERSION: 1.20.4 6918 * DATE: 2018-02-15 6919 * UPDATES AND DOCS AT: http://greensock.com 6920 * 6921 * @license Copyright (c) 2008-2018, GreenSock. All rights reserved. 6922 * This work is subject to the terms at http://greensock.com/standard-license or for 6923 * Club GreenSock members, the software agreement that was issued with your membership. 6924 * 6925 * @author: Jack Doyle, [email protected] 6926 */ 6927(function (window, moduleName) { 6928 "use strict"; 6929 6930 var _exports = {}, 6931 _doc = window.document, 6932 _globals = window.GreenSockGlobals = window.GreenSockGlobals || window; 6933 if (_globals.TweenLite) { 6934 return; //in case the core set of classes is already loaded, don't instantiate twice. 6935 } 6936 var _namespace = function _namespace(ns) { 6937 var a = ns.split("."), 6938 p = _globals, 6939 i; 6940 for (i = 0; i < a.length; i++) { 6941 p[a[i]] = p = p[a[i]] || {}; 6942 } 6943 return p; 6944 }, 6945 gs = _namespace("com.greensock"), 6946 _tinyNum = 0.0000000001, 6947 _slice = function _slice(a) { 6948 //don't use Array.prototype.slice.call(target, 0) because that doesn't work in IE8 with a NodeList that's returned by querySelectorAll() 6949 var b = [], 6950 l = a.length, 6951 i; 6952 for (i = 0; i !== l; b.push(a[i++])) {} 6953 return b; 6954 }, 6955 _emptyFunc = function _emptyFunc() {}, 6956 _isArray = function () { 6957 //works around issues in iframe environments where the Array global isn't shared, thus if the object originates in a different window/iframe, "(obj instanceof Array)" will evaluate false. We added some speed optimizations to avoid Object.prototype.toString.call() unless it's absolutely necessary because it's VERY slow (like 20x slower) 6958 var toString = Object.prototype.toString, 6959 array = toString.call([]); 6960 return function (obj) { 6961 return obj != null && (obj instanceof Array || _typeof(obj) === "object" && !!obj.push && toString.call(obj) === array); 6962 }; 6963 }(), 6964 a, 6965 i, 6966 p, 6967 _ticker, 6968 _tickerActive, 6969 _defLookup = {}, 6970 /** 6971 * @constructor 6972 * Defines a GreenSock class, optionally with an array of dependencies that must be instantiated first and passed into the definition. 6973 * This allows users to load GreenSock JS files in any order even if they have interdependencies (like CSSPlugin extends TweenPlugin which is 6974 * inside TweenLite.js, but if CSSPlugin is loaded first, it should wait to run its code until TweenLite.js loads and instantiates TweenPlugin 6975 * and then pass TweenPlugin to CSSPlugin's definition). This is all done automatically and internally. 6976 * 6977 * Every definition will be added to a "com.greensock" global object (typically window, but if a window.GreenSockGlobals object is found, 6978 * it will go there as of v1.7). For example, TweenLite will be found at window.com.greensock.TweenLite and since it's a global class that should be available anywhere, 6979 * it is ALSO referenced at window.TweenLite. However some classes aren't considered global, like the base com.greensock.core.Animation class, so 6980 * those will only be at the package like window.com.greensock.core.Animation. Again, if you define a GreenSockGlobals object on the window, everything 6981 * gets tucked neatly inside there instead of on the window directly. This allows you to do advanced things like load multiple versions of GreenSock 6982 * files and put them into distinct objects (imagine a banner ad uses a newer version but the main site uses an older one). In that case, you could
6983 * sandbox the banner one like: 6984 * 6985 * <script> 6986 * var gs = window.GreenSockGlobals = {}; //the newer version we're about to load could now be referenced in a "gs" object, like gs.TweenLite.to(...). Use whatever alias you want as long as it's unique, "gs" or "banner" or whatever. 6987 * </script> 6988 * <script src="js/greensock/v1.7/TweenMax.js"></script> 6989 * <script> 6990 * window.GreenSockGlobals = window._gsQueue = window._gsDefine = null; //reset it back to null (along with the special _gsQueue variable) so that the next load of TweenMax affects the window and we can reference things directly like TweenLite.to(...) 6991 * </script> 6992 * <script src="js/greensock/v1.6/TweenMax.js"></script> 6993 * <script> 6994 * gs.TweenLite.to(...); //would use v1.7 6995 * TweenLite.to(...); //would use v1.6 6996 * </script> 6997 * 6998 * @param {!string} ns The namespace of the class definition, leaving off "com.greensock." as that's assumed. For example, "TweenLite" or "plugins.CSSPlugin" or "easing.Back". 6999 * @param {!Array.<string>} dependencies An array of dependencies (described as their namespaces minus "com.greensock." prefix). For example ["TweenLite","plugins.TweenPlugin","core.Animation"] 7000 * @param {!function():Object} func The function that should be called and passed the resolved dependencies which will return the actual class for this definition. 7001 * @param {boolean=} global If true, the class will be added to the global scope (typically window unless you define a window.GreenSockGlobals object) 7002 */ 7003 _Definition = function Definition(ns, dependencies, func, global) { 7004 this.sc = _defLookup[ns] ? _defLookup[ns].sc : []; //subclasses 7005 _defLookup[ns] = this; 7006 this.gsClass = null; 7007 this.func = func; 7008 var _classes = []; 7009 this.check = function (init) { 7010 var i = dependencies.length, 7011 missing = i, 7012 cur, 7013 a, 7014 n, 7015 cl; 7016 while (--i > -1) { 7017 if ((cur = _defLookup[dependencies[i]] || new _Definition(dependencies[i], [])).gsClass) { 7018 _classes[i] = cur.gsClass; 7019 missing--; 7020 } else if (init) { 7021 cur.sc.push(this); 7022 } 7023 } 7024 if (missing === 0 && func) { 7025 a = ("com.greensock." + ns).split("."); 7026 n = a.pop(); 7027 cl = _namespace(a.join("."))[n] = this.gsClass = func.apply(func, _classes); 7028 7029 //exports to multiple environments 7030 if (global) { 7031 _globals[n] = _exports[n] = cl; //provides a way to avoid global namespace pollution. By default, the main classes like TweenLite, Power1, Strong, etc. are added to window unless a GreenSockGlobals is defined. So if you want to have things added to a custom object instead, just do something like window.GreenSockGlobals = {} before loading any GreenSock files. You can even set up an alias like window.GreenSockGlobals = windows.gs = {} so that you can access everything like gs.TweenLite. Also remember that ALL classes are added to the window.com.greensock object (in their respective packages, like com.greensock.easing.Power1, com.greensock.TweenLite, etc.) 7032 if (typeof module !== "undefined" && module.exports) { 7033 //node 7034 if (ns === moduleName) { 7035 module.exports = _exports[moduleName] = cl; 7036 for (i in _exports) { 7037 cl[i] = _exports[i]; 7038 } 7039 } else if (_exports[moduleName]) { 7040 _exports[moduleName][n] = cl; 7041 } 7042 } else if (typeof define === "function" && define.amd) { 7043 //AMD 7044 define((window.GreenSockAMDPath ? window.GreenSockAMDPath + "/" : "") + ns.split(".").pop(), [], function () { 7045 return cl; 7046 }); 7047 } 7048 } 7049 for (i = 0; i < this.sc.length; i++) { 7050 this.sc[i].check(); 7051 } 7052 } 7053 }; 7054 this.check(true); 7055 }, 7056 //used to create Definition instances (which basically registers a class that has dependencies). 7057 _gsDefine = window._gsDefine = function (ns, dependencies, func, global) { 7058 return new _Definition(ns, dependencies, func, global); 7059 }, 7060 //a quick way to create a class that doesn't have any dependencies. Returns the class, but first registers it in the GreenSock namespace so that other classes can grab it (other classes might be dependent on the class). 7061 _class = gs._class = function (ns, func, global) { 7062 func = func || function () {}; 7063 _gsDefine(ns, [], function () { 7064 return func; 7065 }, global); 7066 return func; 7067 }; 7068 _gsDefine.globals = _globals; 7069 7070 /* 7071 * ---------------------------------------------------------------- 7072 * Ease 7073 * ---------------------------------------------------------------- 7074 */ 7075 var _baseParams = [0, 0, 1, 1], 7076 Ease = _class("easing.Ease", function (func, extraParams, type, power) { 7077 this._func = func; 7078 this._type = type || 0; 7079 this._power = power || 0; 7080 this._params = extraParams ? _baseParams.concat(extraParams) : _baseParams; 7081 }, true), 7082 _easeMap = Ease.map = {}, 7083 _easeReg = Ease.register = function (ease, names, types, create) { 7084 var na = names.split(","), 7085 i = na.length, 7086 ta = (types || "easeIn,easeOut,easeInOut").split(","), 7087 e, 7088 name, 7089 j, 7090 type; 7091 while (--i > -1) { 7092 name = na[i]; 7093 e = create ? _class("easing." + name, null, true) : gs.easing[name] || {}; 7094 j = ta.length; 7095 while (--j > -1) { 7096 type = ta[j]; 7097 _easeMap[name + "." + type] = _easeMap[type + name] = e[type] = ease.getRatio ? ease : ease[type] || new ease(); 7098 } 7099 } 7100 }; 7101 p = Ease.prototype; 7102 p._calcEnd = false;
7103 p.getRatio = function (p) { 7104 if (this._func) { 7105 this._params[0] = p; 7106 return this._func.apply(null, this._params); 7107 } 7108 var t = this._type, 7109 pw = this._power, 7110 r = t === 1 ? 1 - p : t === 2 ? p : p < 0.5 ? p * 2 : (1 - p) * 2; 7111 if (pw === 1) { 7112 r *= r; 7113 } else if (pw === 2) { 7114 r *= r * r; 7115 } else if (pw === 3) { 7116 r *= r * r * r; 7117 } else if (pw === 4) { 7118 r *= r * r * r * r; 7119 } 7120 return t === 1 ? 1 - r : t === 2 ? r : p < 0.5 ? r / 2 : 1 - r / 2; 7121 }; 7122 7123 //create all the standard eases like Linear, Quad, Cubic, Quart, Quint, Strong, Power0, Power1, Power2, Power3, and Power4 (each with easeIn, easeOut, and easeInOut) 7124 a = ["Linear", "Quad", "Cubic", "Quart", "Quint,Strong"]; 7125 i = a.length; 7126 while (--i > -1) { 7127 p = a[i] + ",Power" + i; 7128 _easeReg(new Ease(null, null, 1, i), p, "easeOut", true); 7129 _easeReg(new Ease(null, null, 2, i), p, "easeIn" + (i === 0 ? ",easeNone" : "")); 7130 _easeReg(new Ease(null, null, 3, i), p, "easeInOut"); 7131 } 7132 _easeMap.linear = gs.easing.Linear.easeIn; 7133 _easeMap.swing = gs.easing.Quad.easeInOut; //for jQuery folks 7134 7135 /* 7136 * ---------------------------------------------------------------- 7137 * EventDispatcher 7138 * ---------------------------------------------------------------- 7139 */ 7140 var EventDispatcher = _class("events.EventDispatcher", function (target) { 7141 this._listeners = {}; 7142 this._eventTarget = target || this; 7143 }); 7144 p = EventDispatcher.prototype; 7145 p.addEventListener = function (type, callback, scope, useParam, priority) { 7146 priority = priority || 0; 7147 var list = this._listeners[type], 7148 index = 0, 7149 listener, 7150 i; 7151 if (this === _ticker && !_tickerActive) { 7152 _ticker.wake(); 7153 } 7154 if (list == null) { 7155 this._listeners[type] = list = []; 7156 } 7157 i = list.length; 7158 while (--i > -1) { 7159 listener = list[i]; 7160 if (listener.c === callback && listener.s === scope) { 7161 list.splice(i, 1); 7162 } else if (index === 0 && listener.pr < priority) { 7163 index = i + 1; 7164 } 7165 } 7166 list.splice(index, 0, { 7167 c: callback, 7168 s: scope, 7169 up: useParam, 7170 pr: priority 7171 }); 7172 }; 7173 p.removeEventListener = function (type, callback) { 7174 var list = this._listeners[type], 7175 i; 7176 if (list) { 7177 i = list.length; 7178 while (--i > -1) { 7179 if (list[i].c === callback) { 7180 list.splice(i, 1); 7181 return; 7182 } 7183 } 7184 } 7185 }; 7186 p.dispatchEvent = function (type) { 7187 var list = this._listeners[type], 7188 i, 7189 t, 7190 listener; 7191 if (list) { 7192 i = list.length; 7193 if (i > 1) { 7194 list = list.slice(0); //in case addEventListener() is called from within a listener/callback (otherwise the index could change, resulting in a skip) 7195 } 7196 t = this._eventTarget; 7197 while (--i > -1) { 7198 listener = list[i]; 7199 if (listener) { 7200 if (listener.up) { 7201 listener.c.call(listener.s || t, { 7202 type: type, 7203 target: t 7204 }); 7205 } else { 7206 listener.c.call(listener.s || t); 7207 } 7208 } 7209 } 7210 } 7211 }; 7212 7213 /* 7214 * ---------------------------------------------------------------- 7215 * Ticker 7216 * ---------------------------------------------------------------- 7217 */ 7218 var _reqAnimFrame = window.requestAnimationFrame, 7219 _cancelAnimFrame = window.cancelAnimationFrame, 7220 _getTime = Date.now || function () { 7221 return new Date().getTime(); 7222 }, 7223 _lastUpdate = _getTime(); 7224 7225 //now try to determine the requestAnimationFrame and cancelAnimationFrame functions and if none are found, we'll use a setTimeout()/clearTimeout() polyfill. 7226 a = ["ms", "moz", "webkit", "o"]; 7227 i = a.length; 7228 while (--i > -1 && !_reqAnimFrame) { 7229 _reqAnimFrame = window[a[i] + "RequestAnimationFrame"]; 7230 _cancelAnimFrame = window[a[i] + "CancelAnimationFrame"] || window[a[i] + "CancelRequestAnimationFrame"]; 7231 } 7232 _class("Ticker", function (fps, useRAF) { 7233 var _self = this, 7234 _startTime = _getTime(), 7235 _useRAF = useRAF !== false && _reqAnimFrame ? "auto" : false, 7236 _lagThreshold = 500, 7237 _adjustedLag = 33, 7238 _tickWord = "tick", 7239 //helps reduce gc burden 7240 _fps, 7241 _req, 7242 _id, 7243 _gap, 7244 _nextTime, 7245 _tick2 = function _tick(manual) {
7246 var elapsed = _getTime() - _lastUpdate, 7247 overlap, 7248 dispatch; 7249 if (elapsed > _lagThreshold) { 7250 _startTime += elapsed - _adjustedLag; 7251 } 7252 _lastUpdate += elapsed; 7253 _self.time = (_lastUpdate - _startTime) / 1000; 7254 overlap = _self.time - _nextTime; 7255 if (!_fps || overlap > 0 || manual === true) { 7256 _self.frame++; 7257 _nextTime += overlap + (overlap >= _gap ? 0.004 : _gap - overlap); 7258 dispatch = true; 7259 } 7260 if (manual !== true) { 7261 //make sure the request is made before we dispatch the "tick" event so that timing is maintained. Otherwise, if processing the "tick" requires a bunch of time (like 15ms) and we're using a setTimeout() that's based on 16.7ms, it'd technically take 31.7ms between frames otherwise. 7262 _id = _req(_tick2); 7263 } 7264 if (dispatch) { 7265 _self.dispatchEvent(_tickWord); 7266 } 7267 }; 7268 EventDispatcher.call(_self); 7269 _self.time = _self.frame = 0; 7270 _self.tick = function () { 7271 _tick2(true); 7272 }; 7273 _self.lagSmoothing = function (threshold, adjustedLag) { 7274 if (!arguments.length) { 7275 //if lagSmoothing() is called with no arguments, treat it like a getter that returns a boolean indicating if it's enabled or not. This is purposely undocumented and is for internal use. 7276 return _lagThreshold < 1 / _tinyNum; 7277 } 7278 _lagThreshold = threshold || 1 / _tinyNum; //zero should be interpreted as basically unlimited 7279 _adjustedLag = Math.min(adjustedLag, _lagThreshold, 0); 7280 }; 7281 _self.sleep = function () { 7282 if (_id == null) { 7283 return; 7284 } 7285 if (!_useRAF || !_cancelAnimFrame) { 7286 clearTimeout(_id); 7287 } else { 7288 _cancelAnimFrame(_id); 7289 } 7290 _req = _emptyFunc; 7291 _id = null; 7292 if (_self === _ticker) { 7293 _tickerActive = false; 7294 } 7295 }; 7296 _self.wake = function (seamless) { 7297 if (_id !== null) { 7298 _self.sleep(); 7299 } else if (seamless) { 7300 _startTime += -_lastUpdate + (_lastUpdate = _getTime()); 7301 } else if (_self.frame > 10) { 7302 //don't trigger lagSmoothing if we're just waking up, and make sure that at least 10 frames have elapsed because of the iOS bug that we work around below with the 1.5-second setTimout(). 7303 _lastUpdate = _getTime() - _lagThreshold + 5; 7304 } 7305 _req = _fps === 0 ? _emptyFunc : !_useRAF || !_reqAnimFrame ? function (f) { 7306 return setTimeout(f, (_nextTime - _self.time) * 1000 + 1 | 0); 7307 } : _reqAnimFrame; 7308 if (_self === _ticker) { 7309 _tickerActive = true; 7310 } 7311 _tick2(2); 7312 }; 7313 _self.fps = function (value) { 7314 if (!arguments.length) { 7315 return _fps; 7316 } 7317 _fps = value; 7318 _gap = 1 / (_fps || 60); 7319 _nextTime = this.time + _gap; 7320 _self.wake(); 7321 }; 7322 _self.useRAF = function (value) { 7323 if (!arguments.length) { 7324 return _useRAF; 7325 } 7326 _self.sleep(); 7327 _useRAF = value; 7328 _self.fps(_fps); 7329 }; 7330 _self.fps(fps); 7331 7332 //a bug in iOS 6 Safari occasionally prevents the requestAnimationFrame from working initially, so we use a 1.5-second timeout that automatically falls back to setTimeout() if it senses this condition. 7333 setTimeout(function () { 7334 if (_useRAF === "auto" && _self.frame < 5 && (_doc || {}).visibilityState !== "hidden") { 7335 _self.useRAF(false); 7336 } 7337 }, 1500); 7338 }); 7339 p = gs.Ticker.prototype = new gs.events.EventDispatcher(); 7340 p.constructor = gs.Ticker; 7341 7342 /* 7343 * ---------------------------------------------------------------- 7344 * Animation 7345 * ---------------------------------------------------------------- 7346 */ 7347 var Animation = _class("core.Animation", function (duration, vars) { 7348 this.vars = vars = vars || {}; 7349 this._duration = this._totalDuration = duration || 0; 7350 this._delay = Number(vars.delay) || 0; 7351 this._timeScale = 1; 7352 this._active = vars.immediateRender === true; 7353 this.data = vars.data; 7354 this._reversed = vars.reversed === true; 7355 if (!_rootTimeline) { 7356 return; 7357 } 7358 if (!_tickerActive) { 7359 //some browsers (like iOS 6 Safari) shut down JavaScript execution when the tab is disabled and they [occasionally] neglect to start up requestAnimationFrame again when returning - this code ensures that the engine starts up again properly. 7360 _ticker.wake(); 7361 } 7362 var tl = this.vars.useFrames ? _rootFramesTimeline : _rootTimeline; 7363 tl.add(this, tl._time); 7364 if (this.vars.paused) { 7365 this.paused(true); 7366 } 7367 }); 7368 _ticker = Animation.ticker = new gs.Ticker(); 7369 p = Animation.prototype; 7370 p._dirty = p._gc = p._initted = p._paused = false;
7371 p._totalTime = p._time = 0; 7372 p._rawPrevTime = -1; 7373 p._next = p._last = p._onUpdate = p._timeline = p.timeline = null; 7374 p._paused = false; 7375 7376 //some browsers (like iOS) occasionally drop the requestAnimationFrame event when the user switches to a different tab and then comes back again, so we use a 2-second setTimeout() to sense if/when that condition occurs and then wake() the ticker. 7377 var _checkTimeout2 = function _checkTimeout() { 7378 if (_tickerActive && _getTime() - _lastUpdate > 2000 && ((_doc || {}).visibilityState !== "hidden" || !_ticker.lagSmoothing())) { 7379 //note: if the tab is hidden, we should still wake if lagSmoothing has been disabled. 7380 _ticker.wake(); 7381 } 7382 var t = setTimeout(_checkTimeout2, 2000); 7383 if (t.unref) { 7384 // allows a node process to exit even if the timeout’s callback hasn't been invoked. Without it, the node process could hang as this function is called every two seconds. 7385 t.unref(); 7386 } 7387 }; 7388 _checkTimeout2(); 7389 p.play = function (from, suppressEvents) { 7390 if (from != null) { 7391 this.seek(from, suppressEvents); 7392 } 7393 return this.reversed(false).paused(false); 7394 }; 7395 p.pause = function (atTime, suppressEvents) { 7396 if (atTime != null) { 7397 this.seek(atTime, suppressEvents); 7398 } 7399 return this.paused(true); 7400 }; 7401 p.resume = function (from, suppressEvents) { 7402 if (from != null) { 7403 this.seek(from, suppressEvents); 7404 } 7405 return this.paused(false); 7406 }; 7407 p.seek = function (time, suppressEvents) { 7408 return this.totalTime(Number(time), suppressEvents !== false); 7409 }; 7410 p.restart = function (includeDelay, suppressEvents) { 7411 return this.reversed(false).paused(false).totalTime(includeDelay ? -this._delay : 0, suppressEvents !== false, true); 7412 }; 7413 p.reverse = function (from, suppressEvents) { 7414 if (from != null) { 7415 this.seek(from || this.totalDuration(), suppressEvents); 7416 } 7417 return this.reversed(true).paused(false); 7418 }; 7419 p.render = function (time, suppressEvents, force) { 7420 //stub - we override this method in subclasses. 7421 }; 7422 p.invalidate = function () { 7423 this._time = this._totalTime = 0; 7424 this._initted = this._gc = false; 7425 this._rawPrevTime = -1; 7426 if (this._gc || !this.timeline) { 7427 this._enabled(true); 7428 } 7429 return this; 7430 }; 7431 p.isActive = function () { 7432 var tl = this._timeline, 7433 //the 2 root timelines won't have a _timeline; they're always active. 7434 startTime = this._startTime, 7435 rawTime; 7436 return !tl || !this._gc && !this._paused && tl.isActive() && (rawTime = tl.rawTime(true)) >= startTime && rawTime < startTime + this.totalDuration() / this._timeScale - 0.0000001; 7437 }; 7438 p._enabled = function (enabled, ignoreTimeline) { 7439 if (!_tickerActive) { 7440 _ticker.wake(); 7441 } 7442 this._gc = !enabled; 7443 this._active = this.isActive(); 7444 if (ignoreTimeline !== true) { 7445 if (enabled && !this.timeline) { 7446 this._timeline.add(this, this._startTime - this._delay); 7447 } else if (!enabled && this.timeline) { 7448 this._timeline._remove(this, true); 7449 } 7450 } 7451 return false; 7452 }; 7453 p._kill = function (vars, target) { 7454 return this._enabled(false, false); 7455 }; 7456 p.kill = function (vars, target) { 7457 this._kill(vars, target); 7458 return this; 7459 }; 7460 p._uncache = function (includeSelf) { 7461 var tween = includeSelf ? this : this.timeline; 7462 while (tween) { 7463 tween._dirty = true; 7464 tween = tween.timeline; 7465 } 7466 return this; 7467 }; 7468 p._swapSelfInParams = function (params) { 7469 var i = params.length, 7470 copy = params.concat(); 7471 while (--i > -1) { 7472 if (params[i] === "{self}") { 7473 copy[i] = this; 7474 } 7475 } 7476 return copy; 7477 }; 7478 p._callback = function (type) { 7479 var v = this.vars, 7480 callback = v[type], 7481 params = v[type + "Params"], 7482 scope = v[type + "Scope"] || v.callbackScope || this, 7483 l = params ? params.length : 0; 7484 switch (l) { 7485 //speed optimization; call() is faster than apply() so use it when there are only a few parameters (which is by far most common). Previously we simply did var v = this.vars; v[type].apply(v[type + "Scope"] || v.callbackScope || this, v[type + "Params"] || _blankArray); 7486 case 0: 7487 callback.call(scope); 7488 break; 7489 case 1: 7490 callback.call(scope, params[0]); 7491 break; 7492 case 2: 7493 callback.call(scope, params[0], params[1]); 7494 break; 7495 default: 7496 callback.apply(scope, params); 7497 } 7498 }; 7499 7500 //----Animation getters/setters -------------------------------------------------------- 7501 7502 p.eventCallback = function (type, callback, params, scope) { 7503 if ((type || "").substr(0, 2) === "on") { 7504 var v = this.vars; 7505 if (arguments.length === 1) { 7506 return v[type]; 7507 } 7508 if (callback == null) { 7509 delete v[type]; 7510 } else { 7511 v[type] = callback; 7512 v[type + "Params"] = _isArray(params) && params.join("").indexOf("{self}") !== -1 ? this._swapSelfInParams(params) : params; 7513 v[type + "Scope"] = scope; 7514 } 7515 if (type === "onUpdate") { 7516 this._onUpdate = callback; 7517 } 7518 } 7519 return this; 7520 }; 7521 p.delay = function (value) { 7522 if (!arguments.length) { 7523 return this._delay; 7524 } 7525 if (this._timeline.smoothChildTiming) { 7526 this.startTime(this._startTime + value - this._delay); 7527 }
7528 this._delay = value; 7529 return this; 7530 }; 7531 p.duration = function (value) { 7532 if (!arguments.length) { 7533 this._dirty = false; 7534 return this._duration; 7535 } 7536 this._duration = this._totalDuration = value; 7537 this._uncache(true); //true in case it's a TweenMax or TimelineMax that has a repeat - we'll need to refresh the totalDuration. 7538 if (this._timeline.smoothChildTiming) if (this._time > 0) if (this._time < this._duration) if (value !== 0) { 7539 this.totalTime(this._totalTime * (value / this._duration), true); 7540 } 7541 return this; 7542 }; 7543 p.totalDuration = function (value) { 7544 this._dirty = false; 7545 return !arguments.length ? this._totalDuration : this.duration(value); 7546 }; 7547 p.time = function (value, suppressEvents) { 7548 if (!arguments.length) { 7549 return this._time; 7550 } 7551 if (this._dirty) { 7552 this.totalDuration(); 7553 } 7554 return this.totalTime(value > this._duration ? this._duration : value, suppressEvents); 7555 }; 7556 p.totalTime = function (time, suppressEvents, uncapped) { 7557 if (!_tickerActive) { 7558 _ticker.wake(); 7559 } 7560 if (!arguments.length) { 7561 return this._totalTime; 7562 } 7563 if (this._timeline) { 7564 if (time < 0 && !uncapped) { 7565 time += this.totalDuration(); 7566 } 7567 if (this._timeline.smoothChildTiming) { 7568 if (this._dirty) { 7569 this.totalDuration(); 7570 } 7571 var totalDuration = this._totalDuration, 7572 tl = this._timeline; 7573 if (time > totalDuration && !uncapped) { 7574 time = totalDuration; 7575 } 7576 this._startTime = (this._paused ? this._pauseTime : tl._time) - (!this._reversed ? time : totalDuration - time) / this._timeScale; 7577 if (!tl._dirty) { 7578 //for performance improvement. If the parent's cache is already dirty, it already took care of marking the ancestors as dirty too, so skip the function call here. 7579 this._uncache(false); 7580 } 7581 //in case any of the ancestor timelines had completed but should now be enabled, we should reset their totalTime() which will also ensure that they're lined up properly and enabled. Skip for animations that are on the root (wasteful). Example: a TimelineLite.exportRoot() is performed when there's a paused tween on the root, the export will not complete until that tween is unpaused, but imagine a child gets restarted later, after all [unpaused] tweens have completed. The startTime of that child would get pushed out, but one of the ancestors may have completed. 7582 if (tl._timeline) { 7583 while (tl._timeline) { 7584 if (tl._timeline._time !== (tl._startTime + tl._totalTime) / tl._timeScale) { 7585 tl.totalTime(tl._totalTime, true); 7586 } 7587 tl = tl._timeline; 7588 } 7589 } 7590 } 7591 if (this._gc) { 7592 this._enabled(true, false); 7593 } 7594 if (this._totalTime !== time || this._duration === 0) { 7595 if (_lazyTweens.length) { 7596 _lazyRender(); 7597 } 7598 this.render(time, suppressEvents, false); 7599 if (_lazyTweens.length) { 7600 //in case rendering caused any tweens to lazy-init, we should render them because typically when someone calls seek() or time() or progress(), they expect an immediate render. 7601 _lazyRender(); 7602 } 7603 } 7604 } 7605 return this; 7606 }; 7607 p.progress = p.totalProgress = function (value, suppressEvents) { 7608 var duration = this.duration(); 7609 return !arguments.length ? duration ? this._time / duration : this.ratio : this.totalTime(duration * value, suppressEvents); 7610 }; 7611 p.startTime = function (value) { 7612 if (!arguments.length) { 7613 return this._startTime; 7614 } 7615 if (value !== this._startTime) { 7616 this._startTime = value; 7617 if (this.timeline) if (this.timeline._sortChildren) { 7618 this.timeline.add(this, value - this._delay); //ensures that any necessary re-sequencing of Animations in the timeline occurs to make sure the rendering order is correct. 7619 } 7620 } 7621 return this; 7622 }; 7623 p.endTime = function (includeRepeats) { 7624 return this._startTime + (includeRepeats != false ? this.totalDuration() : this.duration()) / this._timeScale; 7625 }; 7626 p.timeScale = function (value) { 7627 if (!arguments.length) { 7628 return this._timeScale; 7629 } 7630 var pauseTime, t; 7631 value = value || _tinyNum; //can't allow zero because it'll throw the math off 7632 if (this._timeline && this._timeline.smoothChildTiming) { 7633 pauseTime = this._pauseTime; 7634 t = pauseTime || pauseTime === 0 ? pauseTime : this._timeline.totalTime(); 7635 this._startTime = t - (t - this._startTime) * this._timeScale / value; 7636 } 7637 this._timeScale = value; 7638 t = this.timeline; 7639 while (t && t.timeline) { 7640 //must update the duration/totalDuration of all ancestor timelines immediately in case in the middle of a render loop, one tween alters another tween's timeScale which shoves its startTime before 0, forcing the parent timeline to shift around and shiftChildren() which could affect that next tween's render (startTime). Doesn't matter for the root timeline though. 7641 t._dirty = true; 7642 t.totalDuration(); 7643 t = t.timeline; 7644 } 7645 return this; 7646 }; 7647 p.reversed = function (value) { 7648 if (!arguments.length) { 7649 return this._reversed; 7650 } 7651 if (value != this._reversed) { 7652 this._reversed = value; 7653 this.totalTime(this._timeline && !this._timeline.smoothChildTiming ? this.totalDuration() - this._totalTime : this._totalTime, true); 7654 } 7655 return this; 7656 }; 7657 p.paused = function (value) { 7658 if (!arguments.length) { 7659 return this._paused; 7660 } 7661 var tl = this._timeline, 7662 raw, 7663 elapsed; 7664 if (value != this._paused) if (tl) { 7665 if (!_tickerActive && !value) { 7666 _ticker.wake(); 7667 } 7668 raw = tl.rawTime();
7669 elapsed = raw - this._pauseTime; 7670 if (!value && tl.smoothChildTiming) { 7671 this._startTime += elapsed; 7672 this._uncache(false); 7673 } 7674 this._pauseTime = value ? raw : null; 7675 this._paused = value; 7676 this._active = this.isActive(); 7677 if (!value && elapsed !== 0 && this._initted && this.duration()) { 7678 raw = tl.smoothChildTiming ? this._totalTime : (raw - this._startTime) / this._timeScale; 7679 this.render(raw, raw === this._totalTime, true); //in case the target's properties changed via some other tween or manual update by the user, we should force a render. 7680 } 7681 } 7682 if (this._gc && !value) { 7683 this._enabled(true, false); 7684 } 7685 return this; 7686 }; 7687 7688 /* 7689 * ---------------------------------------------------------------- 7690 * SimpleTimeline 7691 * ---------------------------------------------------------------- 7692 */ 7693 var SimpleTimeline = _class("core.SimpleTimeline", function (vars) { 7694 Animation.call(this, 0, vars); 7695 this.autoRemoveChildren = this.smoothChildTiming = true; 7696 }); 7697 p = SimpleTimeline.prototype = new Animation(); 7698 p.constructor = SimpleTimeline; 7699 p.kill()._gc = false; 7700 p._first = p._last = p._recent = null; 7701 p._sortChildren = false; 7702 p.add = p.insert = function (child, position, align, stagger) { 7703 var prevTween, st; 7704 child._startTime = Number(position || 0) + child._delay; 7705 if (child._paused) if (this !== child._timeline) { 7706 //we only adjust the _pauseTime if it wasn't in this timeline already. Remember, sometimes a tween will be inserted again into the same timeline when its startTime is changed so that the tweens in the TimelineLite/Max are re-ordered properly in the linked list (so everything renders in the proper order). 7707 child._pauseTime = child._startTime + (this.rawTime() - child._startTime) / child._timeScale; 7708 } 7709 if (child.timeline) { 7710 child.timeline._remove(child, true); //removes from existing timeline so that it can be properly added to this one. 7711 } 7712 child.timeline = child._timeline = this; 7713 if (child._gc) { 7714 child._enabled(true, true); 7715 } 7716 prevTween = this._last; 7717 if (this._sortChildren) { 7718 st = child._startTime; 7719 while (prevTween && prevTween._startTime > st) { 7720 prevTween = prevTween._prev; 7721 } 7722 } 7723 if (prevTween) { 7724 child._next = prevTween._next; 7725 prevTween._next = child; 7726 } else { 7727 child._next = this._first; 7728 this._first = child; 7729 } 7730 if (child._next) { 7731 child._next._prev = child; 7732 } else { 7733 this._last = child; 7734 } 7735 child._prev = prevTween; 7736 this._recent = child; 7737 if (this._timeline) { 7738 this._uncache(true); 7739 } 7740 return this; 7741 }; 7742 p._remove = function (tween, skipDisable) { 7743 if (tween.timeline === this) { 7744 if (!skipDisable) { 7745 tween._enabled(false, true); 7746 } 7747 if (tween._prev) { 7748 tween._prev._next = tween._next; 7749 } else if (this._first === tween) { 7750 this._first = tween._next; 7751 } 7752 if (tween._next) { 7753 tween._next._prev = tween._prev; 7754 } else if (this._last === tween) { 7755 this._last = tween._prev; 7756 } 7757 tween._next = tween._prev = tween.timeline = null; 7758 if (tween === this._recent) { 7759 this._recent = this._last; 7760 } 7761 if (this._timeline) { 7762 this._uncache(true); 7763 } 7764 } 7765 return this; 7766 }; 7767 p.render = function (time, suppressEvents, force) { 7768 var tween = this._first, 7769 next; 7770 this._totalTime = this._time = this._rawPrevTime = time; 7771 while (tween) { 7772 next = tween._next; //record it here because the value could change after rendering... 7773 if (tween._active || time >= tween._startTime && !tween._paused && !tween._gc) { 7774 if (!tween._reversed) { 7775 tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force); 7776 } else { 7777 tween.render((!tween._dirty ? tween._totalDuration : tween.totalDuration()) - (time - tween._startTime) * tween._timeScale, suppressEvents, force); 7778 } 7779 } 7780 tween = next; 7781 } 7782 }; 7783 p.rawTime = function () { 7784 if (!_tickerActive) { 7785 _ticker.wake(); 7786 } 7787 return this._totalTime; 7788 }; 7789 7790 /* 7791 * ---------------------------------------------------------------- 7792 * TweenLite 7793 * ---------------------------------------------------------------- 7794 */ 7795 var TweenLite = _class("TweenLite", function (target, duration, vars) { 7796 Animation.call(this, duration, vars); 7797 this.render = TweenLite.prototype.render; //speed optimization (avoid prototype lookup on this "hot" method) 7798 7799 if (target == null) { 7800 throw "Cannot tween a null target."; 7801 } 7802 this.target = target = typeof target !== "string" ? target : TweenLite.selector(target) || target; 7803 var isSelector = target.jquery || target.length && target !== window && target[0] && (target[0] === window || target[0].nodeType && target[0].style && !target.nodeType),
7804 overwrite = this.vars.overwrite, 7805 i, 7806 targ, 7807 targets; 7808 this._overwrite = overwrite = overwrite == null ? _overwriteLookup[TweenLite.defaultOverwrite] : typeof overwrite === "number" ? overwrite >> 0 : _overwriteLookup[overwrite]; 7809 if ((isSelector || target instanceof Array || target.push && _isArray(target)) && typeof target[0] !== "number") { 7810 this._targets = targets = _slice(target); //don't use Array.prototype.slice.call(target, 0) because that doesn't work in IE8 with a NodeList that's returned by querySelectorAll() 7811 this._propLookup = []; 7812 this._siblings = []; 7813 for (i = 0; i < targets.length; i++) { 7814 targ = targets[i]; 7815 if (!targ) { 7816 targets.splice(i--, 1); 7817 continue; 7818 } else if (typeof targ === "string") { 7819 targ = targets[i--] = TweenLite.selector(targ); //in case it's an array of strings 7820 if (typeof targ === "string") { 7821 targets.splice(i + 1, 1); //to avoid an endless loop (can't imagine why the selector would return a string, but just in case) 7822 } 7823 continue; 7824 } else if (targ.length && targ !== window && targ[0] && (targ[0] === window || targ[0].nodeType && targ[0].style && !targ.nodeType)) { 7825 //in case the user is passing in an array of selector objects (like jQuery objects), we need to check one more level and pull things out if necessary. Also note that <select> elements pass all the criteria regarding length and the first child having style, so we must also check to ensure the target isn't an HTML node itself. 7826 targets.splice(i--, 1); 7827 this._targets = targets = targets.concat(_slice(targ)); 7828 continue; 7829 } 7830 this._siblings[i] = _register(targ, this, false); 7831 if (overwrite === 1) if (this._siblings[i].length > 1) { 7832 _applyOverwrite(targ, this, null, 1, this._siblings[i]); 7833 } 7834 } 7835 } else { 7836 this._propLookup = {}; 7837 this._siblings = _register(target, this, false); 7838 if (overwrite === 1) if (this._siblings.length > 1) { 7839 _applyOverwrite(target, this, null, 1, this._siblings); 7840 } 7841 } 7842 if (this.vars.immediateRender || duration === 0 && this._delay === 0 && this.vars.immediateRender !== false) { 7843 this._time = -_tinyNum; //forces a render without having to set the render() "force" parameter to true because we want to allow lazying by default (using the "force" parameter always forces an immediate full render) 7844 this.render(Math.min(0, -this._delay)); //in case delay is negative 7845 } 7846 }, true), 7847 _isSelector = function _isSelector(v) { 7848 return v && v.length && v !== window && v[0] && (v[0] === window || v[0].nodeType && v[0].style && !v.nodeType); //we cannot check "nodeType" if the target is window from within an iframe, otherwise it will trigger a security error in some browsers like Firefox. 7849 }, 7850 _autoCSS = function _autoCSS(vars, target) { 7851 var css = {}, 7852 p; 7853 for (p in vars) { 7854 if (!_reservedProps[p] && (!(p in target) || p === "transform" || p === "x" || p === "y" || p === "width" || p === "height" || p === "className" || p === "border") && (!_plugins[p] || _plugins[p] && _plugins[p]._autoCSS)) { 7855 //note: <img> elements contain read-only "x" and "y" properties. We should also prioritize editing css width/height rather than the element's properties. 7856 css[p] = vars[p]; 7857 delete vars[p]; 7858 } 7859 } 7860 vars.css = css; 7861 }; 7862 p = TweenLite.prototype = new Animation(); 7863 p.constructor = TweenLite; 7864 p.kill()._gc = false; 7865 7866 //----TweenLite defaults, overwrite management, and root updates ---------------------------------------------------- 7867 7868 p.ratio = 0; 7869 p._firstPT = p._targets = p._overwrittenProps = p._startAt = null; 7870 p._notifyPluginsOfEnabled = p._lazy = false; 7871 TweenLite.version = "1.20.4"; 7872 TweenLite.defaultEase = p._ease = new Ease(null, null, 1, 1); 7873 TweenLite.defaultOverwrite = "auto"; 7874 TweenLite.ticker = _ticker; 7875 TweenLite.autoSleep = 120;
7876 TweenLite.lagSmoothing = function (threshold, adjustedLag) { 7877 _ticker.lagSmoothing(threshold, adjustedLag); 7878 }; 7879 TweenLite.selector = window.$ || window.jQuery || function (e) { 7880 var selector = window.$ || window.jQuery; 7881 if (selector) { 7882 TweenLite.selector = selector; 7883 return selector(e); 7884 } 7885 return typeof _doc === "undefined" ? e : _doc.querySelectorAll ? _doc.querySelectorAll(e) : _doc.getElementById(e.charAt(0) === "#" ? e.substr(1) : e); 7886 }; 7887 var _lazyTweens = [], 7888 _lazyLookup = {}, 7889 _numbersExp = /(?:(-|-=|\+=)?\d*\.?\d*(?:e[\-+]?\d+)?)[0-9]/ig, 7890 _relExp = /[\+-]=-?[\.\d]/, 7891 //_nonNumbersExp = /(?:([\-+](?!(\d|=)))|[^\d\-+=e]|(e(?![\-+][\d])))+/ig, 7892 _setRatio = function _setRatio(v) { 7893 var pt = this._firstPT, 7894 min = 0.000001, 7895 val; 7896 while (pt) { 7897 val = !pt.blob ? pt.c * v + pt.s : v === 1 && this.end != null ? this.end : v ? this.join("") : this.start; 7898 if (pt.m) { 7899 val = pt.m(val, this._target || pt.t); 7900 } else if (val < min) if (val > -min && !pt.blob) { 7901 //prevents issues with converting very small numbers to strings in the browser 7902 val = 0; 7903 } 7904 if (!pt.f) { 7905 pt.t[pt.p] = val; 7906 } else if (pt.fp) { 7907 pt.t[pt.p](pt.fp, val); 7908 } else { 7909 pt.t[pt.p](val); 7910 } 7911 pt = pt._next; 7912 } 7913 }, 7914 //compares two strings (start/end), finds the numbers that are different and spits back an array representing the whole value but with the changing values isolated as elements. For example, "rgb(0,0,0)" and "rgb(100,50,0)" would become ["rgb(", 0, ",", 50, ",0)"]. Notice it merges the parts that are identical (performance optimization). The array also has a linked list of PropTweens attached starting with _firstPT that contain the tweening data (t, p, s, c, f, etc.). It also stores the starting value as a "start" property so that we can revert to it if/when necessary, like when a tween rewinds fully. If the quantity of numbers differs between the start and end, it will always prioritize the end value(s). The pt parameter is optional - it's for a PropTween that will be appended to the end of the linked list and is typically for actually setting the value after all of the elements have been updated (with array.join("")). 7915 _blobDif = function _blobDif(start, end, filter, pt) { 7916 var a = [], 7917 charIndex = 0, 7918 s = "", 7919 color = 0, 7920 startNums, 7921 endNums, 7922 num, 7923 i, 7924 l, 7925 nonNumbers, 7926 currentNum; 7927 a.start = start; 7928 a.end = end; 7929 start = a[0] = start + ""; //ensure values are strings 7930 end = a[1] = end + ""; 7931 if (filter) { 7932 filter(a); //pass an array with the starting and ending values and let the filter do whatever it needs to the values. 7933 start = a[0]; 7934 end = a[1]; 7935 } 7936 a.length = 0; 7937 startNums = start.match(_numbersExp) || []; 7938 endNums = end.match(_numbersExp) || []; 7939 if (pt) { 7940 pt._next = null; 7941 pt.blob = 1; 7942 a._firstPT = a._applyPT = pt; //apply last in the linked list (which means inserting it first) 7943 } 7944 l = endNums.length; 7945 for (i = 0; i < l; i++) { 7946 currentNum = endNums[i]; 7947 nonNumbers = end.substr(charIndex, end.indexOf(currentNum, charIndex) - charIndex); 7948 s += nonNumbers || !i ? nonNumbers : ","; //note: SVG spec allows omission of comma/space when a negative sign is wedged between two numbers, like 2.5-5.3 instead of 2.5,-5.3 but when tweening, the negative value may switch to positive, so we insert the comma just in case. 7949 charIndex += nonNumbers.length; 7950 if (color) { 7951 //sense rgba() values and round them. 7952 color = (color + 1) % 5; 7953 } else if (nonNumbers.substr(-5) === "rgba(") { 7954 color = 1; 7955 } 7956 if (currentNum === startNums[i] || startNums.length <= i) { 7957 s += currentNum; 7958 } else { 7959 if (s) { 7960 a.push(s); 7961 s = ""; 7962 } 7963 num = parseFloat(startNums[i]); 7964 a.push(num); 7965 a._firstPT = { 7966 _next: a._firstPT, 7967 t: a, 7968 p: a.length - 1, 7969 s: num, 7970 c: (currentNum.charAt(1) === "=" ? parseInt(currentNum.charAt(0) + "1", 10) * parseFloat(currentNum.substr(2)) : parseFloat(currentNum) - num) || 0, 7971 f: 0, 7972 m: color && color < 4 ? Math.round : 0 7973 }; 7974 //note: we don't set _prev because we'll never need to remove individual PropTweens from this list. 7975 } 7976 charIndex += currentNum.length; 7977 } 7978 s += end.substr(charIndex); 7979 if (s) { 7980 a.push(s); 7981 } 7982 a.setRatio = _setRatio; 7983 if (_relExp.test(end)) { 7984 //if the end string contains relative values, delete it so that on the final render (in _setRatio()), we don't actually set it to the string with += or -= characters (forces it to use the calculated value). 7985 a.end = null; 7986 } 7987 return a; 7988 }, 7989 //note: "funcParam" is only necessary for function-based getters/setters that require an extra parameter like getAttribute("width") and setAttribute("width", value). In this example, funcParam would be "width". Used by AttrPlugin for example. 7990 _addPropTween = function _addPropTween(target, prop, start, end, overwriteProp, mod, funcParam, stringFilter, index) { 7991 if (typeof end === "function") { 7992 end = end(index || 0, target); 7993 } 7994 var type = _typeof(target[prop]), 7995 getterName = type !== "function" ? "" : prop.indexOf("set") || typeof target["get" + prop.substr(3)] !== "function" ? prop : "get" + prop.substr(3), 7996 s = start !== "get" ? start : !getterName ? target[prop] : funcParam ? target[getterName](funcParam) : target[getterName](), 7997 isRelative = typeof end === "string" && end.charAt(1) === "=", 7998 pt = { 7999 t: target, 8000 p: prop, 8001 s: s, 8002 f: type === "function", 8003 pg: 0, 8004 n: overwriteProp || prop, 8005 m: !mod ? 0 : typeof mod === "function" ? mod : Math.round, 8006 pr: 0, 8007 c: isRelative ? parseInt(end.charAt(0) + "1", 10) * parseFloat(end.substr(2)) : parseFloat(end) - s || 0 8008 }, 8009 blob; 8010 if (typeof s !== "number" || typeof end !== "number" && !isRelative) { 8011 if (funcParam || isNaN(s) || !isRelative && isNaN(end) || typeof s === "boolean" || typeof end === "boolean") { 8012 //a blob (string that has multiple numbers in it) 8013 pt.fp = funcParam; 8014 blob = _blobDif(s, isRelative ? parseFloat(pt.s) + pt.c + (pt.s + "").replace(/[0-9\-\.]/g, "") : end, stringFilter || TweenLite.defaultStringFilter, pt); 8015 pt = { 8016 t: blob, 8017 p: "setRatio", 8018 s: 0, 8019 c: 1, 8020 f: 2, 8021 pg: 0, 8022 n: overwriteProp || prop, 8023 pr: 0, 8024 m: 0 8025 }; //"2" indicates it's a Blob property tween. Needed for RoundPropsPlugin for example. 8026 } else { 8027 pt.s = parseFloat(s); 8028 if (!isRelative) { 8029 pt.c = parseFloat(end) - pt.s || 0; 8030 } 8031 } 8032 } 8033 if (pt.c) { 8034 //only add it to the linked list if there's a change. 8035 if (pt._next = this._firstPT) { 8036 pt._next._prev = pt; 8037 } 8038 this._firstPT = pt; 8039 return pt; 8040 } 8041 }, 8042 _internals = TweenLite._internals = { 8043 isArray: _isArray, 8044 isSelector: _isSelector, 8045 lazyTweens: _lazyTweens, 8046 blobDif: _blobDif 8047 }, 8048 //gives us a way to expose certain private values to other GreenSock classes without contaminating tha main TweenLite object. 8049 _plugins = TweenLite._plugins = {}, 8050 _tweenLookup = _internals.tweenLookup = {}, 8051 _tweenLookupNum = 0, 8052 _reservedProps = _internals.reservedProps = { 8053 ease: 1, 8054 delay: 1, 8055 overwrite: 1, 8056 onComplete: 1, 8057 onCompleteParams: 1, 8058 onCompleteScope: 1, 8059 useFrames: 1, 8060 runBackwards: 1, 8061 startAt: 1, 8062 onUpdate: 1, 8063 onUpdateParams: 1, 8064 onUpdateScope: 1, 8065 onStart: 1, 8066 onStartParams: 1, 8067 onStartScope: 1, 8068 onReverseComplete: 1, 8069 onReverseCompleteParams: 1, 8070 onReverseCompleteScope: 1, 8071 onRepeat: 1, 8072 onRepeatParams: 1, 8073 onRepeatScope: 1, 8074 easeParams: 1, 8075 yoyo: 1, 8076 immediateRender: 1, 8077 repeat: 1, 8078 repeatDelay: 1, 8079 data: 1, 8080 paused: 1, 8081 reversed: 1, 8082 autoCSS: 1, 8083 lazy: 1, 8084 onOverwrite: 1, 8085 callbackScope: 1,
8086 stringFilter: 1, 8087 id: 1, 8088 yoyoEase: 1 8089 }, 8090 _overwriteLookup = { 8091 none: 0, 8092 all: 1, 8093 auto: 2, 8094 concurrent: 3, 8095 allOnStart: 4, 8096 preexisting: 5, 8097 "true": 1, 8098 "false": 0 8099 }, 8100 _rootFramesTimeline = Animation._rootFramesTimeline = new SimpleTimeline(), 8101 _rootTimeline = Animation._rootTimeline = new SimpleTimeline(), 8102 _nextGCFrame = 30, 8103 _lazyRender = _internals.lazyRender = function () { 8104 var i = _lazyTweens.length, 8105 tween; 8106 _lazyLookup = {}; 8107 while (--i > -1) { 8108 tween = _lazyTweens[i]; 8109 if (tween && tween._lazy !== false) { 8110 tween.render(tween._lazy[0], tween._lazy[1], true); 8111 tween._lazy = false; 8112 } 8113 } 8114 _lazyTweens.length = 0; 8115 }; 8116 _rootTimeline._startTime = _ticker.time; 8117 _rootFramesTimeline._startTime = _ticker.frame; 8118 _rootTimeline._active = _rootFramesTimeline._active = true; 8119 setTimeout(_lazyRender, 1); //on some mobile devices, there isn't a "tick" before code runs which means any lazy renders wouldn't run before the next official "tick". 8120 8121 Animation._updateRoot = TweenLite.render = function () { 8122 var i, a, p; 8123 if (_lazyTweens.length) { 8124 //if code is run outside of the requestAnimationFrame loop, there may be tweens queued AFTER the engine refreshed, so we need to ensure any pending renders occur before we refresh again. 8125 _lazyRender(); 8126 } 8127 _rootTimeline.render((_ticker.time - _rootTimeline._startTime) * _rootTimeline._timeScale, false, false); 8128 _rootFramesTimeline.render((_ticker.frame - _rootFramesTimeline._startTime) * _rootFramesTimeline._timeScale, false, false); 8129 if (_lazyTweens.length) { 8130 _lazyRender(); 8131 } 8132 if (_ticker.frame >= _nextGCFrame) { 8133 //dump garbage every 120 frames or whatever the user sets TweenLite.autoSleep to 8134 _nextGCFrame = _ticker.frame + (parseInt(TweenLite.autoSleep, 10) || 120); 8135 for (p in _tweenLookup) { 8136 a = _tweenLookup[p].tweens; 8137 i = a.length; 8138 while (--i > -1) { 8139 if (a[i]._gc) { 8140 a.splice(i, 1); 8141 } 8142 } 8143 if (a.length === 0) { 8144 delete _tweenLookup[p]; 8145 } 8146 } 8147 //if there are no more tweens in the root timelines, or if they're all paused, make the _timer sleep to reduce load on the CPU slightly 8148 p = _rootTimeline._first; 8149 if (!p || p._paused) if (TweenLite.autoSleep && !_rootFramesTimeline._first && _ticker._listeners.tick.length === 1) { 8150 while (p && p._paused) { 8151 p = p._next; 8152 } 8153 if (!p) { 8154 _ticker.sleep(); 8155 } 8156 } 8157 } 8158 }; 8159 _ticker.addEventListener("tick", Animation._updateRoot); 8160 var _register = function _register(target, tween, scrub) { 8161 var id = target._gsTweenID, 8162 a, 8163 i; 8164 if (!_tweenLookup[id || (target._gsTweenID = id = "t" + _tweenLookupNum++)]) { 8165 _tweenLookup[id] = { 8166 target: target, 8167 tweens: [] 8168 }; 8169 } 8170 if (tween) { 8171 a = _tweenLookup[id].tweens; 8172 a[i = a.length] = tween; 8173 if (scrub) { 8174 while (--i > -1) { 8175 if (a[i] === tween) { 8176 a.splice(i, 1); 8177 } 8178 } 8179 } 8180 } 8181 return _tweenLookup[id].tweens; 8182 }, 8183 _onOverwrite = function _onOverwrite(overwrittenTween, overwritingTween, target, killedProps) { 8184 var func = overwrittenTween.vars.onOverwrite, 8185 r1, 8186 r2; 8187 if (func) { 8188 r1 = func(overwrittenTween, overwritingTween, target, killedProps); 8189 } 8190 func = TweenLite.onOverwrite; 8191 if (func) { 8192 r2 = func(overwrittenTween, overwritingTween, target, killedProps); 8193 } 8194 return r1 !== false && r2 !== false; 8195 }, 8196 _applyOverwrite = function _applyOverwrite(target, tween, props, mode, siblings) { 8197 var i, changed, curTween, l; 8198 if (mode === 1 || mode >= 4) { 8199 l = siblings.length; 8200 for (i = 0; i < l; i++) { 8201 if ((curTween = siblings[i]) !== tween) { 8202 if (!curTween._gc) { 8203 if (curTween._kill(null, target, tween)) { 8204 changed = true; 8205 } 8206 } 8207 } else if (mode === 5) { 8208 break; 8209 } 8210 } 8211 return changed; 8212 } 8213 //NOTE: Add 0.0000000001 to overcome floating point errors that can cause the startTime to be VERY slightly off (when a tween's time() is set for example) 8214 var startTime = tween._startTime + _tinyNum, 8215 overlaps = [], 8216 oCount = 0, 8217 zeroDur = tween._duration === 0, 8218 globalStart; 8219 i = siblings.length; 8220 while (--i > -1) { 8221 if ((curTween = siblings[i]) === tween || curTween._gc || curTween._paused) { 8222 //ignore 8223 } else if (curTween._timeline !== tween._timeline) { 8224 globalStart = globalStart || _checkOverlap(tween, 0, zeroDur); 8225 if (_checkOverlap(curTween, globalStart, zeroDur) === 0) { 8226 overlaps[oCount++] = curTween; 8227 } 8228 } else if (curTween._startTime <= startTime) if (curTween._startTime + curTween.totalDuration() / curTween._timeScale > startTime) if (!((zeroDur || !curTween._initted) && startTime - curTween._startTime <= 0.0000000002)) { 8229 overlaps[oCount++] = curTween; 8230 } 8231 } 8232 i = oCount; 8233 while (--i > -1) { 8234 curTween = overlaps[i]; 8235 if (mode === 2) if (curTween._kill(props, target, tween)) { 8236 changed = true; 8237 } 8238 if (mode !== 2 || !curTween._firstPT && curTween._initted) { 8239 if (mode !== 2 && !_onOverwrite(curTween, tween)) { 8240 continue; 8241 } 8242 if (curTween._enabled(false, false)) { 8243 //if all property tweens have been overwritten, kill the tween. 8244 changed = true; 8245 } 8246 } 8247 } 8248 return changed; 8249 }, 8250 _checkOverlap = function _checkOverlap(tween, reference, zeroDur) { 8251 var tl = tween._timeline, 8252 ts = tl._timeScale, 8253 t = tween._startTime; 8254 while (tl._timeline) { 8255 t += tl._startTime; 8256 ts *= tl._timeScale; 8257 if (tl._paused) { 8258 return -100; 8259 } 8260 tl = tl._timeline; 8261 } 8262 t /= ts; 8263 return t > reference ? t - reference : zeroDur && t === reference || !tween._initted && t - reference < 2 * _tinyNum ? _tinyNum : (t += tween.totalDuration() / tween._timeScale / ts) > reference + _tinyNum ? 0 : t - reference - _tinyNum; 8264 }; 8265 8266 //---- TweenLite instance methods ----------------------------------------------------------------------------- 8267 8268 p._init = function () { 8269 var v = this.vars, 8270 op = this._overwrittenProps, 8271 dur = this._duration, 8272 immediate = !!v.immediateRender, 8273 ease = v.ease, 8274 i, 8275 initPlugins, 8276 pt, 8277 p, 8278 startVars, 8279 l; 8280 if (v.startAt) { 8281 if (this._startAt) { 8282 this._startAt.render(-1, true); //if we've run a startAt previously (when the tween instantiated), we should revert it so that the values re-instantiate correctly particularly for relative tweens. Without this, a TweenLite.fromTo(obj, 1, {x:"+=100"}, {x:"-=100"}), for example, would actually jump to +=200 because the startAt would run twice, doubling the relative change. 8283 this._startAt.kill(); 8284 } 8285 startVars = {}; 8286 for (p in v.startAt) { 8287 //copy the properties/values into a new object to avoid collisions, like var to = {x:0}, from = {x:500}; timeline.fromTo(e, 1, from, to).fromTo(e, 1, to, from); 8288 startVars[p] = v.startAt[p]; 8289 } 8290 startVars.data = "isStart"; 8291 startVars.overwrite = false;
8292 startVars.immediateRender = true; 8293 startVars.lazy = immediate && v.lazy !== false; 8294 startVars.startAt = startVars.delay = null; //no nesting of startAt objects allowed (otherwise it could cause an infinite loop). 8295 startVars.onUpdate = v.onUpdate; 8296 startVars.onUpdateParams = v.onUpdateParams; 8297 startVars.onUpdateScope = v.onUpdateScope || v.callbackScope || this; 8298 this._startAt = TweenLite.to(this.target, 0, startVars); 8299 if (immediate) { 8300 if (this._time > 0) { 8301 this._startAt = null; //tweens that render immediately (like most from() and fromTo() tweens) shouldn't revert when their parent timeline's playhead goes backward past the startTime because the initial render could have happened anytime and it shouldn't be directly correlated to this tween's startTime. Imagine setting up a complex animation where the beginning states of various objects are rendered immediately but the tween doesn't happen for quite some time - if we revert to the starting values as soon as the playhead goes backward past the tween's startTime, it will throw things off visually. Reversion should only happen in TimelineLite/Max instances where immediateRender was false (which is the default in the convenience methods like from()). 8302 } else if (dur !== 0) { 8303 return; //we skip initialization here so that overwriting doesn't occur until the tween actually begins. Otherwise, if you create several immediateRender:true tweens of the same target/properties to drop into a TimelineLite or TimelineMax, the last one created would overwrite the first ones because they didn't get placed into the timeline yet before the first render occurs and kicks in overwriting. 8304 } 8305 } 8306 } else if (v.runBackwards && dur !== 0) { 8307 //from() tweens must be handled uniquely: their beginning values must be rendered but we don't want overwriting to occur yet (when time is still 0). Wait until the tween actually begins before doing all the routines like overwriting. At that time, we should render at the END of the tween to ensure that things initialize correctly (remember, from() tweens go backwards) 8308 if (this._startAt) { 8309 this._startAt.render(-1, true); 8310 this._startAt.kill(); 8311 this._startAt = null; 8312 } else { 8313 if (this._time !== 0) { 8314 //in rare cases (like if a from() tween runs and then is invalidate()-ed), immediateRender could be true but the initial forced-render gets skipped, so there's no need to force the render in this context when the _time is greater than 0 8315 immediate = false; 8316 } 8317 pt = {}; 8318 for (p in v) { 8319 //copy props into a new object and skip any reserved props, otherwise onComplete or onUpdate or onStart could fire. We should, however, permit autoCSS to go through. 8320 if (!_reservedProps[p] || p === "autoCSS") { 8321 pt[p] = v[p]; 8322 } 8323 } 8324 pt.overwrite = 0; 8325 pt.data = "isFromStart"; //we tag the tween with as "isFromStart" so that if [inside a plugin] we need to only do something at the very END of a tween, we have a way of identifying this tween as merely the one that's setting the beginning values for a "from()" tween. For example, clearProps in CSSPlugin should only get applied at the very END of a tween and without this tag, from(...{height:100, clearProps:"height", delay:1}) would wipe the height at the beginning of the tween and after 1 second, it'd kick back in. 8326 pt.lazy = immediate && v.lazy !== false; 8327 pt.immediateRender = immediate; //zero-duration tweens render immediately by default, but if we're not specifically instructed to render this tween immediately, we should skip this and merely _init() to record the starting values (rendering them immediately would push them to completion which is wasteful in that case - we'd have to render(-1) immediately after) 8328 this._startAt = TweenLite.to(this.target, 0, pt); 8329 if (!immediate) { 8330 this._startAt._init(); //ensures that the initial values are recorded 8331 this._startAt._enabled(false); //no need to have the tween render on the next cycle. Disable it because we'll always manually control the renders of the _startAt tween. 8332 if (this.vars.immediateRender) { 8333 this._startAt = null; 8334 } 8335 } else if (this._time === 0) { 8336 return; 8337 } 8338 } 8339 } 8340 this._ease = ease = !ease ? TweenLite.defaultEase : ease instanceof Ease ? ease : typeof ease === "function" ? new Ease(ease, v.easeParams) : _easeMap[ease] || TweenLite.defaultEase; 8341 if (v.easeParams instanceof Array && ease.config) { 8342 this._ease = ease.config.apply(ease, v.easeParams); 8343 } 8344 this._easeType = this._ease._type; 8345 this._easePower = this._ease._power; 8346 this._firstPT = null; 8347 if (this._targets) { 8348 l = this._targets.length; 8349 for (i = 0; i < l; i++) { 8350 if (this._initProps(this._targets[i], this._propLookup[i] = {}, this._siblings[i], op ? op[i] : null, i)) { 8351 initPlugins = true; 8352 } 8353 } 8354 } else { 8355 initPlugins = this._initProps(this.target, this._propLookup, this._siblings, op, 0); 8356 } 8357 if (initPlugins) { 8358 TweenLite._onPluginEvent("_onInitAllProps", this); //reorders the array in order of priority. Uses a static TweenPlugin method in order to minimize file size in TweenLite 8359 } 8360 if (op) if (!this._firstPT) if (typeof this.target !== "function") { 8361 //if all tweening properties have been overwritten, kill the tween. If the target is a function, it's probably a delayedCall so let it live. 8362 this._enabled(false, false); 8363 } 8364 if (v.runBackwards) { 8365 pt = this._firstPT; 8366 while (pt) { 8367 pt.s += pt.c; 8368 pt.c = -pt.c; 8369 pt = pt._next; 8370 } 8371 } 8372 this._onUpdate = v.onUpdate; 8373 this._initted = true; 8374 }; 8375 p._initProps = function (target, propLookup, siblings, overwrittenProps, index) { 8376 var p, i, initPlugins, plugin, pt, v; 8377 if (target == null) { 8378 return false;
8379 } 8380 if (_lazyLookup[target._gsTweenID]) { 8381 _lazyRender(); //if other tweens of the same target have recently initted but haven't rendered yet, we've got to force the render so that the starting values are correct (imagine populating a timeline with a bunch of sequential tweens and then jumping to the end) 8382 } 8383 if (!this.vars.css) if (target.style) if (target !== window && target.nodeType) if (_plugins.css) if (this.vars.autoCSS !== false) { 8384 //it's so common to use TweenLite/Max to animate the css of DOM elements, we assume that if the target is a DOM element, that's what is intended (a convenience so that users don't have to wrap things in css:{}, although we still recommend it for a slight performance boost and better specificity). Note: we cannot check "nodeType" on the window inside an iframe. 8385 _autoCSS(this.vars, target); 8386 } 8387 for (p in this.vars) { 8388 v = this.vars[p]; 8389 if (_reservedProps[p]) { 8390 if (v) if (v instanceof Array || v.push && _isArray(v)) if (v.join("").indexOf("{self}") !== -1) { 8391 this.vars[p] = v = this._swapSelfInParams(v, this); 8392 } 8393 } else if (_plugins[p] && (plugin = new _plugins[p]())._onInitTween(target, this.vars[p], this, index)) { 8394 //t - target [object] 8395 //p - property [string] 8396 //s - start [number] 8397 //c - change [number] 8398 //f - isFunction [boolean] 8399 //n - name [string] 8400 //pg - isPlugin [boolean] 8401 //pr - priority [number] 8402 //m - mod [function | 0] 8403 this._firstPT = pt = { 8404 _next: this._firstPT, 8405 t: plugin, 8406 p: "setRatio", 8407 s: 0, 8408 c: 1, 8409 f: 1, 8410 n: p, 8411 pg: 1, 8412 pr: plugin._priority, 8413 m: 0 8414 }; 8415 i = plugin._overwriteProps.length; 8416 while (--i > -1) { 8417 propLookup[plugin._overwriteProps[i]] = this._firstPT; 8418 } 8419 if (plugin._priority || plugin._onInitAllProps) { 8420 initPlugins = true; 8421 } 8422 if (plugin._onDisable || plugin._onEnable) { 8423 this._notifyPluginsOfEnabled = true; 8424 } 8425 if (pt._next) { 8426 pt._next._prev = pt; 8427 } 8428 } else { 8429 propLookup[p] = _addPropTween.call(this, target, p, "get", v, p, 0, null, this.vars.stringFilter, index); 8430 } 8431 } 8432 if (overwrittenProps) if (this._kill(overwrittenProps, target)) { 8433 //another tween may have tried to overwrite properties of this tween before init() was called (like if two tweens start at the same time, the one created second will run first) 8434 return this._initProps(target, propLookup, siblings, overwrittenProps, index); 8435 } 8436 if (this._overwrite > 1) if (this._firstPT) if (siblings.length > 1) if (_applyOverwrite(target, this, propLookup, this._overwrite, siblings)) { 8437 this._kill(propLookup, target); 8438 return this._initProps(target, propLookup, siblings, overwrittenProps, index); 8439 } 8440 if (this._firstPT) if (this.vars.lazy !== false && this._duration || this.vars.lazy && !this._duration) { 8441 //zero duration tweens don't lazy render by default; everything else does. 8442 _lazyLookup[target._gsTweenID] = true; 8443 } 8444 return initPlugins; 8445 }; 8446 p.render = function (time, suppressEvents, force) { 8447 var prevTime = this._time, 8448 duration = this._duration, 8449 prevRawPrevTime = this._rawPrevTime, 8450 isComplete, 8451 callback, 8452 pt, 8453 rawPrevTime; 8454 if (time >= duration - 0.0000001 && time >= 0) { 8455 //to work around occasional floating point math artifacts. 8456 this._totalTime = this._time = duration; 8457 this.ratio = this._ease._calcEnd ? this._ease.getRatio(1) : 1; 8458 if (!this._reversed) { 8459 isComplete = true; 8460 callback = "onComplete"; 8461 force = force || this._timeline.autoRemoveChildren; //otherwise, if the animation is unpaused/activated after it's already finished, it doesn't get removed from the parent timeline. 8462 } 8463 if (duration === 0) if (this._initted || !this.vars.lazy || force) { 8464 //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered. 8465 if (this._startTime === this._timeline._duration) { 8466 //if a zero-duration tween is at the VERY end of a timeline and that timeline renders at its end, it will typically add a tiny bit of cushion to the render time to prevent roun
8466ding errors from getting in the way of tweens rendering their VERY end. If we then reverse() that timeline, the zero-duration tween will trigger its onReverseComplete even though technically the playhead didn't pass over it again. It's a very specific edge case we must accommodate. 8467 time = 0; 8468 } 8469 if (prevRawPrevTime < 0 || time <= 0 && time >= -0.0000001 || prevRawPrevTime === _tinyNum && this.data !== "isPause") if (prevRawPrevTime !== time) { 8470 //note: when this.data is "isPause", it's a callback added by addPause() on a timeline that we should not be triggered when LEAVING its exact start time. In other words, tl.addPause(1).play(1) shouldn't pause. 8471 force = true; 8472 if (prevRawPrevTime > _tinyNum) { 8473 callback = "onReverseComplete"; 8474 } 8475 } 8476 this._rawPrevTime = rawPrevTime = !suppressEvents || time || prevRawPrevTime === time ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient. 8477 } 8478 } else if (time < 0.0000001) { 8479 //to work around occasional floating point math artifacts, round super small values to 0. 8480 this._totalTime = this._time = 0; 8481 this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0; 8482 if (prevTime !== 0 || duration === 0 && prevRawPrevTime > 0) { 8483 callback = "onReverseComplete"; 8484 isComplete = this._reversed; 8485 } 8486 if (time < 0) { 8487 this._active = false; 8488 if (duration === 0) if (this._initted || !this.vars.lazy || force) { 8489 //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered. 8490 if (prevRawPrevTime >= 0 && !(prevRawPrevTime === _tinyNum && this.data === "isPause")) { 8491 force = true; 8492 } 8493 this._rawPrevTime = rawPrevTime = !suppressEvents || time || prevRawPrevTime === time ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient. 8494 } 8495 } 8496 if (!this._initted || this._startAt && this._startAt.progress()) { 8497 //if we render the very beginning (time == 0) of a fromTo(), we must force the render (normal tweens wouldn't need to render at a time of 0 when the prevTime was also 0). This is also mandatory to make sure overwriting kicks in immediately. Also, we check progress() because if startAt has already rendered at its end, we should force a render at its beginning. Otherwise, if you put the playhead directly on top of where a fromTo({immediateRender:false}) starts, and then move it backwards, the from() won't revert its values. 8498 force = true; 8499 } 8500 } else { 8501 this._totalTime = this._time = time; 8502 if (this._easeType) { 8503 var r = time / duration, 8504 type = this._easeType, 8505 pow = this._easePower; 8506 if (type === 1 || type === 3 && r >= 0.5) { 8507 r = 1 - r; 8508 } 8509 if (type === 3) { 8510 r *= 2; 8511 } 8512 if (pow === 1) { 8513 r *= r; 8514 } else if (pow === 2) { 8515 r *= r * r; 8516 } else if (pow === 3) { 8517 r *= r * r * r; 8518 } else if (pow === 4) { 8519 r *= r * r * r * r; 8520 } 8521 if (type === 1) { 8522 this.ratio = 1 - r; 8523 } else if (type === 2) { 8524 this.ratio = r; 8525 } else if (time / duration < 0.5) { 8526 this.ratio = r / 2; 8527 } else { 8528 this.ratio = 1 - r / 2; 8529 } 8530 } else { 8531 this.ratio = this._ease.getRatio(time / duration); 8532 } 8533 } 8534 if (this._time === prevTime && !force) { 8535 return; 8536 } else if (!this._initted) { 8537 this._init(); 8538 if (!this._initted || this._gc) { 8539 //immediateRender tweens typically won't initialize until the playhead advances (_time is greater than 0) in order to ensure that over
8539writing occurs properly. Also, if all of the tweening properties have been overwritten (which would cause _gc to be true, as set in _init()), we shouldn't continue otherwise an onStart callback could be called for example. 8540 return; 8541 } else if (!force && this._firstPT && (this.vars.lazy !== false && this._duration || this.vars.lazy && !this._duration)) { 8542 this._time = this._totalTime = prevTime; 8543 this._rawPrevTime = prevRawPrevTime; 8544 _lazyTweens.push(this); 8545 this._lazy = [time, suppressEvents]; 8546 return; 8547 } 8548 //_ease is initially set to defaultEase, so now that init() has run, _ease is set properly and we need to recalculate the ratio. Overall this is faster than using conditional logic earlier in the method to avoid having to set ratio twice because we only init() once but renderTime() gets called VERY frequently. 8549 if (this._time && !isComplete) { 8550 this.ratio = this._ease.getRatio(this._time / duration); 8551 } else if (isComplete && this._ease._calcEnd) { 8552 this.ratio = this._ease.getRatio(this._time === 0 ? 0 : 1); 8553 } 8554 } 8555 if (this._lazy !== false) { 8556 //in case a lazy render is pending, we should flush it because the new render is occurring now (imagine a lazy tween instantiating and then immediately the user calls tween.seek(tween.duration()), skipping to the end - the end render would be forced, and then if we didn't flush the lazy render, it'd fire AFTER the seek(), rendering it at the wrong time. 8557 this._lazy = false; 8558 } 8559 if (!this._active) if (!this._paused && this._time !== prevTime && time >= 0) { 8560 this._active = true; //so that if the user renders a tween (as opposed to the timeline rendering it), the timeline is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the tween already finished but the user manually re-renders it as halfway done. 8561 } 8562 if (prevTime === 0) { 8563 if (this._startAt) { 8564 if (time >= 0) { 8565 this._startAt.render(time, true, force); 8566 } else if (!callback) { 8567 callback = "_dummyGS"; //if no callback is defined, use a dummy value just so that the condition at the end evaluates as true because _startAt should render AFTER the normal render loop when the time is negative. We could handle this in a more intuitive way, of course, but the render loop is the MOST important thing to optimize, so this technique allows us to avoid adding extra conditional logic in a high-frequency area. 8568 } 8569 } 8570 if (this.vars.onStart) if (this._time !== 0 || duration === 0) if (!suppressEvents) { 8571 this._callback("onStart"); 8572 } 8573 } 8574 pt = this._firstPT; 8575 while (pt) { 8576 if (pt.f) { 8577 pt.t[pt.p](pt.c * this.ratio + pt.s); 8578 } else { 8579 pt.t[pt.p] = pt.c * this.ratio + pt.s; 8580 } 8581 pt = pt._next; 8582 } 8583 if (this._onUpdate) { 8584 if (time < 0) if (this._startAt && time !== -0.0001) { 8585 //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values. 8586 this._startAt.render(time, true, force); //note: for performance reasons, we tuck this conditional logic inside less traveled areas (most tweens don't have an onUpdate). We'd just have it at the end before the onComplete, but the values should be updated before any onUpdate is called, so we ALSO put it here and then if it's not called, we do so later near the onComplete. 8587 } 8588 if (!suppressEvents) if (this._time !== prevTime || isComplete || force) { 8589 this._callback("onUpdate"); 8590 } 8591 } 8592 if (callback) if (!this._gc || force) { 8593 //check _gc because there's a chance that kill() could be called in an onUpdate 8594 if (time < 0 && this._startAt && !this._onUpdate && time !== -0.0001) { 8595 //-0.0001 is a special value that we use when looping back to the beginning of a repeated TimelineMax, in which case we shouldn't render the _startAt values. 8596 this._startAt.render(time, true, force); 8597 } 8598 if (isComplete) { 8599 if (this._timeline.autoRemoveChildren) { 8600 this._enabled(false, false); 8601 } 8602 this._active = false;
8603 } 8604 if (!suppressEvents && this.vars[callback]) { 8605 this._callback(callback); 8606 } 8607 if (duration === 0 && this._rawPrevTime === _tinyNum && rawPrevTime !== _tinyNum) { 8608 //the onComplete or onReverseComplete could trigger movement of the playhead and for zero-duration tweens (which must discern direction) that land directly back on their start time, we don't want to fire again on the next render. Think of several addPause()'s in a timeline that forces the playhead to a certain spot, but what if it's already paused and another tween is tweening the "time" of the timeline? Each time it moves [forward] past that spot, it would move back, and since suppressEvents is true, it'd reset _rawPrevTime to _tinyNum so that when it begins again, the callback would fire (so ultimately it could bounce back and forth during that tween). Again, this is a very uncommon scenario, but possible nonetheless. 8609 this._rawPrevTime = 0; 8610 } 8611 } 8612 }; 8613 p._kill = function (vars, target, overwritingTween) { 8614 if (vars === "all") { 8615 vars = null; 8616 } 8617 if (vars == null) if (target == null || target === this.target) { 8618 this._lazy = false; 8619 return this._enabled(false, false); 8620 } 8621 target = typeof target !== "string" ? target || this._targets || this.target : TweenLite.selector(target) || target; 8622 var simultaneousOverwrite = overwritingTween && this._time && overwritingTween._startTime === this._startTime && this._timeline === overwritingTween._timeline, 8623 i, 8624 overwrittenProps, 8625 p, 8626 pt, 8627 propLookup, 8628 changed, 8629 killProps, 8630 record, 8631 killed; 8632 if ((_isArray(target) || _isSelector(target)) && typeof target[0] !== "number") { 8633 i = target.length; 8634 while (--i > -1) { 8635 if (this._kill(vars, target[i], overwritingTween)) { 8636 changed = true; 8637 } 8638 } 8639 } else { 8640 if (this._targets) { 8641 i = this._targets.length; 8642 while (--i > -1) { 8643 if (target === this._targets[i]) { 8644 propLookup = this._propLookup[i] || {}; 8645 this._overwrittenProps = this._overwrittenProps || []; 8646 overwrittenProps = this._overwrittenProps[i] = vars ? this._overwrittenProps[i] || {} : "all"; 8647 break; 8648 } 8649 } 8650 } else if (target !== this.target) { 8651 return false; 8652 } else { 8653 propLookup = this._propLookup; 8654 overwrittenProps = this._overwrittenProps = vars ? this._overwrittenProps || {} : "all"; 8655 } 8656 if (propLookup) { 8657 killProps = vars || propLookup; 8658 record = vars !== overwrittenProps && overwrittenProps !== "all" && vars !== propLookup && (_typeof(vars) !== "object" || !vars._tempKill); //_tempKill is a super-secret way to delete a particular tweening property but NOT have it remembered as an official overwritten property (like in BezierPlugin) 8659 if (overwritingTween && (TweenLite.onOverwrite || this.vars.onOverwrite)) { 8660 for (p in killProps) { 8661 if (propLookup[p]) { 8662 if (!killed) { 8663 killed = []; 8664 } 8665 killed.push(p); 8666 } 8667 } 8668 if ((killed || !vars) && !_onOverwrite(this, overwritingTween, target, killed)) { 8669 //if the onOverwrite returned false, that means the user wants to override the overwriting (cancel it). 8670 return false; 8671 } 8672 } 8673 for (p in killProps) { 8674 if (pt = propLookup[p]) { 8675 if (simultaneousOverwrite) { 8676 //if another tween overwrites this one and they both start at exactly the same time, yet this tween has already rendered once (for example, at 0.001) because it's first in the queue, we should revert the values to where they were at 0 so that the starting values aren't contaminated on the overwriting tween. 8677 if (pt.f) { 8678 pt.t[pt.p](pt.s); 8679 } else { 8680 pt.t[pt.p] = pt.s; 8681 } 8682 changed = true; 8683 } 8684 if (pt.pg && pt.t._kill(killProps)) { 8685 changed = true; //some plugins need to be notified so they can perform cleanup tasks first 8686 } 8687 if (!pt.pg || pt.t._overwriteProps.length === 0) { 8688 if (pt._prev) { 8689 pt._prev._next = pt._next; 8690 } else if (pt === this._firstPT) { 8691 this._firstPT = pt._next; 8692 } 8693 if (pt._next) { 8694 pt._next._prev = pt._prev; 8695 } 8696 pt._next = pt._prev = null; 8697 } 8698 delete propLookup[p]; 8699 } 8700 if (record) { 8701 overwrittenProps[p] = 1; 8702 } 8703 } 8704 if (!this._firstPT && this._initted) { 8705 //if all tweening properties are killed, kill the tween. Without this line, if there's a tween with multiple targets and then you killTweensOf() each target individually, the tween would technically still remain active and fire its onComplete even though there aren't any more properties tweening. 8706 this._enabled(false, false); 8707 } 8708 } 8709 } 8710 return changed; 8711 }; 8712 p.invalidate = function () { 8713 if (this._notifyPluginsOfEnabled) { 8714 TweenLite._onPluginEvent("_onDisable", this); 8715 } 8716 this._firstPT = this._overwrittenProps = this._startAt = this._onUpdate = null; 8717 this._notifyPluginsOfEnabled = this._active = this._lazy = false;
8718 this._propLookup = this._targets ? {} : []; 8719 Animation.prototype.invalidate.call(this); 8720 if (this.vars.immediateRender) { 8721 this._time = -_tinyNum; //forces a render without having to set the render() "force" parameter to true because we want to allow lazying by default (using the "force" parameter always forces an immediate full render) 8722 this.render(Math.min(0, -this._delay)); //in case delay is negative. 8723 } 8724 return this; 8725 }; 8726 p._enabled = function (enabled, ignoreTimeline) { 8727 if (!_tickerActive) { 8728 _ticker.wake(); 8729 } 8730 if (enabled && this._gc) { 8731 var targets = this._targets, 8732 i; 8733 if (targets) { 8734 i = targets.length; 8735 while (--i > -1) { 8736 this._siblings[i] = _register(targets[i], this, true); 8737 } 8738 } else { 8739 this._siblings = _register(this.target, this, true); 8740 } 8741 } 8742 Animation.prototype._enabled.call(this, enabled, ignoreTimeline); 8743 if (this._notifyPluginsOfEnabled) if (this._firstPT) { 8744 return TweenLite._onPluginEvent(enabled ? "_onEnable" : "_onDisable", this); 8745 } 8746 return false; 8747 }; 8748 8749 //----TweenLite static methods ----------------------------------------------------- 8750 8751 TweenLite.to = function (target, duration, vars) { 8752 return new TweenLite(target, duration, vars); 8753 }; 8754 TweenLite.from = function (target, duration, vars) { 8755 vars.runBackwards = true; 8756 vars.immediateRender = vars.immediateRender != false; 8757 return new TweenLite(target, duration, vars); 8758 }; 8759 TweenLite.fromTo = function (target, duration, fromVars, toVars) { 8760 toVars.startAt = fromVars; 8761 toVars.immediateRender = toVars.immediateRender != false && fromVars.immediateRender != false; 8762 return new TweenLite(target, duration, toVars); 8763 }; 8764 TweenLite.delayedCall = function (delay, callback, params, scope, useFrames) { 8765 return new TweenLite(callback, 0, { 8766 delay: delay, 8767 onComplete: callback, 8768 onCompleteParams: params, 8769 callbackScope: scope, 8770 onReverseComplete: callback, 8771 onReverseCompleteParams: params, 8772 immediateRender: false, 8773 lazy: false, 8774 useFrames: useFrames, 8775 overwrite: 0 8776 }); 8777 }; 8778 TweenLite.set = function (target, vars) { 8779 return new TweenLite(target, 0, vars); 8780 }; 8781 TweenLite.getTweensOf = function (target, onlyActive) { 8782 if (target == null) { 8783 return []; 8784 } 8785 target = typeof target !== "string" ? target : TweenLite.selector(target) || target; 8786 var i, a, j, t; 8787 if ((_isArray(target) || _isSelector(target)) && typeof target[0] !== "number") { 8788 i = target.length; 8789 a = []; 8790 while (--i > -1) { 8791 a = a.concat(TweenLite.getTweensOf(target[i], onlyActive)); 8792 } 8793 i = a.length; 8794 //now get rid of any duplicates (tweens of arrays of objects could cause duplicates) 8795 while (--i > -1) { 8796 t = a[i]; 8797 j = i; 8798 while (--j > -1) { 8799 if (t === a[j]) { 8800 a.splice(i, 1); 8801 } 8802 } 8803 } 8804 } else if (target._gsTweenID) { 8805 a = _register(target).concat(); 8806 i = a.length; 8807 while (--i > -1) { 8808 if (a[i]._gc || onlyActive && !a[i].isActive()) { 8809 a.splice(i, 1); 8810 } 8811 } 8812 } 8813 return a || []; 8814 }; 8815 TweenLite.killTweensOf = TweenLite.killDelayedCallsTo = function (target, onlyActive, vars) { 8816 if (_typeof(onlyActive) === "object") { 8817 vars = onlyActive; //for backwards compatibility (before "onlyActive" parameter was inserted) 8818 onlyActive = false; 8819 } 8820 var a = TweenLite.getTweensOf(target, onlyActive), 8821 i = a.length; 8822 while (--i > -1) { 8823 a[i]._kill(vars, target); 8824 } 8825 }; 8826 8827 /* 8828 * ---------------------------------------------------------------- 8829 * TweenPlugin (could easily be split out as a separate file/class, but included for ease of use (so that people don't need to include another script call before loading plugins which is easy to forget) 8830 * ---------------------------------------------------------------- 8831 */ 8832 var TweenPlugin = _class("plugins.TweenPlugin", function (props, priority) { 8833 this._overwriteProps = (props || "").split(","); 8834 this._propName = this._overwriteProps[0]; 8835 this._priority = priority || 0; 8836 this._super = TweenPlugin.prototype; 8837 }, true); 8838 p = TweenPlugin.prototype; 8839 TweenPlugin.version = "1.19.0"; 8840 TweenPlugin.API = 2; 8841 p._firstPT = null; 8842 p._addTween = _addPropTween; 8843 p.setRatio = _setRatio; 8844 p._kill = function (lookup) { 8845 var a = this._overwriteProps, 8846 pt = this._firstPT, 8847 i; 8848 if (lookup[this._propName] != null) { 8849 this._overwriteProps = []; 8850 } else { 8851 i = a.length; 8852 while (--i > -1) { 8853 if (lookup[a[i]] != null) { 8854 a.splice(i, 1); 8855 } 8856 } 8857 } 8858 while (pt) { 8859 if (lookup[pt.n] != null) { 8860 if (pt._next) { 8861 pt._next._prev = pt._prev; 8862 } 8863 if (pt._prev) { 8864 pt._prev._next = pt._next; 8865 pt._prev = null; 8866 } else if (this._firstPT === pt) { 8867 this._firstPT = pt._next; 8868 } 8869 } 8870 pt = pt._next; 8871 } 8872 return false;
8873 }; 8874 p._mod = p._roundProps = function (lookup) { 8875 var pt = this._firstPT, 8876 val; 8877 while (pt) { 8878 val = lookup[this._propName] || pt.n != null && lookup[pt.n.split(this._propName + "_").join("")]; 8879 if (val && typeof val === "function") { 8880 //some properties that are very plugin-specific add a prefix named after the _propName plus an underscore, so we need to ignore that extra stuff here. 8881 if (pt.f === 2) { 8882 pt.t._applyPT.m = val; 8883 } else { 8884 pt.m = val; 8885 } 8886 } 8887 pt = pt._next; 8888 } 8889 }; 8890 TweenLite._onPluginEvent = function (type, tween) { 8891 var pt = tween._firstPT, 8892 changed, 8893 pt2, 8894 first, 8895 last, 8896 next; 8897 if (type === "_onInitAllProps") { 8898 //sorts the PropTween linked list in order of priority because some plugins need to render earlier/later than others, like MotionBlurPlugin applies its effects after all x/y/alpha tweens have rendered on each frame. 8899 while (pt) { 8900 next = pt._next; 8901 pt2 = first; 8902 while (pt2 && pt2.pr > pt.pr) { 8903 pt2 = pt2._next; 8904 } 8905 if (pt._prev = pt2 ? pt2._prev : last) { 8906 pt._prev._next = pt; 8907 } else { 8908 first = pt; 8909 } 8910 if (pt._next = pt2) { 8911 pt2._prev = pt; 8912 } else { 8913 last = pt; 8914 } 8915 pt = next; 8916 } 8917 pt = tween._firstPT = first; 8918 } 8919 while (pt) { 8920 if (pt.pg) if (typeof pt.t[type] === "function") if (pt.t[type]()) { 8921 changed = true; 8922 } 8923 pt = pt._next; 8924 } 8925 return changed; 8926 }; 8927 TweenPlugin.activate = function (plugins) { 8928 var i = plugins.length; 8929 while (--i > -1) { 8930 if (plugins[i].API === TweenPlugin.API) { 8931 _plugins[new plugins[i]()._propName] = plugins[i]; 8932 } 8933 } 8934 return true; 8935 }; 8936 8937 //provides a more concise way to define plugins that have no dependencies besides TweenPlugin and TweenLite, wrapping common boilerplate stuff into one function (added in 1.9.0). You don't NEED to use this to define a plugin - the old way still works and can be useful in certain (rare) situations. 8938 _gsDefine.plugin = function (config) { 8939 if (!config || !config.propName || !config.init || !config.API) { 8940 throw "illegal plugin definition."; 8941 } 8942 var propName = config.propName, 8943 priority = config.priority || 0, 8944 overwriteProps = config.overwriteProps, 8945 map = { 8946 init: "_onInitTween", 8947 set: "setRatio", 8948 kill: "_kill", 8949 round: "_mod", 8950 mod: "_mod", 8951 initAll: "_onInitAllProps" 8952 }, 8953 Plugin = _class("plugins." + propName.charAt(0).toUpperCase() + propName.substr(1) + "Plugin", function () { 8954 TweenPlugin.call(this, propName, priority); 8955 this._overwriteProps = overwriteProps || []; 8956 }, config.global === true), 8957 p = Plugin.prototype = new TweenPlugin(propName), 8958 prop; 8959 p.constructor = Plugin; 8960 Plugin.API = config.API; 8961 for (prop in map) { 8962 if (typeof config[prop] === "function") { 8963 p[map[prop]] = config[prop]; 8964 } 8965 } 8966 Plugin.version = config.version; 8967 TweenPlugin.activate([Plugin]); 8968 return Plugin; 8969 }; 8970 8971 //now run through all the dependencies discovered and if any are missing, log that to the console as a warning. This is why it's best to have TweenLite load last - it can check all the dependencies for you. 8972 a = window._gsQueue; 8973 if (a) { 8974 for (i = 0; i < a.length; i++) { 8975 a[i](); 8976 } 8977 for (p in _defLookup) { 8978 if (!_defLookup[p].func) { 8979 window.console.log("GSAP encountered missing dependency: " + p); 8980 } 8981 } 8982 } 8983 _tickerActive = false; //ensures that the first official animation forces a ticker.tick() to update the time when it is instantiated 8984})(typeof module !== "undefined" && module.exports && typeof global !== "undefined" ? global : void 0 || window, "TweenLite"); 8985 8986}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 8987},{}],5:[function(require,module,exports){ 8988(function (global){(function (){ 8989"use strict"; 8990 8991function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 8992/*! 8993 * VERSION: 1.20.4 8994 * DATE: 2018-02-15 8995 * UPDATES AND DOCS AT: http://greensock.com 8996 * 8997 * Includes all of the following: TweenLite, TweenMax, TimelineLite, TimelineMax, EasePack, CSSPlugin, RoundPropsPlugin, BezierPlugin, AttrPlugin, DirectionalRotationPlugin 8998 * 8999 * @license Copyright (c) 2008-2018, GreenSock. All rights reserved. 9000 * This work is subject to the terms at http://greensock.com/standard-license or for
9001 * Club GreenSock members, the software agreement that was issued with your membership. 9002 * 9003 * @author: Jack Doyle, [email protected] 9004 **/ 9005var _gsScope = typeof module !== "undefined" && module.exports && typeof global !== "undefined" ? global : void 0 || window; //helps ensure compatibility with AMD/RequireJS and CommonJS/Node 9006(_gsScope._gsQueue || (_gsScope._gsQueue = [])).push(function () { 9007 "use strict"; 9008 9009 _gsScope._gsDefine("TweenMax", ["core.Animation", "core.SimpleTimeline", "TweenLite"], function (Animation, SimpleTimeline, TweenLite) { 9010 var _slice = function _slice(a) { 9011 //don't use [].slice because that doesn't work in IE8 with a NodeList that's returned by querySelectorAll() 9012 var b = [], 9013 l = a.length, 9014 i; 9015 for (i = 0; i !== l; b.push(a[i++])); 9016 return b; 9017 }, 9018 _applyCycle = function _applyCycle(vars, targets, i) { 9019 var alt = vars.cycle, 9020 p, 9021 val; 9022 for (p in alt) { 9023 val = alt[p]; 9024 vars[p] = typeof val === "function" ? val(i, targets[i]) : val[i % val.length]; 9025 } 9026 delete vars.cycle; 9027 }, 9028 _TweenMax = function TweenMax(target, duration, vars) { 9029 TweenLite.call(this, target, duration, vars); 9030 this._cycle = 0; 9031 this._yoyo = this.vars.yoyo === true || !!this.vars.yoyoEase; 9032 this._repeat = this.vars.repeat || 0; 9033 this._repeatDelay = this.vars.repeatDelay || 0; 9034 if (this._repeat) { 9035 this._uncache(true); //ensures that if there is any repeat, the totalDuration will get recalculated to accurately report it. 9036 } 9037 this.render = _TweenMax.prototype.render; //speed optimization (avoid prototype lookup on this "hot" method) 9038 }, 9039 _tinyNum = 0.0000000001, 9040 TweenLiteInternals = TweenLite._internals, 9041 _isSelector = TweenLiteInternals.isSelector, 9042 _isArray = TweenLiteInternals.isArray, 9043 p = _TweenMax.prototype = TweenLite.to({}, 0.1, {}), 9044 _blankArray = []; 9045 _TweenMax.version = "1.20.4"; 9046 p.constructor = _TweenMax; 9047 p.kill()._gc = false; 9048 _TweenMax.killTweensOf = _TweenMax.killDelayedCallsTo = TweenLite.killTweensOf; 9049 _TweenMax.getTweensOf = TweenLite.getTweensOf; 9050 _TweenMax.lagSmoothing = TweenLite.lagSmoothing; 9051 _TweenMax.ticker = TweenLite.ticker; 9052 _TweenMax.render = TweenLite.render; 9053 p.invalidate = function () { 9054 this._yoyo = this.vars.yoyo === true || !!this.vars.yoyoEase; 9055 this._repeat = this.vars.repeat || 0; 9056 this._repeatDelay = this.vars.repeatDelay || 0; 9057 this._yoyoEase = null; 9058 this._uncache(true); 9059 return TweenLite.prototype.invalidate.call(this); 9060 }; 9061 p.updateTo = function (vars, resetDuration) { 9062 var curRatio = this.ratio, 9063 immediate = this.vars.immediateRender || vars.immediateRender, 9064 p; 9065 if (resetDuration && this._startTime < this._timeline._time) { 9066 this._startTime = this._timeline._time; 9067 this._uncache(false); 9068 if (this._gc) { 9069 this._enabled(true, false); 9070 } else { 9071 this._timeline.insert(this, this._startTime - this._delay); //ensures that any necessary re-sequencing of Animations in the timeline occurs to make sure the rendering order is correct. 9072 } 9073 } 9074 for (p in vars) { 9075 this.vars[p] = vars[p]; 9076 } 9077 if (this._initted || immediate) { 9078 if (resetDuration) { 9079 this._initted = false; 9080 if (immediate) { 9081 this.render(0, true, true); 9082 } 9083 } else { 9084 if (this._gc) { 9085 this._enabled(true, false); 9086 } 9087 if (this._notifyPluginsOfEnabled && this._firstPT) { 9088 TweenLite._onPluginEvent("_onDisable", this); //in case a plugin like MotionBlur must perform some cleanup tasks 9089 } 9090 if (this._time / this._duration > 0.998) { 9091 //if the tween has finished (or come extremely close to finishing), we just need to rewind it to 0 and then render it again at the end which forces it to re-initialize (parsing the new vars). We allow tweens that are close to finishing (but haven't quite finished) to work this way too because otherwise, the values are so small when determining where to project the starting values that binary math issues creep in and can make the tween appear to render incorrectly when run backwards. 9092 var prevTime = this._totalTime; 9093 this.render(0, true, false); 9094 this._initted = false;
9095 this.render(prevTime, true, false); 9096 } else { 9097 this._initted = false; 9098 this._init(); 9099 if (this._time > 0 || immediate) { 9100 var inv = 1 / (1 - curRatio), 9101 pt = this._firstPT, 9102 endValue; 9103 while (pt) { 9104 endValue = pt.s + pt.c; 9105 pt.c *= inv; 9106 pt.s = endValue - pt.c; 9107 pt = pt._next; 9108 } 9109 } 9110 } 9111 } 9112 } 9113 return this; 9114 }; 9115 p.render = function (time, suppressEvents, force) { 9116 if (!this._initted) if (this._duration === 0 && this.vars.repeat) { 9117 //zero duration tweens that render immediately have render() called from TweenLite's constructor, before TweenMax's constructor has finished setting _repeat, _repeatDelay, and _yoyo which are critical in determining totalDuration() so we need to call invalidate() which is a low-kb way to get those set properly. 9118 this.invalidate(); 9119 } 9120 var totalDur = !this._dirty ? this._totalDuration : this.totalDuration(), 9121 prevTime = this._time, 9122 prevTotalTime = this._totalTime, 9123 prevCycle = this._cycle, 9124 duration = this._duration, 9125 prevRawPrevTime = this._rawPrevTime, 9126 isComplete, 9127 callback, 9128 pt, 9129 cycleDuration, 9130 r, 9131 type, 9132 pow, 9133 rawPrevTime, 9134 yoyoEase; 9135 if (time >= totalDur - 0.0000001 && time >= 0) { 9136 //to work around occasional floating point math artifacts. 9137 this._totalTime = totalDur; 9138 this._cycle = this._repeat; 9139 if (this._yoyo && (this._cycle & 1) !== 0) { 9140 this._time = 0; 9141 this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0; 9142 } else { 9143 this._time = duration; 9144 this.ratio = this._ease._calcEnd ? this._ease.getRatio(1) : 1; 9145 } 9146 if (!this._reversed) { 9147 isComplete = true; 9148 callback = "onComplete"; 9149 force = force || this._timeline.autoRemoveChildren; //otherwise, if the animation is unpaused/activated after it's already finished, it doesn't get removed from the parent timeline. 9150 } 9151 if (duration === 0) if (this._initted || !this.vars.lazy || force) { 9152 //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered. 9153 if (this._startTime === this._timeline._duration) { 9154 //if a zero-duration tween is at the VERY end of a timeline and that timeline renders at its end, it will typically add a tiny bit of cushion to the render time to prevent rounding errors from getting in the way of tweens rendering their VERY end. If we then reverse() that timeline, the zero-duration tween will trigger its onReverseComplete even though technically the playhead didn't pass over it again. It's a very specific edge case we must accommodate. 9155 time = 0; 9156 } 9157 if (prevRawPrevTime < 0 || time <= 0 && time >= -0.0000001 || prevRawPrevTime === _tinyNum && this.data !== "isPause") if (prevRawPrevTime !== time) { 9158 //note: when this.data is "isPause", it's a callback added by addPause() on a timeline that we should not be triggered when LEAVING its exact start time. In other words, tl.addPause(1).play(1) shouldn't pause. 9159 force = true; 9160 if (prevRawPrevTime > _tinyNum) { 9161 callback = "onReverseComplete"; 9162 } 9163 } 9164 this._rawPrevTime = rawPrevTime = !suppressEvents || time || prevRawPrevTime === time ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient. 9165 } 9166 } else if (time < 0.0000001) { 9167 //to work around occasional floating point math artifacts, round super small values to 0. 9168 this._totalTime = this._time = this._cycle = 0; 9169 this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0; 9170 if (prevTotalTime !== 0 || duration === 0 && prevRawPrevTime > 0) { 9171 callback = "onReverseComplete"; 9172 isComplete = this._reversed; 9173 } 9174 if (time < 0) { 9175 this._active = false;
9176 if (duration === 0) if (this._initted || !this.vars.lazy || force) { 9177 //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered. 9178 if (prevRawPrevTime >= 0) { 9179 force = true; 9180 } 9181 this._rawPrevTime = rawPrevTime = !suppressEvents || time || prevRawPrevTime === time ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient. 9182 } 9183 } 9184 if (!this._initted) { 9185 //if we render the very beginning (time == 0) of a fromTo(), we must force the render (normal tweens wouldn't need to render at a time of 0 when the prevTime was also 0). This is also mandatory to make sure overwriting kicks in immediately. 9186 force = true; 9187 } 9188 } else { 9189 this._totalTime = this._time = time; 9190 if (this._repeat !== 0) { 9191 cycleDuration = duration + this._repeatDelay; 9192 this._cycle = this._totalTime / cycleDuration >> 0; //originally _totalTime % cycleDuration but floating point errors caused problems, so I normalized it. (4 % 0.8 should be 0 but some browsers report it as 0.79999999!) 9193 if (this._cycle !== 0) if (this._cycle === this._totalTime / cycleDuration && prevTotalTime <= time) { 9194 this._cycle--; //otherwise when rendered exactly at the end time, it will act as though it is repeating (at the beginning) 9195 } 9196 this._time = this._totalTime - this._cycle * cycleDuration; 9197 if (this._yoyo) if ((this._cycle & 1) !== 0) { 9198 this._time = duration - this._time; 9199 yoyoEase = this._yoyoEase || this.vars.yoyoEase; //note: we don't set this._yoyoEase in _init() like we do other properties because it's TweenMax-specific and doing it here allows us to optimize performance (most tweens don't have a yoyoEase). Note that we also must skip the this.ratio calculation further down right after we _init() in this function, because we're doing it here. 9200 if (yoyoEase) { 9201 if (!this._yoyoEase) { 9202 if (yoyoEase === true && !this._initted) { 9203 //if it's not initted and yoyoEase is true, this._ease won't have been populated yet so we must discern it here. 9204 yoyoEase = this.vars.ease; 9205 this._yoyoEase = yoyoEase = !yoyoEase ? TweenLite.defaultEase : yoyoEase instanceof Ease ? yoyoEase : typeof yoyoEase === "function" ? new Ease(yoyoEase, this.vars.easeParams) : Ease.map[yoyoEase] || TweenLite.defaultEase; 9206 } else { 9207 this._yoyoEase = yoyoEase = yoyoEase === true ? this._ease : yoyoEase instanceof Ease ? yoyoEase : Ease.map[yoyoEase]; 9208 } 9209 } 9210 this.ratio = yoyoEase ? 1 - yoyoEase.getRatio((duration - this._time) / duration) : 0; 9211 } 9212 } 9213 if (this._time > duration) { 9214 this._time = duration; 9215 } else if (this._time < 0) { 9216 this._time = 0; 9217 } 9218 } 9219 if (this._easeType && !yoyoEase) { 9220 r = this._time / duration; 9221 type = this._easeType; 9222 pow = this._easePower; 9223 if (type === 1 || type === 3 && r >= 0.5) { 9224 r = 1 - r; 9225 } 9226 if (type === 3) { 9227 r *= 2; 9228 } 9229 if (pow === 1) { 9230 r *= r; 9231 } else if (pow === 2) { 9232 r *= r * r; 9233 } else if (pow === 3) { 9234 r *= r * r * r; 9235 } else if (pow === 4) { 9236 r *= r * r * r * r; 9237 } 9238 if (type === 1) { 9239 this.ratio = 1 - r; 9240 } else if (type === 2) { 9241 this.ratio = r; 9242 } else if (this._time / duration < 0.5) { 9243 this.ratio = r / 2; 9244 } else { 9245 this.ratio = 1 - r / 2; 9246 } 9247 } else if (!yoyoEase) { 9248 this.ratio = this._ease.getRatio(this._time / duration); 9249 } 9250 } 9251 if (prevTime === this._time && !force && prevCycle === this._cycle) { 9252 if (prevTotalTime !== this._totalTime) if (this._onUpdate) if (!suppressEvents) {
9253 //so that onUpdate fires even during the repeatDelay - as long as the totalTime changed, we should trigger onUpdate. 9254 this._callback("onUpdate"); 9255 } 9256 return; 9257 } else if (!this._initted) { 9258 this._init(); 9259 if (!this._initted || this._gc) { 9260 //immediateRender tweens typically won't initialize until the playhead advances (_time is greater than 0) in order to ensure that overwriting occurs properly. Also, if all of the tweening properties have been overwritten (which would cause _gc to be true, as set in _init()), we shouldn't continue otherwise an onStart callback could be called for example. 9261 return; 9262 } else if (!force && this._firstPT && (this.vars.lazy !== false && this._duration || this.vars.lazy && !this._duration)) { 9263 //we stick it in the queue for rendering at the very end of the tick - this is a performance optimization because browsers invalidate styles and force a recalculation if you read, write, and then read style data (so it's better to read/read/read/write/write/write than read/write/read/write/read/write). The down side, of course, is that usually you WANT things to render immediately because you may have code running right after that which depends on the change. Like imagine running TweenLite.set(...) and then immediately after that, creating a nother tween that animates the same property to another value; the starting values of that 2nd tween wouldn't be accurate if lazy is true. 9264 this._time = prevTime; 9265 this._totalTime = prevTotalTime; 9266 this._rawPrevTime = prevRawPrevTime; 9267 this._cycle = prevCycle; 9268 TweenLiteInternals.lazyTweens.push(this); 9269 this._lazy = [time, suppressEvents]; 9270 return; 9271 } 9272 //_ease is initially set to defaultEase, so now that init() has run, _ease is set properly and we need to recalculate the ratio. Overall this is faster than using conditional logic earlier in the method to avoid having to set ratio twice because we only init() once but renderTime() gets called VERY frequently. 9273 if (this._time && !isComplete && !yoyoEase) { 9274 this.ratio = this._ease.getRatio(this._time / duration); 9275 } else if (isComplete && this._ease._calcEnd && !yoyoEase) { 9276 this.ratio = this._ease.getRatio(this._time === 0 ? 0 : 1); 9277 } 9278 } 9279 if (this._lazy !== false) { 9280 this._lazy = false; 9281 } 9282 if (!this._active) if (!this._paused && this._time !== prevTime && time >= 0) { 9283 this._active = true; //so that if the user renders a tween (as opposed to the timeline rendering it), the timeline is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the tween already finished but the user manually re-renders it as halfway done. 9284 } 9285 if (prevTotalTime === 0) { 9286 if (this._initted === 2 && time > 0) { 9287 //this.invalidate(); 9288 this._init(); //will just apply overwriting since _initted of (2) means it was a from() tween that had immediateRender:true 9289 } 9290 if (this._startAt) { 9291 if (time >= 0) { 9292 this._startAt.render(time, true, force); 9293 } else if (!callback) { 9294 callback = "_dummyGS"; //if no callback is defined, use a dummy value just so that the condition at the end evaluates as true because _startAt should render AFTER the normal render loop when the time is negative. We could handle this in a more intuitive way, of course, but the render loop is the MOST important thing to optimize, so this technique allows us to avoid adding extra conditional logic in a high-frequency area. 9295 } 9296 } 9297 if (this.vars.onStart) if (this._totalTime !== 0 || duration === 0) if (!suppressEvents) { 9298 this._callback("onStart"); 9299 } 9300 } 9301 pt = this._firstPT; 9302 while (pt) { 9303 if (pt.f) { 9304 pt.t[pt.p](pt.c * this.ratio + pt.s); 9305 } else { 9306 pt.t[pt.p] = pt.c * this.ratio + pt.s; 9307 } 9308 pt = pt._next; 9309 } 9310 if (this._onUpdate) { 9311 if (time < 0) if (this._startAt && this._startTime) { 9312 //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values. 9313 this._startAt.render(time, true, force); //note: for performance reasons, we tuck this conditional logic inside less traveled areas (most tweens don't have an onUpdate). We'd just have it at the end before the onComplete, but the values should be updated before any onUpdate is called, so we ALSO put it here and then if it's not called, we do so later near the onComplete. 9314 } 9315 if (!suppressEvents) if (this._totalTime !== prevTotalTime || callback) {
9316 this._callback("onUpdate"); 9317 } 9318 } 9319 if (this._cycle !== prevCycle) if (!suppressEvents) if (!this._gc) if (this.vars.onRepeat) { 9320 this._callback("onRepeat"); 9321 } 9322 if (callback) if (!this._gc || force) { 9323 //check gc because there's a chance that kill() could be called in an onUpdate 9324 if (time < 0 && this._startAt && !this._onUpdate && this._startTime) { 9325 //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values. 9326 this._startAt.render(time, true, force); 9327 } 9328 if (isComplete) { 9329 if (this._timeline.autoRemoveChildren) { 9330 this._enabled(false, false); 9331 } 9332 this._active = false; 9333 } 9334 if (!suppressEvents && this.vars[callback]) { 9335 this._callback(callback); 9336 } 9337 if (duration === 0 && this._rawPrevTime === _tinyNum && rawPrevTime !== _tinyNum) { 9338 //the onComplete or onReverseComplete could trigger movement of the playhead and for zero-duration tweens (which must discern direction) that land directly back on their start time, we don't want to fire again on the next render. Think of several addPause()'s in a timeline that forces the playhead to a certain spot, but what if it's already paused and another tween is tweening the "time" of the timeline? Each time it moves [forward] past that spot, it would move back, and since suppressEvents is true, it'd reset _rawPrevTime to _tinyNum so that when it begins again, the callback would fire (so ultimately it could bounce back and forth during that tween). Again, this is a very uncommon sce
9338nario, but possible nonetheless. 9339 this._rawPrevTime = 0; 9340 } 9341 } 9342 }; 9343 9344 //---- STATIC FUNCTIONS ----------------------------------------------------------------------------------------------------------- 9345 9346 _TweenMax.to = function (target, duration, vars) { 9347 return new _TweenMax(target, duration, vars); 9348 }; 9349 _TweenMax.from = function (target, duration, vars) { 9350 vars.runBackwards = true; 9351 vars.immediateRender = vars.immediateRender != false; 9352 return new _TweenMax(target, duration, vars); 9353 }; 9354 _TweenMax.fromTo = function (target, duration, fromVars, toVars) { 9355 toVars.startAt = fromVars; 9356 toVars.immediateRender = toVars.immediateRender != false && fromVars.immediateRender != false; 9357 return new _TweenMax(target, duration, toVars); 9358 }; 9359 _TweenMax.staggerTo = _TweenMax.allTo = function (targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) { 9360 stagger = stagger || 0; 9361 var delay = 0, 9362 a = [], 9363 finalComplete = function finalComplete() { 9364 if (vars.onComplete) { 9365 vars.onComplete.apply(vars.onCompleteScope || this, arguments); 9366 } 9367 onCompleteAll.apply(onCompleteAllScope || vars.callbackScope || this, onCompleteAllParams || _blankArray); 9368 }, 9369 cycle = vars.cycle, 9370 fromCycle = vars.startAt && vars.startAt.cycle, 9371 l, 9372 copy, 9373 i, 9374 p; 9375 if (!_isArray(targets)) { 9376 if (typeof targets === "string") { 9377 targets = TweenLite.selector(targets) || targets; 9378 } 9379 if (_isSelector(targets)) { 9380 targets = _slice(targets); 9381 } 9382 } 9383 targets = targets || []; 9384 if (stagger < 0) { 9385 targets = _slice(targets); 9386 targets.reverse(); 9387 stagger *= -1; 9388 } 9389 l = targets.length - 1; 9390 for (i = 0; i <= l; i++) { 9391 copy = {}; 9392 for (p in vars) { 9393 copy[p] = vars[p]; 9394 } 9395 if (cycle) { 9396 _applyCycle(copy, targets, i); 9397 if (copy.duration != null) { 9398 duration = copy.duration; 9399 delete copy.duration; 9400 } 9401 } 9402 if (fromCycle) { 9403 fromCycle = copy.startAt = {}; 9404 for (p in vars.startAt) { 9405 fromCycle[p] = vars.startAt[p]; 9406 } 9407 _applyCycle(copy.startAt, targets, i); 9408 } 9409 copy.delay = delay + (copy.delay || 0); 9410 if (i === l && onCompleteAll) { 9411 copy.onComplete = finalComplete; 9412 } 9413 a[i] = new _TweenMax(targets[i], duration, copy); 9414 delay += stagger; 9415 } 9416 return a; 9417 }; 9418 _TweenMax.staggerFrom = _TweenMax.allFrom = function (targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) { 9419 vars.runBackwards = true; 9420 vars.immediateRender = vars.immediateRender != false; 9421 return _TweenMax.staggerTo(targets, duration, vars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope); 9422 }; 9423 _TweenMax.staggerFromTo = _TweenMax.allFromTo = function (targets, duration, fromVars, toVars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope) { 9424 toVars.startAt = fromVars; 9425 toVars.immediateRender = toVars.immediateRender != false && fromVars.immediateRender != false; 9426 return _TweenMax.staggerTo(targets, duration, toVars, stagger, onCompleteAll, onCompleteAllParams, onCompleteAllScope); 9427 }; 9428 _TweenMax.delayedCall = function (delay, callback, params, scope, useFrames) { 9429 return new _TweenMax(callback, 0, { 9430 delay: delay, 9431 onComplete: callback, 9432 onCompleteParams: params, 9433 callbackScope: scope, 9434 onReverseComplete: callback, 9435 onReverseCompleteParams: params, 9436 immediateRender: false, 9437 useFrames: useFrames, 9438 overwrite: 0 9439 }); 9440 }; 9441 _TweenMax.set = function (target, vars) { 9442 return new _TweenMax(target, 0, vars); 9443 }; 9444 _TweenMax.isTweening = function (target) { 9445 return TweenLite.getTweensOf(target, true).length > 0; 9446 }; 9447 var _getChildrenOf2 = function _getChildrenOf(timeline, includeTimelines) { 9448 var a = [], 9449 cnt = 0, 9450 tween = timeline._first; 9451 while (tween) { 9452 if (tween instanceof TweenLite) { 9453 a[cnt++] = tween; 9454 } else { 9455 if (includeTimelines) { 9456 a[cnt++] = tween; 9457 } 9458 a = a.concat(_getChildrenOf2(tween, includeTimelines)); 9459 cnt = a.length; 9460 } 9461 tween = tween._next; 9462 } 9463 return a; 9464 }, 9465 getAllTweens = _TweenMax.getAllTweens = function (includeTimelines) { 9466 return _getChildrenOf2(Animation._rootTimeline, includeTimelines).concat(_getChildrenOf2(Animation._rootFramesTimeline, includeTimelines)); 9467 }; 9468 _TweenMax.killAll = function (complete, tweens, delayedCalls, timelines) { 9469 if (tweens == null) { 9470 tweens = true; 9471 } 9472 if (delayedCalls == null) { 9473 delayedCalls = true; 9474 } 9475 var a = getAllTweens(timelines != false), 9476 l = a.length, 9477 allTrue = tweens && delayedCalls && timelines, 9478 isDC, 9479 tween, 9480 i; 9481 for (i = 0; i < l; i++) { 9482 tween = a[i]; 9483 if (allTrue || tween instanceof SimpleTimeline || (isDC = tween.target === tween.vars.onComplete) && delayedCalls || tweens && !isDC) { 9484 if (complete) { 9485 tween.totalTime(tween._reversed ? 0 : tween.totalDuration()); 9486 } else { 9487 tween._enabled(false, false); 9488 } 9489 } 9490 } 9491 }; 9492 _TweenMax.killChildTweensOf = function (parent, complete) { 9493 if (parent == null) { 9494 return; 9495 } 9496 var tl = TweenLiteInternals.tweenLookup, 9497 a, 9498 curParent, 9499 p, 9500 i, 9501 l; 9502 if (typeof parent === "string") { 9503 parent = TweenLite.selector(parent) || parent; 9504 } 9505 if (_isSelector(parent)) { 9506 parent = _slice(parent); 9507 } 9508 if (_isArray(parent)) { 9509 i = parent.length; 9510 while (--i > -1) { 9511 _TweenMax.killChildTweensOf(parent[i], complete); 9512 } 9513 return; 9514 } 9515 a = []; 9516 for (p in tl) { 9517 curParent = tl[p].target.parentNode; 9518 while (curParent) { 9519 if (curParent === parent) { 9520 a = a.concat(tl[p].tweens); 9521 } 9522 curParent = curParent.parentNode; 9523 } 9524 } 9525 l = a.length; 9526 for (i = 0; i < l; i++) { 9527 if (complete) { 9528 a[i].totalTime(a[i].totalDuration()); 9529 } 9530 a[i]._enabled(false, false); 9531 } 9532 }; 9533 var _changePause = function _changePause(pause, tweens, delayedCalls, timelines) { 9534 tweens = tweens !== false; 9535 delayedCalls = delayedCalls !== false; 9536 timelines = timelines !== false; 9537 var a = getAllTweens(timelines), 9538 allTrue = tweens && delayedCalls && timelines, 9539 i = a.length, 9540 isDC, 9541 tween; 9542 while (--i > -1) { 9543 tween = a[i]; 9544 if (allTrue || tween instanceof SimpleTimeline || (isDC = tween.target === tween.vars.onComplete) && delayedCalls || tweens && !isDC) { 9545 tween.paused(pause); 9546 } 9547 } 9548 }; 9549 _TweenMax.pauseAll = function (tweens, delayedCalls, timelines) { 9550 _changePause(true, tweens, delayedCalls, timelines); 9551 }; 9552 _TweenMax.resumeAll = function (tweens, delayedCalls, timelines) { 9553 _changePause(false, tweens, delayedCalls, timelines); 9554 }; 9555 _TweenMax.globalTimeScale = function (value) { 9556 var tl = Animation._rootTimeline, 9557 t = TweenLite.ticker.time; 9558 if (!arguments.length) { 9559 return tl._timeScale; 9560 } 9561 value = value || _tinyNum; //can't allow zero because it'll throw the math off 9562 tl._startTime = t - (t - tl._startTime) * tl._timeScale / value; 9563 tl = Animation._rootFramesTimeline; 9564 t = TweenLite.ticker.frame; 9565 tl._startTime = t - (t - tl._startTime) * tl._timeScale / value; 9566 tl._timeScale = Animation._rootTimeline._timeScale = value; 9567 return value; 9568 }; 9569 9570 //---- GETTERS / SETTERS ---------------------------------------------------------------------------------------------------------- 9571 9572 p.progress = function (value, suppressEvents) { 9573 return !arguments.length ? this._time / this.duration() : this.totalTime(this.duration() * (this._yoyo && (this._cycle & 1) !== 0 ? 1 - value : value) + this._cycle * (this._duration + this._repeatDelay), suppressEvents); 9574 }; 9575 p.totalProgress = function (value, suppressEvents) { 9576 return !arguments.length ? this._totalTime / this.totalDuration() : this.totalTime(this.totalDuration() * value, suppressEvents); 9577 }; 9578 p.time = function (value, suppressEvents) { 9579 if (!arguments.length) { 9580 return this._time; 9581 } 9582 if (this._dirty) { 9583 this.totalDuration(); 9584 } 9585 if (value > this._duration) { 9586 value = this._duration; 9587 } 9588 if (this._yoyo && (this._cycle & 1) !== 0) { 9589 value = this._duration - value + this._cycle * (this._duration + this._repeatDelay); 9590 } else if (this._repeat !== 0) { 9591 value += this._cycle * (this._duration + this._repeatDelay); 9592 } 9593 return this.totalTime(value, suppressEvents); 9594 }; 9595 p.duration = function (value) { 9596 if (!arguments.length) { 9597 return this._duration; //don't set _dirty = false because there could be repeats that haven't been factored
9597into the _totalDuration yet. Otherwise, if you create a repeated TweenMax and then immediately check its duration(), it would cache the value and the totalDuration would not be correct, thus repeats wouldn't take effect. 9598 } 9599 return Animation.prototype.duration.call(this, value); 9600 }; 9601 p.totalDuration = function (value) { 9602 if (!arguments.length) { 9603 if (this._dirty) { 9604 //instead of Infinity, we use 999999999999 so that we can accommodate reverses 9605 this._totalDuration = this._repeat === -1 ? 999999999999 : this._duration * (this._repeat + 1) + this._repeatDelay * this._repeat; 9606 this._dirty = false; 9607 } 9608 return this._totalDuration; 9609 } 9610 return this._repeat === -1 ? this : this.duration((value - this._repeat * this._repeatDelay) / (this._repeat + 1)); 9611 }; 9612 p.repeat = function (value) { 9613 if (!arguments.length) { 9614 return this._repeat; 9615 } 9616 this._repeat = value; 9617 return this._uncache(true); 9618 }; 9619 p.repeatDelay = function (value) { 9620 if (!arguments.length) { 9621 return this._repeatDelay; 9622 } 9623 this._repeatDelay = value; 9624 return this._uncache(true); 9625 }; 9626 p.yoyo = function (value) { 9627 if (!arguments.length) { 9628 return this._yoyo; 9629 } 9630 this._yoyo = value; 9631 return this; 9632 }; 9633 return _TweenMax; 9634 }, true); 9635 9636 /* 9637 * ---------------------------------------------------------------- 9638 * TimelineLite 9639 * ---------------------------------------------------------------- 9640 */ 9641 _gsScope._gsDefine("TimelineLite", ["core.Animation", "core.SimpleTimeline", "TweenLite"], function (Animation, SimpleTimeline, TweenLite) { 9642 var TimelineLite = function TimelineLite(vars) { 9643 SimpleTimeline.call(this, vars); 9644 this._labels = {}; 9645 this.autoRemoveChildren = this.vars.autoRemoveChildren === true; 9646 this.smoothChildTiming = this.vars.smoothChildTiming === true; 9647 this._sortChildren = true; 9648 this._onUpdate = this.vars.onUpdate; 9649 var v = this.vars, 9650 val, 9651 p; 9652 for (p in v) { 9653 val = v[p]; 9654 if (_isArray(val)) if (val.join("").indexOf("{self}") !== -1) { 9655 v[p] = this._swapSelfInParams(val); 9656 } 9657 } 9658 if (_isArray(v.tweens)) { 9659 this.add(v.tweens, 0, v.align, v.stagger); 9660 } 9661 }, 9662 _tinyNum = 0.0000000001, 9663 TweenLiteInternals = TweenLite._internals, 9664 _internals = TimelineLite._internals = {}, 9665 _isSelector = TweenLiteInternals.isSelector, 9666 _isArray = TweenLiteInternals.isArray, 9667 _lazyTweens = TweenLiteInternals.lazyTweens, 9668 _lazyRender = TweenLiteInternals.lazyRender, 9669 _globals = _gsScope._gsDefine.globals, 9670 _copy = function _copy(vars) { 9671 var copy = {}, 9672 p; 9673 for (p in vars) { 9674 copy[p] = vars[p]; 9675 } 9676 return copy; 9677 }, 9678 _applyCycle = function _applyCycle(vars, targets, i) { 9679 var alt = vars.cycle, 9680 p, 9681 val; 9682 for (p in alt) { 9683 val = alt[p]; 9684 vars[p] = typeof val === "function" ? val(i, targets[i]) : val[i % val.length]; 9685 } 9686 delete vars.cycle; 9687 }, 9688 _pauseCallback = _internals.pauseCallback = function () {}, 9689 _slice = function _slice(a) { 9690 //don't use [].slice because that doesn't work in IE8 with a NodeList that's returned by querySelectorAll() 9691 var b = [], 9692 l = a.length, 9693 i; 9694 for (i = 0; i !== l; b.push(a[i++])); 9695 return b; 9696 }, 9697 p = TimelineLite.prototype = new SimpleTimeline(); 9698 TimelineLite.version = "1.20.4"; 9699 p.constructor = TimelineLite; 9700 p.kill()._gc = p._forcingPlayhead = p._hasPause = false; 9701 9702 /* might use later... 9703 //translates a local time inside an animation to the corresponding time on the root/global timeline, factoring in all nesting and timeScales. 9704 function localToGlobal(time, animation) { 9705 while (animation) { 9706 time = (time / animation._timeScale) + animation._startTime; 9707 animation = animation.timeline; 9708 } 9709 return time; 9710 } 9711 //translates the supplied time on the root/global timeline into the corresponding local time inside a particular animation, factoring in all nesting and timeScales 9712 function globalToLocal(time, animation) { 9713 var scale = 1; 9714 time -= localToGlobal(0, animation); 9715 while (animation) { 9716 scale *= animation._timeScale; 9717 animation = animation.timeline; 9718 } 9719 return time * scale; 9720 } 9721 */ 9722 9723 p.to = function (target, duration, vars, position) { 9724 var Engine = vars.repeat && _globals.TweenMax || TweenLite; 9725 return duration ? this.add(new Engine(target, duration, vars), position) : this.set(target, vars, position); 9726 }; 9727 p.from = function (target, duration, vars, position) { 9728 return this.add((vars.repeat && _globals.TweenMax || TweenLite).from(target, duration, vars), position); 9729 }; 9730 p.fromTo = function (target, duration, fromVars, toVars, position) { 9731 var Engine = toVars.repeat && _globals.TweenMax || TweenLite; 9732 return duration ? this.add(Engine.fromTo(target, duration, fromVars, toVars), position) : this.set(target, toVars, position); 9733 }; 9734 p.staggerTo = function (targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) { 9735 var tl = new TimelineLite({ 9736 onComplete: onCompleteAll, 9737 onCompleteParams: onCompleteAllParams, 9738 callbackScope: onCompleteAllScope, 9739 smoothChildTiming: this.smoothChildTiming 9740 }), 9741 cycle = vars.cycle, 9742 copy, 9743 i; 9744 if (typeof targets === "string") { 9745 targets = TweenLite.selector(targets) || targets; 9746 } 9747 targets = targets || []; 9748 if (_isSelector(targets)) { 9749 //senses if the targets object is a selector. If it is, we should translate it into an array.
9750 targets = _slice(targets); 9751 } 9752 stagger = stagger || 0; 9753 if (stagger < 0) { 9754 targets = _slice(targets); 9755 targets.reverse(); 9756 stagger *= -1; 9757 } 9758 for (i = 0; i < targets.length; i++) { 9759 copy = _copy(vars); 9760 if (copy.startAt) { 9761 copy.startAt = _copy(copy.startAt); 9762 if (copy.startAt.cycle) { 9763 _applyCycle(copy.startAt, targets, i); 9764 } 9765 } 9766 if (cycle) { 9767 _applyCycle(copy, targets, i); 9768 if (copy.duration != null) { 9769 duration = copy.duration; 9770 delete copy.duration; 9771 } 9772 } 9773 tl.to(targets[i], duration, copy, i * stagger); 9774 } 9775 return this.add(tl, position); 9776 }; 9777 p.staggerFrom = function (targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) { 9778 vars.immediateRender = vars.immediateRender != false; 9779 vars.runBackwards = true; 9780 return this.staggerTo(targets, duration, vars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope); 9781 }; 9782 p.staggerFromTo = function (targets, duration, fromVars, toVars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope) { 9783 toVars.startAt = fromVars; 9784 toVars.immediateRender = toVars.immediateRender != false && fromVars.immediateRender != false; 9785 return this.staggerTo(targets, duration, toVars, stagger, position, onCompleteAll, onCompleteAllParams, onCompleteAllScope); 9786 }; 9787 p.call = function (callback, params, scope, position) { 9788 return this.add(TweenLite.delayedCall(0, callback, params, scope), position); 9789 }; 9790 p.set = function (target, vars, position) { 9791 position = this._parseTimeOrLabel(position, 0, true); 9792 if (vars.immediateRender == null) { 9793 vars.immediateRender = position === this._time && !this._paused; 9794 } 9795 return this.add(new TweenLite(target, 0, vars), position); 9796 }; 9797 TimelineLite.exportRoot = function (vars, ignoreDelayedCalls) { 9798 vars = vars || {}; 9799 if (vars.smoothChildTiming == null) { 9800 vars.smoothChildTiming = true; 9801 } 9802 var tl = new TimelineLite(vars), 9803 root = tl._timeline, 9804 hasNegativeStart, 9805 time, 9806 tween, 9807 next; 9808 if (ignoreDelayedCalls == null) { 9809 ignoreDelayedCalls = true; 9810 } 9811 root._remove(tl, true); 9812 tl._startTime = 0; 9813 tl._rawPrevTime = tl._time = tl._totalTime = root._time; 9814 tween = root._first; 9815 while (tween) { 9816 next = tween._next; 9817 if (!ignoreDelayedCalls || !(tween instanceof TweenLite && tween.target === tween.vars.onComplete)) { 9818 time = tween._startTime - tween._delay; 9819 if (time < 0) { 9820 hasNegativeStart = 1; 9821 } 9822 tl.add(tween, time); 9823 } 9824 tween = next; 9825 } 9826 root.add(tl, 0); 9827 if (hasNegativeStart) { 9828 //calling totalDuration() will force the adjustment necessary to shift the children forward so none of them start before zero, and moves the timeline backwards the same amount, so the playhead is still aligned where it should be globally, but the timeline doesn't have illegal children that start before zero. 9829 tl.totalDuration(); 9830 } 9831 return tl; 9832 }; 9833 p.add = function (value, position, align, stagger) { 9834 var curTime, l, i, child, tl, beforeRawTime; 9835 if (typeof position !== "number") { 9836 position = this._parseTimeOrLabel(position, 0, true, value); 9837 } 9838 if (!(value instanceof Animation)) { 9839 if (value instanceof Array || value && value.push && _isArray(value)) { 9840 align = align || "normal"; 9841 stagger = stagger || 0; 9842 curTime = position; 9843 l = value.length; 9844 for (i = 0; i < l; i++) { 9845 if (_isArray(child = value[i])) { 9846 child = new TimelineLite({ 9847 tweens: child 9848 }); 9849 } 9850 this.add(child, curTime); 9851 if (typeof child !== "string" && typeof child !== "function") { 9852 if (align === "sequence") { 9853 curTime = child._startTime + child.totalDuration() / child._timeScale; 9854 } else if (align === "start") { 9855 child._startTime -= child.delay(); 9856 } 9857 } 9858 curTime += stagger; 9859 } 9860 return this._uncache(true); 9861 } else if (typeof value === "string") { 9862 return this.addLabel(value, position); 9863 } else if (typeof value === "function") { 9864 value = TweenLite.delayedCall(0, value); 9865 } else { 9866 throw "Cannot add " + value + " into the timeline; it is not a tween, timeline, function, or string."; 9867 } 9868 } 9869 SimpleTimeline.prototype.add.call(this, value, position); 9870 if (value._time) { 9871 //in case, for example, the _startTime is moved on a tween that has already rendered. Imagine it's at its end state, then the startTime is moved WAY later (after the end of this timeline), it should render at its beginning. 9872 value.render((this.rawTime() - value._startTime) * value._timeScale, false, false); 9873 } 9874 9875 //if the timeline has already ended but the inserted tween/timeline extends the duration, we should enable this timeline again so that it renders properly. We should also align the playhead with the parent timeline's when appropriate. 9876 if (this._gc || this._time === this._duration) if (!this._paused) if (this._duration < this.duration()) { 9877 //in case any of the ancestors had completed but should now be enabled... 9878 tl = this; 9879 beforeRawTime = tl.rawTime() > value._startTime; //if the tween is placed on the timeline so that it starts BEFORE the current rawTime, we should align the playhead (move the timeline). This is because sometimes users will create a timeline, let it finish, and much later append a tween and expect it to run instead of jumping to its end state. While technically one could argue that it should jump to its end state, that's not what users intuitively expect. 9880 while (tl._timeline) { 9881 if (beforeRawTime && tl._timeline.smoothChildTiming) { 9882 tl.totalTime(tl._totalTime, true); //moves the timeline (shifts its startTime) if necessary, and also enables it. 9883 } else if (tl._gc) { 9884 tl._enabled(true, false); 9885 } 9886 tl = tl._timeline; 9887 } 9888 } 9889 return this; 9890 }; 9891 p.remove = function (value) { 9892 if (value instanceof Animation) { 9893 this._remove(value, false); 9894 var tl = value._timeline = value.vars.useFrames ? Animation._rootFramesTimeline : Animation._rootTimeline; //now that it's removed, default it to the root timeline so that if it gets played again, it doesn't jump back into this timeline. 9895 value._startTime = (value._paused ? value._pauseTime : tl._time) - (!value._reversed ? value._totalTime : value.totalDuration() - value._totalTime) / value._timeScale; //ensure that if it gets played again, the timing is correct. 9896 return this; 9897 } else if (value instanceof Array || value && value.push && _isArray(value)) { 9898 var i = value.length; 9899 while (--i > -1) { 9900 this.remove(value[i]); 9901 } 9902 return this; 9903 } else if (typeof value === "string") { 9904 return this.removeLabel(value); 9905 } 9906 return this.kill(null, value); 9907 }; 9908 p._remove = function (tween, skipDisable) { 9909 SimpleTimeline.prototype._remove.call(this, tween, skipDisable); 9910 var last = this._last; 9911 if (!last) { 9912 this._time = this._totalTime = this._duration = this._totalDuration = 0; 9913 } else if (this._time > this.duration()) { 9914 this._time = this._duration; 9915 this._totalTime = this._totalDuration; 9916 } 9917 return this; 9918 }; 9919 p.append = function (value, offsetOrLabel) { 9920 return this.add(value, this._parseTimeOrLabel(null, offsetOrLabel, true, value)); 9921 }; 9922 p.insert = p.insertMultiple = function (value, position, align, stagger) { 9923 return this.add(value, position || 0, align, stagger); 9924 }; 9925 p.appendMultiple = function (tweens, offsetOrLabel, align, stagger) { 9926 return this.add(tweens, this._parseTimeOrLabel(null, offsetOrLabel, true, tweens), align, stagger); 9927 }; 9928 p.addLabel = function (label, position) { 9929 this._labels[label] = this._parseTimeOrLabel(position); 9930 return this; 9931 }; 9932 p.addPause = function (position, callback, params, scope) { 9933 var t = TweenLite.delayedCall(0, _pauseCallback, params, scope || this); 9934 t.vars.onComplete = t.vars.onReverseComplete = callback;
9935 t.data = "isPause"; 9936 this._hasPause = true; 9937 return this.add(t, position); 9938 }; 9939 p.removeLabel = function (label) { 9940 delete this._labels[label]; 9941 return this; 9942 }; 9943 p.getLabelTime = function (label) { 9944 return this._labels[label] != null ? this._labels[label] : -1; 9945 }; 9946 p._parseTimeOrLabel = function (timeOrLabel, offsetOrLabel, appendIfAbsent, ignore) { 9947 var clippedDuration, i; 9948 //if we're about to add a tween/timeline (or an array of them) that's already a child of this timeline, we should remove it first so that it doesn't contaminate the duration(). 9949 if (ignore instanceof Animation && ignore.timeline === this) { 9950 this.remove(ignore); 9951 } else if (ignore && (ignore instanceof Array || ignore.push && _isArray(ignore))) { 9952 i = ignore.length; 9953 while (--i > -1) { 9954 if (ignore[i] instanceof Animation && ignore[i].timeline === this) { 9955 this.remove(ignore[i]); 9956 } 9957 } 9958 } 9959 clippedDuration = typeof timeOrLabel === "number" && !offsetOrLabel ? 0 : this.duration() > 99999999999 ? this.recent().endTime(false) : this._duration; //in case there's a child that infinitely repeats, users almost never intend for the insertion point of a new child to be based on a SUPER long value like that so we clip it and assume the most recently-added child's endTime should be used instead. 9960 if (typeof offsetOrLabel === "string") { 9961 return this._parseTimeOrLabel(offsetOrLabel, appendIfAbsent && typeof timeOrLabel === "number" && this._labels[offsetOrLabel] == null ? timeOrLabel - clippedDuration : 0, appendIfAbsent); 9962 } 9963 offsetOrLabel = offsetOrLabel || 0; 9964 if (typeof timeOrLabel === "string" && (isNaN(timeOrLabel) || this._labels[timeOrLabel] != null)) { 9965 //if the string is a number like "1", check to see if there's a label with that name, otherwise interpret it as a number (absolute value). 9966 i = timeOrLabel.indexOf("="); 9967 if (i === -1) { 9968 if (this._labels[timeOrLabel] == null) { 9969 return appendIfAbsent ? this._labels[timeOrLabel] = clippedDuration + offsetOrLabel : offsetOrLabel; 9970 } 9971 return this._labels[timeOrLabel] + offsetOrLabel; 9972 } 9973 offsetOrLabel = parseInt(timeOrLabel.charAt(i - 1) + "1", 10) * Number(timeOrLabel.substr(i + 1)); 9974 timeOrLabel = i > 1 ? this._parseTimeOrLabel(timeOrLabel.substr(0, i - 1), 0, appendIfAbsent) : clippedDuration; 9975 } else if (timeOrLabel == null) { 9976 timeOrLabel = clippedDuration; 9977 } 9978 return Number(timeOrLabel) + offsetOrLabel; 9979 }; 9980 p.seek = function (position, suppressEvents) { 9981 return this.totalTime(typeof position === "number" ? position : this._parseTimeOrLabel(position), suppressEvents !== false); 9982 }; 9983 p.stop = function () { 9984 return this.paused(true); 9985 }; 9986 p.gotoAndPlay = function (position, suppressEvents) { 9987 return this.play(position, suppressEvents); 9988 }; 9989 p.gotoAndStop = function (position, suppressEvents) { 9990 return this.pause(position, suppressEvents); 9991 }; 9992 p.render = function (time, suppressEvents, force) { 9993 if (this._gc) { 9994 this._enabled(true, false); 9995 } 9996 var prevTime = this._time, 9997 totalDur = !this._dirty ? this._totalDuration : this.totalDuration(), 9998 prevStart = this._startTime, 9999 prevTimeScale = this._timeScale, 10000 prevPaused = this._paused, 10001 tween, 10002 isComplete, 10003 next, 10004 callback, 10005 internalForce, 10006 pauseTween, 10007 curTime; 10008 if (prevTime !== this._time) { 10009 //if totalDuration() finds a child with a negative startTime and smoothChildTiming is true, things get shifted around internally so we need to adjust the time accordingly. For example, if a tween starts at -30 we must shift EVERYTHING forward 30 seconds and move this timeline's startTime backward by 30 seconds so that things align with the playhead (no jump). 10010 time += this._time - prevTime; 10011 } 10012 if (time >= totalDur - 0.0000001 && time >= 0) { 10013 //to work around occasional floating point math artifacts. 10014 this._totalTime = this._time = totalDur; 10015 if (!this._reversed) if (!this._hasPausedChild()) { 10016 isComplete = true; 10017 callback = "onComplete"; 10018 internalForce = !!this._timeline.autoRemoveChildren; //otherwise, if the animation is unpaused/activated after it's already finished, it doesn't get removed from the parent timeline. 10019 if (this._duration === 0) if (time <= 0 && time >= -0.0000001 || this._rawPrevTime < 0 || this._rawPrevTime === _tinyNum) if (this._rawPrevTime !== time && this._first) { 10020 internalForce = true; 10021 if (this._rawPrevTime > _tinyNum) { 10022 callback = "onReverseComplete"; 10023 } 10024 } 10025 } 10026 this._rawPrevTime = this._duration || !suppressEvents || time || this._rawPrevTime === time ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration timeline or tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient. 10027 time = totalDur + 0.0001; //to avoid occasional floating point rounding errors - sometimes child tweens/timelines were not being fully completed (their progress might be 0.999999999999998 instead of 1 because when _time - tween._startTime is performed, floating point errors would return a value that was SLIGHTLY off). Try (999999999999.7 - 999999999999) * 1 = 0.699951171875 instead of 0.7. 10028 } else if (time < 0.0000001) { 10029 //to work around occasional floating point math artifacts, round super small values to 0. 10030 this._totalTime = this._time = 0; 10031 if (prevTime !== 0 || this._duration === 0 && this._rawPrevTime !== _tinyNum && (this._rawPrevTime > 0 || time < 0 && this._rawPrevTime >= 0)) { 10032 callback = "onReverseComplete"; 10033 isComplete = this._reversed; 10034 } 10035 if (time < 0) { 10036 this._active = false;
10037 if (this._timeline.autoRemoveChildren && this._reversed) { 10038 //ensures proper GC if a timeline is resumed after it's finished reversing. 10039 internalForce = isComplete = true; 10040 callback = "onReverseComplete"; 10041 } else if (this._rawPrevTime >= 0 && this._first) { 10042 //when going back beyond the start, force a render so that zero-duration tweens that sit at the very beginning render their start values properly. Otherwise, if the parent timeline's playhead lands exactly at this timeline's startTime, and then moves backwards, the zero-duration tweens at the beginning would still be at their end state. 10043 internalForce = true; 10044 } 10045 this._rawPrevTime = time; 10046 } else { 10047 this._rawPrevTime = this._duration || !suppressEvents || time || this._rawPrevTime === time ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration timeline or tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient. 10048 if (time === 0 && isComplete) { 10049 //if there's a zero-duration tween at the very beginning of a timeline and the playhead lands EXACTLY at time 0, that tween will correctly render its end values, but we need to keep the timeline alive for one more render so that the beginning values render properly as the parent's playhead keeps moving beyond the begining. Imagine obj.x starts at 0 and then we do tl.set(obj, {x:100}).to(obj, 1, {x:200}) and then later we tl.reverse()...the goal is to have obj.x revert to 0. If the playhead happens to land on exactly 0, without this chunk of code, it'd complete the timeline and remove it from the rendering queue (not good). 10050 tween = this._first; 10051 while (tween && tween._startTime === 0) { 10052 if (!tween._duration) { 10053 isComplete = false; 10054 } 10055 tween = tween._next; 10056 } 10057 } 10058 time = 0; //to avoid occasional floating point rounding errors (could cause problems especially with zero-duration tweens at the very beginning of the timeline) 10059 if (!this._initted) { 10060 internalForce = true; 10061 } 10062 } 10063 } else { 10064 if (this._hasPause && !this._forcingPlayhead && !suppressEvents) { 10065 if (time >= prevTime) { 10066 tween = this._first; 10067 while (tween && tween._startTime <= time && !pauseTween) { 10068 if (!tween._duration) if (tween.data === "isPause" && !tween.ratio && !(tween._startTime === 0 && this._rawPrevTime === 0)) { 10069 pauseTween = tween; 10070 } 10071 tween = tween._next; 10072 } 10073 } else { 10074 tween = this._last; 10075 while (tween && tween._startTime >= time && !pauseTween) { 10076 if (!tween._duration) if (tween.data === "isPause" && tween._rawPrevTime > 0) { 10077 pauseTween = tween; 10078 } 10079 tween = tween._prev; 10080 } 10081 } 10082 if (pauseTween) { 10083 this._time = time = pauseTween._startTime; 10084 this._totalTime = time + this._cycle * (this._totalDuration + this._repeatDelay); 10085 } 10086 } 10087 this._totalTime = this._time = this._rawPrevTime = time; 10088 } 10089 if ((this._time === prevTime || !this._first) && !force && !internalForce && !pauseTween) { 10090 return; 10091 } else if (!this._initted) { 10092 this._initted = true; 10093 } 10094 if (!this._active) if (!this._paused && this._time !== prevTime && time > 0) { 10095 this._active = true; //so that if the user renders the timeline (as opposed to the parent timeline rendering it), it is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the timeline already finished but the user manually re-renders it as halfway done, for example. 10096 } 10097 if (prevTime === 0) if (this.vars.onStart) if (this._time !== 0 || !this._duration) if (!suppressEvents) { 10098 this._callback("onStart"); 10099 } 10100 curTime = this._time; 10101 if (curTime >= prevTime) { 10102 tween = this._first; 10103 while (tween) { 10104 next = tween._next; //record it here because the value could change after rendering... 10105 if (curTime !== this._time || this._paused && !prevPaused) { 10106 //in case a tween pauses or seeks the timeline when rendering, like inside of an onUpdate/onComplete 10107 break; 10108 } else if (tween._active || tween._startTime <= curTime && !tween._paused && !tween._gc) { 10109 if (pauseTween === tween) { 10110 this.pause(); 10111 } 10112 if (!tween._reversed) { 10113 tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force); 10114 } else { 10115 tween.render((!tween._dirty ? tween._totalDuration : tween.totalDuration()) - (time - tween._startTime) * tween._timeScale, suppressEvents, force); 10116 } 10117 } 10118 tween = next; 10119 } 10120 } else { 10121 tween = this._last; 10122 while (tween) { 10123 next = tween._prev; //record it here because the value could change after rendering... 10124 if (curTime !== this._time || this._paused && !prevPaused) { 10125 //in case a tween pauses or seeks the timeline when rendering, like inside of an onUpdate/onComplete 10126 break; 10127 } else if (tween._active || tween._startTime <= prevTime && !tween._paused && !tween._gc) { 10128 if (pauseTween === tween) { 10129 pauseTween = tween._prev; //the linked list is organized by _startTime, thus it's possible that a tween could start BEFORE the pause and end after it, in which case it would be positioned before the pause tween in the linked list, but we should render it before we pause() the timeline and cease rendering. This is only a concern when going in reverse. 10130 while (pauseTween && pauseTween.endTime() > this._time) { 10131 pauseTween.render(pauseTween._reversed ? pauseTween.totalDuration() - (time - pauseTween._startTime) * pauseTween._timeScale : (time - pauseTween._startTime) * pauseTween._timeScale, suppressEvents, force); 10132 pauseTween = pauseTween._prev; 10133 } 10134 pauseTween = null; 10135 this.pause(); 10136 } 10137 if (!tween._reversed) { 10138 tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force); 10139 } else { 10140 tween.render((!tween._dirty ? tween._totalDuration : tween.totalDuration()) - (time - tween._startTime) * tween._timeScale, suppressEvents, force); 10141 } 10142 } 10143 tween = next; 10144 } 10145 } 10146 if (this._onUpdate) if (!suppressEvents) { 10147 if (_lazyTweens.length) { 10148 //in case rendering caused any tweens to lazy-init, we should render them because typically when a timeline finishes, users expect things to have rendered fully. Imagine an onUpdate on a timeline that reports/checks tweened values. 10149 _lazyRender(); 10150 }
10151 this._callback("onUpdate"); 10152 } 10153 if (callback) if (!this._gc) if (prevStart === this._startTime || prevTimeScale !== this._timeScale) if (this._time === 0 || totalDur >= this.totalDuration()) { 10154 //if one of the tweens that was rendered altered this timeline's startTime (like if an onComplete reversed the timeline), it probably isn't complete. If it is, don't worry, because whatever call altered the startTime would complete if it was necessary at the new time. The only exception is the timeScale property. Also check _gc because there's a chance that kill() could be called in an onUpdate 10155 if (isComplete) { 10156 if (_lazyTweens.length) { 10157 //in case rendering caused any tweens to lazy-init, we should render them because typically when a timeline finishes, users expect things to have rendered fully. Imagine an onComplete on a timeline that reports/checks tweened values. 10158 _lazyRender(); 10159 } 10160 if (this._timeline.autoRemoveChildren) { 10161 this._enabled(false, false); 10162 } 10163 this._active = false; 10164 } 10165 if (!suppressEvents && this.vars[callback]) { 10166 this._callback(callback); 10167 } 10168 } 10169 }; 10170 p._hasPausedChild = function () { 10171 var tween = this._first; 10172 while (tween) { 10173 if (tween._paused || tween instanceof TimelineLite && tween._hasPausedChild()) { 10174 return true; 10175 } 10176 tween = tween._next; 10177 } 10178 return false; 10179 }; 10180 p.getChildren = function (nested, tweens, timelines, ignoreBeforeTime) { 10181 ignoreBeforeTime = ignoreBeforeTime || -9999999999; 10182 var a = [], 10183 tween = this._first, 10184 cnt = 0; 10185 while (tween) { 10186 if (tween._startTime < ignoreBeforeTime) { 10187 //do nothing 10188 } else if (tween instanceof TweenLite) { 10189 if (tweens !== false) { 10190 a[cnt++] = tween; 10191 } 10192 } else { 10193 if (timelines !== false) { 10194 a[cnt++] = tween; 10195 } 10196 if (nested !== false) { 10197 a = a.concat(tween.getChildren(true, tweens, timelines)); 10198 cnt = a.length; 10199 } 10200 } 10201 tween = tween._next; 10202 } 10203 return a; 10204 }; 10205 p.getTweensOf = function (target, nested) { 10206 var disabled = this._gc, 10207 a = [], 10208 cnt = 0, 10209 tweens, 10210 i; 10211 if (disabled) { 10212 this._enabled(true, true); //getTweensOf() filters out disabled tweens, and we have to mark them as _gc = true when the timeline completes in order to allow clean garbage collection, so temporarily re-enable the timeline here. 10213 } 10214 tweens = TweenLite.getTweensOf(target); 10215 i = tweens.length; 10216 while (--i > -1) { 10217 if (tweens[i].timeline === this || nested && this._contains(tweens[i])) { 10218 a[cnt++] = tweens[i]; 10219 } 10220 } 10221 if (disabled) { 10222 this._enabled(false, true); 10223 } 10224 return a; 10225 }; 10226 p.recent = function () { 10227 return this._recent; 10228 }; 10229 p._contains = function (tween) { 10230 var tl = tween.timeline; 10231 while (tl) { 10232 if (tl === this) { 10233 return true; 10234 } 10235 tl = tl.timeline; 10236 } 10237 return false; 10238 }; 10239 p.shiftChildren = function (amount, adjustLabels, ignoreBeforeTime) { 10240 ignoreBeforeTime = ignoreBeforeTime || 0; 10241 var tween = this._first, 10242 labels = this._labels, 10243 p; 10244 while (tween) { 10245 if (tween._startTime >= ignoreBeforeTime) { 10246 tween._startTime += amount; 10247 } 10248 tween = tween._next; 10249 } 10250 if (adjustLabels) { 10251 for (p in labels) { 10252 if (labels[p] >= ignoreBeforeTime) { 10253 labels[p] += amount; 10254 } 10255 } 10256 } 10257 return this._uncache(true); 10258 }; 10259 p._kill = function (vars, target) { 10260 if (!vars && !target) { 10261 return this._enabled(false, false); 10262 } 10263 var tweens = !target ? this.getChildren(true, true, false) : this.getTweensOf(target), 10264 i = tweens.length, 10265 changed = false; 10266 while (--i > -1) { 10267 if (tweens[i]._kill(vars, target)) { 10268 changed = true; 10269 } 10270 } 10271 return changed; 10272 }; 10273 p.clear = function (labels) { 10274 var tweens = this.getChildren(false, true, true), 10275 i = tweens.length; 10276 this._time = this._totalTime = 0; 10277 while (--i > -1) { 10278 tweens[i]._enabled(false, false); 10279 } 10280 if (labels !== false) { 10281 this._labels = {}; 10282 } 10283 return this._uncache(true); 10284 }; 10285 p.invalidate = function () { 10286 var tween = this._first; 10287 while (tween) { 10288 tween.invalidate(); 10289 tween = tween._next; 10290 } 10291 return Animation.prototype.invalidate.call(this); 10292 ; 10293 }; 10294 p._enabled = function (enabled, ignoreTimeline) { 10295 if (enabled === this._gc) { 10296 var tween = this._first; 10297 while (tween) { 10298 tween._enabled(enabled, true); 10299 tween = tween._next; 10300 } 10301 } 10302 return SimpleTimeline.prototype._enabled.call(this, enabled, ignoreTimeline); 10303 }; 10304 p.totalTime = function (time, suppressEvents, uncapped) { 10305 this._forcingPlayhead = true; 10306 var val = Animation.prototype.totalTime.apply(this, arguments); 10307 this._forcingPlayhead = false;
10308 return val; 10309 }; 10310 p.duration = function (value) { 10311 if (!arguments.length) { 10312 if (this._dirty) { 10313 this.totalDuration(); //just triggers recalculation 10314 } 10315 return this._duration; 10316 } 10317 if (this.duration() !== 0 && value !== 0) { 10318 this.timeScale(this._duration / value); 10319 } 10320 return this; 10321 }; 10322 p.totalDuration = function (value) { 10323 if (!arguments.length) { 10324 if (this._dirty) { 10325 var max = 0, 10326 tween = this._last, 10327 prevStart = 999999999999, 10328 prev, 10329 end; 10330 while (tween) { 10331 prev = tween._prev; //record it here in case the tween changes position in the sequence... 10332 if (tween._dirty) { 10333 tween.totalDuration(); //could change the tween._startTime, so make sure the tween's cache is clean before analyzing it. 10334 } 10335 if (tween._startTime > prevStart && this._sortChildren && !tween._paused && !this._calculatingDuration) { 10336 //in case one of the tweens shifted out of order, it needs to be re-inserted into the correct position in the sequence 10337 this._calculatingDuration = 1; //prevent endless recursive calls - there are methods that get triggered that check duration/totalDuration when we add(), like _parseTimeOrLabel(). 10338 this.add(tween, tween._startTime - tween._delay); 10339 this._calculatingDuration = 0; 10340 } else { 10341 prevStart = tween._startTime; 10342 } 10343 if (tween._startTime < 0 && !tween._paused) { 10344 //children aren't allowed to have negative startTimes unless smoothChildTiming is true, so adjust here if one is found. 10345 max -= tween._startTime; 10346 if (this._timeline.smoothChildTiming) { 10347 this._startTime += tween._startTime / this._timeScale; 10348 this._time -= tween._startTime; 10349 this._totalTime -= tween._startTime; 10350 this._rawPrevTime -= tween._startTime; 10351 } 10352 this.shiftChildren(-tween._startTime, false, -9999999999); 10353 prevStart = 0; 10354 } 10355 end = tween._startTime + tween._totalDuration / tween._timeScale; 10356 if (end > max) { 10357 max = end; 10358 } 10359 tween = prev; 10360 } 10361 this._duration = this._totalDuration = max; 10362 this._dirty = false; 10363 } 10364 return this._totalDuration; 10365 } 10366 return value && this.totalDuration() ? this.timeScale(this._totalDuration / value) : this; 10367 }; 10368 p.paused = function (value) { 10369 if (!value) { 10370 //if there's a pause directly at the spot from where we're unpausing, skip it. 10371 var tween = this._first, 10372 time = this._time; 10373 while (tween) { 10374 if (tween._startTime === time && tween.data === "isPause") { 10375 tween._rawPrevTime = 0; //remember, _rawPrevTime is how zero-duration tweens/callbacks sense directionality and determine whether or not to fire. If _rawPrevTime is the same as _startTime on the next render, it won't fire. 10376 } 10377 tween = tween._next; 10378 } 10379 } 10380 return Animation.prototype.paused.apply(this, arguments); 10381 }; 10382 p.usesFrames = function () { 10383 var tl = this._timeline; 10384 while (tl._timeline) { 10385 tl = tl._timeline; 10386 } 10387 return tl === Animation._rootFramesTimeline; 10388 }; 10389 p.rawTime = function (wrapRepeats) { 10390 return wrapRepeats && (this._paused || this._repeat && this.time() > 0 && this.totalProgress() < 1) ? this._totalTime % (this._duration + this._repeatDelay) : this._paused ? this._totalTime : (this._timeline.rawTime(wrapRepeats) - this._startTime) * this._timeScale; 10391 }; 10392 return TimelineLite; 10393 }, true); 10394 10395 /* 10396 * ---------------------------------------------------------------- 10397 * TimelineMax 10398 * ---------------------------------------------------------------- 10399 */ 10400 _gsScope._gsDefine("TimelineMax", ["TimelineLite", "TweenLite", "easing.Ease"], function (TimelineLite, TweenLite, Ease) { 10401 var TimelineMax = function TimelineMax(vars) { 10402 TimelineLite.call(this, vars); 10403 this._repeat = this.vars.repeat || 0; 10404 this._repeatDelay = this.vars.repeatDelay || 0; 10405 this._cycle = 0; 10406 this._yoyo = this.vars.yoyo === true; 10407 this._dirty = true; 10408 }, 10409 _tinyNum = 0.0000000001, 10410 TweenLiteInternals = TweenLite._internals, 10411 _lazyTweens = TweenLiteInternals.lazyTweens, 10412 _lazyRender = TweenLiteInternals.lazyRender, 10413 _globals = _gsScope._gsDefine.globals,
10414 _easeNone = new Ease(null, null, 1, 0), 10415 p = TimelineMax.prototype = new TimelineLite(); 10416 p.constructor = TimelineMax; 10417 p.kill()._gc = false; 10418 TimelineMax.version = "1.20.4"; 10419 p.invalidate = function () { 10420 this._yoyo = this.vars.yoyo === true; 10421 this._repeat = this.vars.repeat || 0; 10422 this._repeatDelay = this.vars.repeatDelay || 0; 10423 this._uncache(true); 10424 return TimelineLite.prototype.invalidate.call(this); 10425 }; 10426 p.addCallback = function (callback, position, params, scope) { 10427 return this.add(TweenLite.delayedCall(0, callback, params, scope), position); 10428 }; 10429 p.removeCallback = function (callback, position) { 10430 if (callback) { 10431 if (position == null) { 10432 this._kill(null, callback); 10433 } else { 10434 var a = this.getTweensOf(callback, false), 10435 i = a.length, 10436 time = this._parseTimeOrLabel(position); 10437 while (--i > -1) { 10438 if (a[i]._startTime === time) { 10439 a[i]._enabled(false, false); 10440 } 10441 } 10442 } 10443 } 10444 return this; 10445 }; 10446 p.removePause = function (position) { 10447 return this.removeCallback(TimelineLite._internals.pauseCallback, position); 10448 }; 10449 p.tweenTo = function (position, vars) { 10450 vars = vars || {}; 10451 var copy = { 10452 ease: _easeNone, 10453 useFrames: this.usesFrames(), 10454 immediateRender: false, 10455 lazy: false 10456 }, 10457 Engine = vars.repeat && _globals.TweenMax || TweenLite, 10458 duration, 10459 p, 10460 t; 10461 for (p in vars) { 10462 copy[p] = vars[p]; 10463 } 10464 copy.time = this._parseTimeOrLabel(position); 10465 duration = Math.abs(Number(copy.time) - this._time) / this._timeScale || 0.001; 10466 t = new Engine(this, duration, copy); 10467 copy.onStart = function () { 10468 t.target.paused(true); 10469 if (t.vars.time !== t.target.time() && duration === t.duration() && !t.isFromTo) { 10470 //don't make the duration zero - if it's supposed to be zero, don't worry because it's already initting the tween and will complete immediately, effectively making the duration zero anyway. If we make duration zero, the tween won't run at all. 10471 t.duration(Math.abs(t.vars.time - t.target.time()) / t.target._timeScale).render(t.time(), true, true); //render() right away to ensure that things look right, especially in the case of .tweenTo(0). 10472 } 10473 if (vars.onStart) { 10474 //in case the user had an onStart in the vars - we don't want to overwrite it. 10475 vars.onStart.apply(vars.onStartScope || vars.callbackScope || t, vars.onStartParams || []); //don't use t._callback("onStart") or it'll point to the copy.onStart and we'll get a recursion error. 10476 } 10477 }; 10478 return t; 10479 }; 10480 p.tweenFromTo = function (fromPosition, toPosition, vars) { 10481 vars = vars || {}; 10482 fromPosition = this._parseTimeOrLabel(fromPosition); 10483 vars.startAt = { 10484 onComplete: this.seek, 10485 onCompleteParams: [fromPosition], 10486 callbackScope: this 10487 }; 10488 vars.immediateRender = vars.immediateRender !== false; 10489 var t = this.tweenTo(toPosition, vars); 10490 t.isFromTo = 1; //to ensure we don't mess with the duration in the onStart (we've got the start and end values here, so lock it in) 10491 return t.duration(Math.abs(t.vars.time - fromPosition) / this._timeScale || 0.001); 10492 }; 10493 p.render = function (time, suppressEvents, force) { 10494 if (this._gc) { 10495 this._enabled(true, false); 10496 } 10497 var prevTime = this._time, 10498 totalDur = !this._dirty ? this._totalDuration : this.totalDuration(), 10499 dur = this._duration, 10500 prevTotalTime = this._totalTime, 10501 prevStart = this._startTime, 10502 prevTimeScale = this._timeScale, 10503 prevRawPrevTime = this._rawPrevTime, 10504 prevPaused = this._paused, 10505 prevCycle = this._cycle, 10506 tween, 10507 isComplete, 10508 next, 10509 callback, 10510 internalForce, 10511 cycleDuration, 10512 pauseTween, 10513 curTime; 10514 if (prevTime !== this._time) { 10515 //if totalDuration() finds a child with a negative startTime and smoothChildTiming is true, things get shifted around internally so we need to adjust the time accordingly. For example, if a tween starts at -30 we must shift EVERYTHING forward 30 seconds and move this timeline's startTime backward by 30 seconds so that things align with the playhead (no jump). 10516 time += this._time - prevTime; 10517 } 10518 if (time >= totalDur - 0.0000001 && time >= 0) { 10519 //to work around occasional floating point math artifacts. 10520 if (!this._locked) { 10521 this._totalTime = totalDur; 10522 this._cycle = this._repeat; 10523 } 10524 if (!this._reversed) if (!this._hasPausedChild()) { 10525 isComplete = true; 10526 callback = "onComplete"; 10527 internalForce = !!this._timeline.autoRemoveChildren; //otherwise, if the animation is unpaused/activated after it's already finished, it doesn't get removed from the parent timeline. 10528 if (this._duration === 0) if (time <= 0 && time >= -0.0000001 || prevRawPrevTime < 0 || prevRawPrevTime === _tinyNum) if (prevRawPrevTime !== time && this._first) { 10529 internalForce = true; 10530 if (prevRawPrevTime > _tinyNum) { 10531 callback = "onReverseComplete"; 10532 } 10533 } 10534 } 10535 this._rawPrevTime = this._duration || !suppressEvents || time || this._rawPrevTime === time ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration timeline or tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient. 10536 if (this._yoyo && (this._cycle & 1) !== 0) { 10537 this._time = time = 0; 10538 } else { 10539 this._time = dur; 10540 time = dur + 0.0001; //to avoid occasional floating point rounding errors - sometimes child tweens/timelines were not being fully completed (their progress might be 0.999999999999998 instead of 1 because when _time - tween._startTime is performed, floating point errors would return a value that was SLIGHTLY off). Try (999999999999.7 - 999999999999) * 1 = 0.699951171875 instead of 0.7. We cannot do less then 0.0001 because the same issue can occur when the duration is extremely large like 999999999999 in
10540which case adding 0.00000001, for example, causes it to act like nothing was added. 10541 } 10542 } else if (time < 0.0000001) { 10543 //to work around occasional floating point math artifacts, round super small values to 0. 10544 if (!this._locked) { 10545 this._totalTime = this._cycle = 0; 10546 } 10547 this._time = 0; 10548 if (prevTime !== 0 || dur === 0 && prevRawPrevTime !== _tinyNum && (prevRawPrevTime > 0 || time < 0 && prevRawPrevTime >= 0) && !this._locked) { 10549 //edge case for checking time < 0 && prevRawPrevTime >= 0: a zero-duration fromTo() tween inside a zero-duration timeline (yeah, very rare) 10550 callback = "onReverseComplete"; 10551 isComplete = this._reversed; 10552 } 10553 if (time < 0) { 10554 this._active = false; 10555 if (this._timeline.autoRemoveChildren && this._reversed) { 10556 internalForce = isComplete = true; 10557 callback = "onReverseComplete"; 10558 } else if (prevRawPrevTime >= 0 && this._first) { 10559 //when going back beyond the start, force a render so that zero-duration tweens that sit at the very beginning render their start values properly. Otherwise, if the parent timeline's playhead lands exactly at this timeline's startTime, and then moves backwards, the zero-duration tweens at the beginning would still be at their end state. 10560 internalForce = true; 10561 } 10562 this._rawPrevTime = time; 10563 } else { 10564 this._rawPrevTime = dur || !suppressEvents || time || this._rawPrevTime === time ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration timeline or tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient. 10565 if (time === 0 && isComplete) { 10566 //if there's a zero-duration tween at the very beginning of a timeline and the playhead lands EXACTLY at time 0, that tween will correctly render its end values, but we need to keep the timeline alive for one more render so that the beginning values render properly as the parent's playhead keeps moving beyond the begining. Imagine obj.x starts at 0 and then we do tl.set(obj, {x:100}).to(obj, 1, {x:200}) and then later we tl.reverse()...the goal is to have obj.x revert to 0. If the playhead happens to land on exactly 0, without this chunk of code, it'd complete the timeline and remove it from the rendering queue (not good). 10567 tween = this._first; 10568 while (tween && tween._startTime === 0) { 10569 if (!tween._duration) { 10570 isComplete = false; 10571 } 10572 tween = tween._next; 10573 } 10574 } 10575 time = 0; //to avoid occasional floating point rounding errors (could cause problems especially with zero-duration tweens at the very beginning of the timeline) 10576 if (!this._initted) { 10577 internalForce = true; 10578 } 10579 } 10580 } else { 10581 if (dur === 0 && prevRawPrevTime < 0) { 10582 //without this, zero-duration repeating timelines (like with a simple callback nested at the very beginning and a repeatDelay) wouldn't render the first time through. 10583 internalForce = true; 10584 } 10585 this._time = this._rawPrevTime = time; 10586 if (!this._locked) { 10587 this._totalTime = time; 10588 if (this._repeat !== 0) { 10589 cycleDuration = dur + this._repeatDelay; 10590 this._cycle = this._totalTime / cycleDuration >> 0; //originally _totalTime % cycleDuration but floating point errors caused problems, so I normalized it. (4 % 0.8 should be 0 but it gets reported as 0.79999999!) 10591 if (this._cycle !== 0) if (this._cycle === this._totalTime / cycleDuration && prevTotalTime <= time) { 10592 this._cycle--; //otherwise when rendered exactly at the end time, it will act as though it is repeating (at the beginning) 10593 } 10594 this._time = this._totalTime - this._cycle * cycleDuration; 10595 if (this._yoyo) if ((this._cycle & 1) !== 0) { 10596 this._time = dur - this._time; 10597 } 10598 if (this._time > dur) { 10599 this._time = dur; 10600 time = dur + 0.0001; //to avoid occasional floating point rounding error 10601 } else if (this._time < 0) { 10602 this._time = time = 0; 10603 } else { 10604 time = this._time; 10605 } 10606 } 10607 } 10608 if (this._hasPause && !this._forcingPlayhead && !suppressEvents) { 10609 time = this._time; 10610 if (time >= prevTime || this._repeat && prevCycle !== this._cycle) { 10611 tween = this._first; 10612 while (tween && tween._startTime <= time && !pauseTween) { 10613 if (!tween._duration) if (tween.data === "isPause" && !tween.ratio && !(tween._startTime === 0 && this._rawPrevTime === 0)) { 10614 pauseTween = tween; 10615 } 10616 tween = tween._next; 10617 } 10618 } else { 10619 tween = this._last; 10620 while (tween && tween._startTime >= time && !pauseTween) { 10621 if (!tween._duration) if (tween.data === "isPause" && tween._rawPrevTime > 0) { 10622 pauseTween = tween; 10623 } 10624 tween = tween._prev; 10625 } 10626 } 10627 if (pauseTween && pauseTween._startTime < dur) { 10628 this._time = time = pauseTween._startTime; 10629 this._totalTime = time + this._cycle * (this._totalDuration + this._repeatDelay); 10630 } 10631 } 10632 } 10633 if (this._cycle !== prevCycle) if (!this._locked) { 10634 /* 10635 make sure children at the end/beginning of the timeline are rendered properly. If, for example, 10636 a 3-second long timeline rendered at 2.9 seconds previously, and now renders at 3.2 seconds (which
10637 would get transated to 2.8 seconds if the timeline yoyos or 0.2 seconds if it just repeats), there 10638 could be a callback or a short tween that's at 2.95 or 3 seconds in which wouldn't render. So 10639 we need to push the timeline to the end (and/or beginning depending on its yoyo value). Also we must 10640 ensure that zero-duration tweens at the very beginning or end of the TimelineMax work. 10641 */ 10642 var backwards = this._yoyo && (prevCycle & 1) !== 0, 10643 wrap = backwards === (this._yoyo && (this._cycle & 1) !== 0), 10644 recTotalTime = this._totalTime, 10645 recCycle = this._cycle, 10646 recRawPrevTime = this._rawPrevTime, 10647 recTime = this._time; 10648 this._totalTime = prevCycle * dur; 10649 if (this._cycle < prevCycle) { 10650 backwards = !backwards; 10651 } else { 10652 this._totalTime += dur; 10653 } 10654 this._time = prevTime; //temporarily revert _time so that render() renders the children in the correct order. Without this, tweens won't rewind correctly. We could arhictect things in a "cleaner" way by splitting out the rendering queue into a separate method but for performance reasons, we kept it all inside this method. 10655 10656 this._rawPrevTime = dur === 0 ? prevRawPrevTime - 0.0001 : prevRawPrevTime; 10657 this._cycle = prevCycle; 10658 this._locked = true; //prevents changes to totalTime and skips repeat/yoyo behavior when we recursively call render() 10659 prevTime = backwards ? 0 : dur; 10660 this.render(prevTime, suppressEvents, dur === 0); 10661 if (!suppressEvents) if (!this._gc) { 10662 if (this.vars.onRepeat) { 10663 this._cycle = recCycle; //in case the onRepeat alters the playhead or invalidates(), we shouldn't stay locked or use the previous cycle. 10664 this._locked = false; 10665 this._callback("onRepeat"); 10666 } 10667 } 10668 if (prevTime !== this._time) { 10669 //in case there's a callback like onComplete in a nested tween/timeline that changes the playhead position, like via seek(), we should just abort. 10670 return; 10671 } 10672 if (wrap) { 10673 this._cycle = prevCycle; //if there's an onRepeat, we reverted this above, so make sure it's set properly again. We also unlocked in that scenario, so reset that too. 10674 this._locked = true; 10675 prevTime = backwards ? dur + 0.0001 : -0.0001; 10676 this.render(prevTime, true, false); 10677 } 10678 this._locked = false; 10679 if (this._paused && !prevPaused) { 10680 //if the render() triggered callback that paused this timeline, we should abort (very rare, but possible) 10681 return; 10682 } 10683 this._time = recTime; 10684 this._totalTime = recTotalTime; 10685 this._cycle = recCycle; 10686 this._rawPrevTime = recRawPrevTime; 10687 } 10688 if ((this._time === prevTime || !this._first) && !force && !internalForce && !pauseTween) { 10689 if (prevTotalTime !== this._totalTime) if (this._onUpdate) if (!suppressEvents) { 10690 //so that onUpdate fires even during the repeatDelay - as long as the totalTime changed, we should trigger onUpdate. 10691 this._callback("onUpdate"); 10692 } 10693 return; 10694 } else if (!this._initted) { 10695 this._initted = true; 10696 } 10697 if (!this._active) if (!this._paused && this._totalTime !== prevTotalTime && time > 0) { 10698 this._active = true; //so that if the user renders the timeline (as opposed to the parent timeline rendering it), it is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the timeline already finished but the user manually re-renders it as halfway done, for example. 10699 } 10700 if (prevTotalTime === 0) if (this.vars.onStart) if (this._totalTime !== 0 || !this._totalDuration) if (!suppressEvents) { 10701 this._callback("onStart"); 10702 } 10703 curTime = this._time; 10704 if (curTime >= prevTime) { 10705 tween = this._first; 10706 while (tween) { 10707 next = tween._next; //record it here because the value could change after rendering... 10708 if (curTime !== this._time || this._paused && !prevPaused) { 10709 //in case a tween pauses or seeks the timeline when rendering, like inside of an onUpdate/onComplete 10710 break; 10711 } else if (tween._active || tween._startTime <= this._time && !tween._paused && !tween._gc) { 10712 if (pauseTween === tween) { 10713 this.pause(); 10714 } 10715 if (!tween._reversed) { 10716 tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force); 10717 } else { 10718 tween.render((!tween._dirty ? tween._totalDuration : tween.totalDuration()) - (time - tween._startTime) * tween._timeScale, suppressEvents, force); 10719 } 10720 } 10721 tween = next; 10722 } 10723 } else { 10724 tween = this._last; 10725 while (tween) { 10726 next = tween._prev; //record it here because the value could change after rendering... 10727 if (curTime !== this._time || this._paused && !prevPaused) { 10728 //in case a tween pauses or seeks the timeline when rendering, like inside of an onUpdate/onComplete 10729 break; 10730 } else if (tween._active || tween._startTime <= prevTime && !tween._paused && !tween._gc) { 10731 if (pauseTween === tween) { 10732 pauseTween = tween._prev; //the linked list is organized by _startTime, thus it's possible that a tween could start BEFORE the pause and end after it, in which case it would be positioned before the pause tween in the linked list, but we should render it before we pause() the timeline and cease rendering. This is only a concern when going in reverse. 10733 while (pauseTween && pauseTween.endTime() > this._time) { 10734 pauseTween.render(pauseTween._reversed ? pauseTween.totalDuration() - (time - pauseTween._startTime) * pauseTween._timeScale : (time - pauseTween._startTime) * pauseTween._timeScale, suppressEvents, force); 10735 pauseTween = pauseTween._prev; 10736 } 10737 pauseTween = null; 10738 this.pause(); 10739 } 10740 if (!tween._reversed) { 10741 tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force); 10742 } else { 10743 tween.render((!tween._dirty ? tween._totalDuration : tween.totalDuration()) - (time - tween._startTime) * tween._timeScale, suppressEvents, force); 10744 } 10745 } 10746 tween = next; 10747 } 10748 } 10749 if (this._onUpdate) if (!suppressEvents) { 10750 if (_lazyTweens.length) { 10751 //in case rendering caused any tweens to lazy-init, we should render them because typically when a timeline finishes, users expect things to have rendered fully. Imagine an onUpdate on a timeline that reports/checks tweened values. 10752 _lazyRender(); 10753 }
10754 this._callback("onUpdate"); 10755 } 10756 if (callback) if (!this._locked) if (!this._gc) if (prevStart === this._startTime || prevTimeScale !== this._timeScale) if (this._time === 0 || totalDur >= this.totalDuration()) { 10757 //if one of the tweens that was rendered altered this timeline's startTime (like if an onComplete reversed the timeline), it probably isn't complete. If it is, don't worry, because whatever call altered the startTime would complete if it was necessary at the new time. The only exception is the timeScale property. Also check _gc because there's a chance that kill() could be called in an onUpdate 10758 if (isComplete) { 10759 if (_lazyTweens.length) { 10760 //in case rendering caused any tweens to lazy-init, we should render them because typically when a timeline finishes, users expect things to have rendered fully. Imagine an onComplete on a timeline that reports/checks tweened values. 10761 _lazyRender(); 10762 } 10763 if (this._timeline.autoRemoveChildren) { 10764 this._enabled(false, false); 10765 } 10766 this._active = false; 10767 } 10768 if (!suppressEvents && this.vars[callback]) { 10769 this._callback(callback); 10770 } 10771 } 10772 }; 10773 p.getActive = function (nested, tweens, timelines) { 10774 if (nested == null) { 10775 nested = true; 10776 } 10777 if (tweens == null) { 10778 tweens = true; 10779 } 10780 if (timelines == null) { 10781 timelines = false; 10782 } 10783 var a = [], 10784 all = this.getChildren(nested, tweens, timelines), 10785 cnt = 0, 10786 l = all.length, 10787 i, 10788 tween; 10789 for (i = 0; i < l; i++) { 10790 tween = all[i]; 10791 if (tween.isActive()) { 10792 a[cnt++] = tween; 10793 } 10794 } 10795 return a; 10796 }; 10797 p.getLabelAfter = function (time) { 10798 if (!time) if (time !== 0) { 10799 //faster than isNan() 10800 time = this._time; 10801 } 10802 var labels = this.getLabelsArray(), 10803 l = labels.length, 10804 i; 10805 for (i = 0; i < l; i++) { 10806 if (labels[i].time > time) { 10807 return labels[i].name; 10808 } 10809 } 10810 return null; 10811 }; 10812 p.getLabelBefore = function (time) { 10813 if (time == null) { 10814 time = this._time; 10815 } 10816 var labels = this.getLabelsArray(), 10817 i = labels.length; 10818 while (--i > -1) { 10819 if (labels[i].time < time) { 10820 return labels[i].name; 10821 } 10822 } 10823 return null; 10824 }; 10825 p.getLabelsArray = function () { 10826 var a = [], 10827 cnt = 0, 10828 p; 10829 for (p in this._labels) { 10830 a[cnt++] = { 10831 time: this._labels[p], 10832 name: p 10833 }; 10834 } 10835 a.sort(function (a, b) { 10836 return a.time - b.time; 10837 }); 10838 return a; 10839 }; 10840 p.invalidate = function () { 10841 this._locked = false; //unlock and set cycle in case invalidate() is called from inside an onRepeat 10842 return TimelineLite.prototype.invalidate.call(this); 10843 }; 10844 10845 //---- GETTERS / SETTERS ------------------------------------------------------------------------------------------------------- 10846 10847 p.progress = function (value, suppressEvents) { 10848 return !arguments.length ? this._time / this.duration() || 0 : this.totalTime(this.duration() * (this._yoyo && (this._cycle & 1) !== 0 ? 1 - value : value) + this._cycle * (this._duration + this._repeatDelay), suppressEvents); 10849 }; 10850 p.totalProgress = function (value, suppressEvents) { 10851 return !arguments.length ? this._totalTime / this.totalDuration() || 0 : this.totalTime(this.totalDuration() * value, suppressEvents); 10852 }; 10853 p.totalDuration = function (value) { 10854 if (!arguments.length) { 10855 if (this._dirty) { 10856 TimelineLite.prototype.totalDuration.call(this); //just forces refresh 10857 //Instead of Infinity, we use 999999999999 so that we can accommodate reverses. 10858 this._totalDuration = this._repeat === -1 ? 999999999999 : this._duration * (this._repeat + 1) + this._repeatDelay * this._repeat; 10859 } 10860 return this._totalDuration; 10861 } 10862 return this._repeat === -1 || !value ? this : this.timeScale(this.totalDuration() / value); 10863 }; 10864 p.time = function (value, suppressEvents) { 10865 if (!arguments.length) { 10866 return this._time; 10867 } 10868 if (this._dirty) { 10869 this.totalDuration(); 10870 } 10871 if (value > this._duration) { 10872 value = this._duration; 10873 } 10874 if (this._yoyo && (this._cycle & 1) !== 0) { 10875 value = this._duration - value + this._cycle * (this._duration + this._repeatDelay); 10876 } else if (this._repeat !== 0) { 10877 value += this._cycle * (this._duration + this._repeatDelay); 10878 } 10879 return this.totalTime(value, suppressEvents); 10880 }; 10881 p.repeat = function (value) { 10882 if (!arguments.length) { 10883 return this._repeat; 10884 } 10885 this._repeat = value; 10886 return this._uncache(true); 10887 }; 10888 p.repeatDelay = function (value) { 10889 if (!arguments.length) { 10890 return this._repeatDelay; 10891 } 10892 this._repeatDelay = value; 10893 return this._uncache(true); 10894 }; 10895 p.yoyo = function (value) { 10896 if (!arguments.length) { 10897 return this._yoyo; 10898 } 10899 this._yoyo = value; 10900 return this; 10901 }; 10902 p.currentLabel = function (value) { 10903 if (!arguments.length) { 10904 return this.getLabelBefore(this._time + 0.00000001); 10905 } 10906 return this.seek(value, true); 10907 }; 10908 return TimelineMax; 10909 }, true); 10910 10911 /* 10912 * ---------------------------------------------------------------- 10913 * BezierPlugin 10914 * ---------------------------------------------------------------- 10915 */ 10916 (function () { 10917 var _RAD2DEG = 180 / Math.PI, 10918 _r1 = [], 10919 _r2 = [], 10920 _r3 = [], 10921 _corProps = {}, 10922 _globals = _gsScope._gsDefine.globals, 10923 Segment = function Segment(a, b, c, d) { 10924 if (c === d) { 10925 //if c and d match, the final autoRotate value could lock at -90 degrees, so differentiate them slightly. 10926 c = d - (d - b) / 1000000; 10927 } 10928 if (a === b) { 10929 //if a and b match, the starting autoRotate value could lock at -90 degrees, so differentiate them slightly. 10930 b = a + (c - a) / 1000000; 10931 } 10932 this.a = a; 10933 this.b = b; 10934 this.c = c; 10935 this.d = d; 10936 this.da = d - a; 10937 this.ca = c - a; 10938 this.ba = b - a; 10939 }, 10940 _correlate = ",x,y,z,left,top,right,bottom,marginTop,marginLeft,marginRight,marginBottom,paddingLeft,paddingTop,paddingRight,paddingBottom,backgroundPosition,backgroundPosition_y,", 10941 cubicToQuadratic = function cubicToQuadratic(a, b, c, d) { 10942 var q1 = { 10943 a: a 10944 }, 10945 q2 = {}, 10946 q3 = {}, 10947 q4 = { 10948 c: d 10949 }, 10950 mab = (a + b) / 2, 10951 mbc = (b + c) / 2, 10952 mcd = (c + d) / 2, 10953 mabc = (mab + mbc) / 2, 10954 mbcd = (mbc + mcd) / 2, 10955 m8 = (mbcd - mabc) / 8; 10956 q1.b = mab + (a - mab) / 4; 10957 q2.b = mabc + m8; 10958 q1.c = q2.a = (q1.b + q2.b) / 2; 10959 q2.c = q3.a = (mabc + mbcd) / 2; 10960 q3.b = mbcd - m8; 10961 q4.b = mcd + (d - mcd) / 4; 10962 q3.c = q4.a = (q3.b + q4.b) / 2; 10963 return [q1, q2, q3, q4]; 10964 }, 10965 _calculateControlPoints = function _calculateControlPoints(a, curviness, quad, basic, correlate) { 10966 var l = a.length - 1, 10967 ii = 0, 10968 cp1 = a[0].a, 10969 i, 10970 p1, 10971 p2, 10972 p3, 10973 seg, 10974 m1, 10975 m2, 10976 mm, 10977 cp2, 10978 qb, 10979 r1, 10980 r2, 10981 tl; 10982 for (i = 0; i < l; i++) { 10983 seg = a[ii]; 10984 p1 = seg.a; 10985 p2 = seg.d; 10986 p3 = a[ii + 1].d; 10987 if (correlate) { 10988 r1 = _r1[i]; 10989 r2 = _r2[i]; 10990 tl = (r2 + r1) * curviness * 0.25 / (basic ? 0.5 : _r3[i] || 0.5); 10991 m1 = p2 - (p2 - p1) * (basic ? curviness * 0.5 : r1 !== 0 ? tl / r1 : 0); 10992 m2 = p2 + (p3 - p2) * (basic ? curviness * 0.5 : r2 !== 0 ? tl / r2 : 0); 10993 mm = p2 - (m1 + ((m2 - m1) * (r1 * 3 / (r1 + r2) + 0.5) / 4 || 0)); 10994 } else { 10995 m1 = p2 - (p2 - p1) * curviness * 0.5; 10996 m2 = p2 + (p3 - p2) * curviness * 0.5; 10997 mm = p2 - (m1 + m2) / 2; 10998 } 10999 m1 += mm; 11000 m2 += mm; 11001 seg.c = cp2 = m1; 11002 if (i !== 0) { 11003 seg.b = cp1; 11004 } else { 11005 seg.b = cp1 = seg.a + (seg.c - seg.a) * 0.6; //instead of placing b on a exactly, we move it inline with c so that if the user specifies an ease like Back.easeIn or Elastic.easeIn which goes BEYOND the beginning, it will do so smoothly. 11006 } 11007 seg.da = p2 - p1; 11008 seg.ca = cp2 - p1; 11009 seg.ba = cp1 - p1; 11010 if (quad) { 11011 qb = cubicToQuadratic(p1, cp1, cp2, p2); 11012 a.splice(ii, 1, qb[0], qb[1], qb[2], qb[3]); 11013 ii += 4; 11014 } else { 11015 ii++; 11016 } 11017 cp1 = m2; 11018 } 11019 seg = a[ii]; 11020 seg.b = cp1; 11021 seg.c = cp1 + (seg.d - cp1) * 0.4; //instead of placing c on d exactly, we move it inline with b so that if the user specifies an ease like Back.easeOut or Elastic.easeOut which goes BEYOND the end, it will do so smoothly. 11022 seg.da = seg.d - seg.a; 11023 seg.ca = seg.c - seg.a; 11024 seg.ba = cp1 - seg.a; 11025 if (quad) { 11026 qb = cubicToQuadratic(seg.a, cp1, seg.c, seg.d); 11027 a.splice(ii, 1, qb[0], qb[1], qb[2], qb[3]); 11028 } 11029 }, 11030 _parseAnchors = function _parseAnchors(values, p, correlate, prepend) { 11031 var a = [], 11032 l, 11033 i, 11034 p1, 11035 p2, 11036 p3, 11037 tmp; 11038 if (prepend) {
11039 values = [prepend].concat(values); 11040 i = values.length; 11041 while (--i > -1) { 11042 if (typeof (tmp = values[i][p]) === "string") if (tmp.charAt(1) === "=") { 11043 values[i][p] = prepend[p] + Number(tmp.charAt(0) + tmp.substr(2)); //accommodate relative values. Do it inline instead of breaking it out into a function for speed reasons 11044 } 11045 } 11046 } 11047 l = values.length - 2; 11048 if (l < 0) { 11049 a[0] = new Segment(values[0][p], 0, 0, values[0][p]); 11050 return a; 11051 } 11052 for (i = 0; i < l; i++) { 11053 p1 = values[i][p]; 11054 p2 = values[i + 1][p]; 11055 a[i] = new Segment(p1, 0, 0, p2); 11056 if (correlate) { 11057 p3 = values[i + 2][p]; 11058 _r1[i] = (_r1[i] || 0) + (p2 - p1) * (p2 - p1); 11059 _r2[i] = (_r2[i] || 0) + (p3 - p2) * (p3 - p2); 11060 } 11061 } 11062 a[i] = new Segment(values[i][p], 0, 0, values[i + 1][p]); 11063 return a; 11064 }, 11065 bezierThrough = function bezierThrough(values, curviness, quadratic, basic, correlate, prepend) { 11066 var obj = {}, 11067 props = [], 11068 first = prepend || values[0], 11069 i, 11070 p, 11071 a, 11072 j, 11073 r, 11074 l, 11075 seamless, 11076 last; 11077 correlate = typeof correlate === "string" ? "," + correlate + "," : _correlate; 11078 if (curviness == null) { 11079 curviness = 1; 11080 } 11081 for (p in values[0]) { 11082 props.push(p); 11083 } 11084 //check to see if the last and first values are identical (well, within 0.05). If so, make seamless by appending the second element to the very end of the values array and the 2nd-to-last element to the very beginning (we'll remove those segments later) 11085 if (values.length > 1) { 11086 last = values[values.length - 1]; 11087 seamless = true; 11088 i = props.length; 11089 while (--i > -1) { 11090 p = props[i]; 11091 if (Math.abs(first[p] - last[p]) > 0.05) { 11092 //build in a tolerance of +/-0.05 to accommodate rounding errors. 11093 seamless = false; 11094 break; 11095 } 11096 } 11097 if (seamless) { 11098 values = values.concat(); //duplicate the array to avoid contaminating the original which the user may be reusing for other tweens 11099 if (prepend) { 11100 values.unshift(prepend); 11101 } 11102 values.push(values[1]); 11103 prepend = values[values.length - 3]; 11104 } 11105 } 11106 _r1.length = _r2.length = _r3.length = 0; 11107 i = props.length; 11108 while (--i > -1) { 11109 p = props[i]; 11110 _corProps[p] = correlate.indexOf("," + p + ",") !== -1; 11111 obj[p] = _parseAnchors(values, p, _corProps[p], prepend); 11112 } 11113 i = _r1.length; 11114 while (--i > -1) { 11115 _r1[i] = Math.sqrt(_r1[i]); 11116 _r2[i] = Math.sqrt(_r2[i]); 11117 } 11118 if (!basic) { 11119 i = props.length; 11120 while (--i > -1) { 11121 if (_corProps[p]) { 11122 a = obj[props[i]]; 11123 l = a.length - 1; 11124 for (j = 0; j < l; j++) { 11125 r = a[j + 1].da / _r2[j] + a[j].da / _r1[j] || 0; 11126 _r3[j] = (_r3[j] || 0) + r * r; 11127 } 11128 } 11129 } 11130 i = _r3.length; 11131 while (--i > -1) { 11132 _r3[i] = Math.sqrt(_r3[i]); 11133 } 11134 } 11135 i = props.length; 11136 j = quadratic ? 4 : 1; 11137 while (--i > -1) { 11138 p = props[i]; 11139 a = obj[p]; 11140 _calculateControlPoints(a, curviness, quadratic, basic, _corProps[p]); //this method requires that _parseAnchors() and _setSegmentRatios() ran first so that _r1, _r2, and _r3 values are populated for all properties 11141 if (seamless) { 11142 a.splice(0, j); 11143 a.splice(a.length - j, j); 11144 } 11145 } 11146 return obj; 11147 }, 11148 _parseBezierData = function _parseBezierData(values, type, prepend) { 11149 type = type || "soft"; 11150 var obj = {}, 11151 inc = type === "cubic" ? 3 : 2, 11152 soft = type === "soft", 11153 props = [], 11154 a, 11155 b, 11156 c, 11157 d, 11158 cur, 11159 i, 11160 j, 11161 l, 11162 p, 11163 cnt, 11164 tmp; 11165 if (soft && prepend) {
11166 values = [prepend].concat(values); 11167 } 11168 if (values == null || values.length < inc + 1) { 11169 throw "invalid Bezier data"; 11170 } 11171 for (p in values[0]) { 11172 props.push(p); 11173 } 11174 i = props.length; 11175 while (--i > -1) { 11176 p = props[i]; 11177 obj[p] = cur = []; 11178 cnt = 0; 11179 l = values.length; 11180 for (j = 0; j < l; j++) { 11181 a = prepend == null ? values[j][p] : typeof (tmp = values[j][p]) === "string" && tmp.charAt(1) === "=" ? prepend[p] + Number(tmp.charAt(0) + tmp.substr(2)) : Number(tmp); 11182 if (soft) if (j > 1) if (j < l - 1) { 11183 cur[cnt++] = (a + cur[cnt - 2]) / 2; 11184 } 11185 cur[cnt++] = a; 11186 } 11187 l = cnt - inc + 1; 11188 cnt = 0; 11189 for (j = 0; j < l; j += inc) { 11190 a = cur[j]; 11191 b = cur[j + 1]; 11192 c = cur[j + 2]; 11193 d = inc === 2 ? 0 : cur[j + 3]; 11194 cur[cnt++] = tmp = inc === 3 ? new Segment(a, b, c, d) : new Segment(a, (2 * b + a) / 3, (2 * b + c) / 3, c); 11195 } 11196 cur.length = cnt; 11197 } 11198 return obj; 11199 }, 11200 _addCubicLengths = function _addCubicLengths(a, steps, resolution) { 11201 var inc = 1 / resolution, 11202 j = a.length, 11203 d, 11204 d1, 11205 s, 11206 da, 11207 ca, 11208 ba, 11209 p, 11210 i, 11211 inv, 11212 bez, 11213 index; 11214 while (--j > -1) { 11215 bez = a[j]; 11216 s = bez.a; 11217 da = bez.d - s; 11218 ca = bez.c - s; 11219 ba = bez.b - s; 11220 d = d1 = 0; 11221 for (i = 1; i <= resolution; i++) { 11222 p = inc * i; 11223 inv = 1 - p; 11224 d = d1 - (d1 = (p * p * da + 3 * inv * (p * ca + inv * ba)) * p); 11225 index = j * resolution + i - 1; 11226 steps[index] = (steps[index] || 0) + d * d; 11227 } 11228 } 11229 }, 11230 _parseLengthData = function _parseLengthData(obj, resolution) { 11231 resolution = resolution >> 0 || 6; 11232 var a = [], 11233 lengths = [], 11234 d = 0, 11235 total = 0, 11236 threshold = resolution - 1, 11237 segments = [], 11238 curLS = [], 11239 //current length segments array 11240 p, 11241 i, 11242 l, 11243 index; 11244 for (p in obj) { 11245 _addCubicLengths(obj[p], a, resolution); 11246 } 11247 l = a.length; 11248 for (i = 0; i < l; i++) { 11249 d += Math.sqrt(a[i]); 11250 index = i % resolution; 11251 curLS[index] = d; 11252 if (index === threshold) { 11253 total += d; 11254 index = i / resolution >> 0; 11255 segments[index] = curLS; 11256 lengths[index] = total; 11257 d = 0; 11258 curLS = []; 11259 } 11260 } 11261 return { 11262 length: total, 11263 lengths: lengths, 11264 segments: segments 11265 }; 11266 }, 11267 BezierPlugin = _gsScope._gsDefine.plugin({ 11268 propName: "bezier", 11269 priority: -1, 11270 version: "1.3.8", 11271 API: 2, 11272 global: true, 11273 //gets called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run. 11274 init: function init(target, vars, tween) { 11275 this._target = target; 11276 if (vars instanceof Array) { 11277 vars = { 11278 values: vars 11279 }; 11280 } 11281 this._func = {}; 11282 this._mod = {}; 11283 this._props = []; 11284 this._timeRes = vars.timeResolution == null ? 6 : parseInt(vars.timeResolution, 10); 11285 var values = vars.values || [], 11286 first = {}, 11287 second = values[0], 11288 autoRotate = vars.autoRotate || tween.vars.orientToBezier, 11289 p, 11290 isFunc, 11291 i, 11292 j, 11293 prepend; 11294 this._autoRotate = autoRotate ? autoRotate instanceof Array ? autoRotate : [["x", "y", "rotation", autoRotate === true ? 0 : Number(autoRotate) || 0]] : null; 11295 for (p in second) { 11296 this._props.push(p); 11297 } 11298 i = this._props.length; 11299 while (--i > -1) { 11300 p = this._props[i]; 11301 this._overwriteProps.push(p); 11302 isFunc = this._func[p] = typeof target[p] === "function"; 11303 first[p] = !isFunc ? parseFloat(target[p]) : target[p.indexOf("set") || typeof target["get" + p.substr(3)] !== "function" ? p : "get" + p.substr(3)](); 11304 if (!prepend) if (first[p] !== values[0][p]) { 11305 prepend = first; 11306 } 11307 } 11308 this._beziers = vars.type !== "cubic" && vars.type !== "quadratic" && vars.type !== "soft" ? bezierThrough(values, isNaN(vars.curviness) ? 1 : vars.curviness, false, vars.type === "thruBasic", vars.c
11308orrelate, prepend) : _parseBezierData(values, vars.type, first); 11309 this._segCount = this._beziers[p].length; 11310 if (this._timeRes) { 11311 var ld = _parseLengthData(this._beziers, this._timeRes); 11312 this._length = ld.length; 11313 this._lengths = ld.lengths; 11314 this._segments = ld.segments; 11315 this._l1 = this._li = this._s1 = this._si = 0; 11316 this._l2 = this._lengths[0]; 11317 this._curSeg = this._segments[0]; 11318 this._s2 = this._curSeg[0]; 11319 this._prec = 1 / this._curSeg.length; 11320 } 11321 if (autoRotate = this._autoRotate) { 11322 this._initialRotations = []; 11323 if (!(autoRotate[0] instanceof Array)) { 11324 this._autoRotate = autoRotate = [autoRotate]; 11325 } 11326 i = autoRotate.length; 11327 while (--i > -1) { 11328 for (j = 0; j < 3; j++) { 11329 p = autoRotate[i][j]; 11330 this._func[p] = typeof target[p] === "function" ? target[p.indexOf("set") || typeof target["get" + p.substr(3)] !== "function" ? p : "get" + p.substr(3)] : false; 11331 } 11332 p = autoRotate[i][2]; 11333 this._initialRotations[i] = (this._func[p] ? this._func[p].call(this._target) : this._target[p]) || 0; 11334 this._overwriteProps.push(p); 11335 } 11336 } 11337 this._startRatio = tween.vars.runBackwards ? 1 : 0; //we determine the starting ratio when the tween inits which is always 0 unless the tween has runBackwards:true (indicating it's a from() tween) in which case it's 1. 11338 return true; 11339 }, 11340 //called each time the values should be updated, and the ratio gets passed as the only parameter (typically it's a value between 0 and 1, but it can exceed those when using an ease like Elastic.easeOut or Back.easeOut, etc.) 11341 set: function set(v) { 11342 var segments = this._segCount, 11343 func = this._func, 11344 target = this._target, 11345 notStart = v !== this._startRatio, 11346 curIndex, 11347 inv, 11348 i, 11349 p, 11350 b, 11351 t, 11352 val, 11353 l, 11354 lengths, 11355 curSeg; 11356 if (!this._timeRes) { 11357 curIndex = v < 0 ? 0 : v >= 1 ? segments - 1 : segments * v >> 0; 11358 t = (v - curIndex * (1 / segments)) * segments; 11359 } else { 11360 lengths = this._lengths; 11361 curSeg = this._curSeg; 11362 v *= this._length; 11363 i = this._li; 11364 //find the appropriate segment (if the currently cached one isn't correct) 11365 if (v > this._l2 && i < segments - 1) { 11366 l = segments - 1; 11367 while (i < l && (this._l2 = lengths[++i]) <= v) {} 11368 this._l1 = lengths[i - 1]; 11369 this._li = i; 11370 this._curSeg = curSeg = this._segments[i]; 11371 this._s2 = curSeg[this._s1 = this._si = 0]; 11372 } else if (v < this._l1 && i > 0) { 11373 while (i > 0 && (this._l1 = lengths[--i]) >= v) {} 11374 if (i === 0 && v < this._l1) { 11375 this._l1 = 0; 11376 } else { 11377 i++; 11378 } 11379 this._l2 = lengths[i]; 11380 this._li = i; 11381 this._curSeg = curSeg = this._segments[i]; 11382 this._s1 = curSeg[(this._si = curSeg.length - 1) - 1] || 0; 11383 this._s2 = curSeg[this._si]; 11384 } 11385 curIndex = i; 11386 //now find the appropriate sub-segment (we split it into the number of pieces that was defined by "precision" and measured each one) 11387 v -= this._l1; 11388 i = this._si; 11389 if (v > this._s2 && i < curSeg.length - 1) { 11390 l = curSeg.length - 1; 11391 while (i < l && (this._s2 = curSeg[++i]) <= v) {} 11392 this._s1 = curSeg[i - 1]; 11393 this._si = i; 11394 } else if (v < this._s1 && i > 0) { 11395 while (i > 0 && (this._s1 = curSeg[--i]) >= v) {} 11396 if (i === 0 && v < this._s1) { 11397 this._s1 = 0; 11398 } else { 11399 i++; 11400 } 11401 this._s2 = curSeg[i]; 11402 this._si = i; 11403 } 11404 t = (i + (v - this._s1) / (this._s2 - this._s1)) * this._prec || 0; 11405 } 11406 inv = 1 - t; 11407 i = this._props.length; 11408 while (--i > -1) { 11409 p = this._props[i]; 11410 b = this._beziers[p][curIndex]; 11411 val = (t * t * b.da + 3 * inv * (t * b.ca + inv * b.ba)) * t + b.a; 11412 if (this._mod[p]) { 11413 val = this._mod[p](val, target); 11414 } 11415 if (func[p]) { 11416 target[p](val); 11417 } else { 11418 target[p] = val; 11419 } 11420 } 11421 if (this._autoRotate) { 11422 var ar = this._autoRotate, 11423 b2, 11424 x1, 11425 y1, 11426 x2, 11427 y2, 11428 add, 11429 conv; 11430 i = ar.length; 11431 while (--i > -1) { 11432 p = ar[i][2]; 11433 add = ar[i][3] || 0; 11434 conv = ar[i][4] === true ? 1 : _RAD2DEG; 11435 b = this._beziers[ar[i][0]]; 11436 b2 = this._beziers[ar[i][1]]; 11437 if (b && b2) { 11438 //in case one of the properties got overwritten. 11439 b = b[curIndex]; 11440 b2 = b2[curIndex]; 11441 x1 = b.a + (b.b - b.a) * t; 11442 x2 = b.b + (b.c - b.b) * t; 11443 x1 += (x2 - x1) * t; 11444 x2 += (b.c + (b.d - b.c) * t - x2) * t; 11445 y1 = b2.a + (b2.b - b2.a) * t; 11446 y2 = b2.b + (b2.c - b2.b) * t; 11447 y1 += (y2 - y1) * t; 11448 y2 += (b2.c + (b2.d - b2.c) * t - y2) * t; 11449 val = notStart ? Math.atan2(y2 - y1, x2 - x1) * conv + add : this._initialRotations[i]; 11450 if (this._mod[p]) { 11451 val = this._mod[p](val, target); //for modProps 11452 } 11453 if (func[p]) { 11454 target[p](val); 11455 } else { 11456 target[p] = val; 11457 } 11458 } 11459 } 11460 } 11461 } 11462 }), 11463 p = BezierPlugin.prototype; 11464 BezierPlugin.bezierThrough = bezierThrough; 11465 BezierPlugin.cubicToQuadratic = cubicToQuadratic; 11466 BezierPlugin._autoCSS = true; //indicates that this plugin can be inserted into the "css" object using the autoCSS feature of TweenLite 11467 BezierPlugin.quadraticToCubic = function (a, b, c) { 11468 return new Segment(a, (2 * b + a) / 3, (2 * b + c) / 3, c); 11469 }; 11470 BezierPlugin._cssRegister = function () { 11471 var CSSPlugin = _globals.CSSPlugin; 11472 if (!CSSPlugin) { 11473 return; 11474 } 11475 var _internals = CSSPlugin._internals, 11476 _parseToProxy = _internals._parseToProxy, 11477 _setPluginRatio = _internals._setPluginRatio, 11478 CSSPropTween = _internals.CSSPropTween; 11479 _internals._registerComplexSpecialProp("bezier", { 11480 parser: function parser(t, e, prop, cssp, pt, plugin) { 11481 if (e instanceof Array) { 11482 e = { 11483 values: e 11484 }; 11485 } 11486 plugin = new BezierPlugin(); 11487 var values = e.values, 11488 l = values.length - 1, 11489 pluginValues = [], 11490 v = {}, 11491 i, 11492 p, 11493 data; 11494 if (l < 0) { 11495 return pt; 11496 } 11497 for (i = 0; i <= l; i++) { 11498 data = _parseToProxy(t, values[i], cssp, pt, plugin, l !== i); 11499 pluginValues[i] = data.end; 11500 } 11501 for (p in e) { 11502 v[p] = e[p]; //duplicate the vars object because we need to alter some things which w
11502ould cause problems if the user plans to reuse the same vars object for another tween. 11503 } 11504 v.values = pluginValues; 11505 pt = new CSSPropTween(t, "bezier", 0, 0, data.pt, 2); 11506 pt.data = data; 11507 pt.plugin = plugin; 11508 pt.setRatio = _setPluginRatio; 11509 if (v.autoRotate === 0) { 11510 v.autoRotate = true; 11511 } 11512 if (v.autoRotate && !(v.autoRotate instanceof Array)) { 11513 i = v.autoRotate === true ? 0 : Number(v.autoRotate); 11514 v.autoRotate = data.end.left != null ? [["left", "top", "rotation", i, false]] : data.end.x != null ? [["x", "y", "rotation", i, false]] : false; 11515 } 11516 if (v.autoRotate) { 11517 if (!cssp._transform) { 11518 cssp._enableTransforms(false); 11519 } 11520 data.autoRotate = cssp._target._gsTransform; 11521 data.proxy.rotation = data.autoRotate.rotation || 0; 11522 cssp._overwriteProps.push("rotation"); 11523 } 11524 plugin._onInitTween(data.proxy, v, cssp._tween); 11525 return pt; 11526 } 11527 }); 11528 }; 11529 p._mod = function (lookup) { 11530 var op = this._overwriteProps, 11531 i = op.length, 11532 val; 11533 while (--i > -1) { 11534 val = lookup[op[i]]; 11535 if (val && typeof val === "function") { 11536 this._mod[op[i]] = val; 11537 } 11538 } 11539 }; 11540 p._kill = function (lookup) { 11541 var a = this._props, 11542 p, 11543 i; 11544 for (p in this._beziers) { 11545 if (p in lookup) { 11546 delete this._beziers[p]; 11547 delete this._func[p]; 11548 i = a.length; 11549 while (--i > -1) { 11550 if (a[i] === p) { 11551 a.splice(i, 1); 11552 } 11553 } 11554 } 11555 } 11556 a = this._autoRotate; 11557 if (a) { 11558 i = a.length; 11559 while (--i > -1) { 11560 if (lookup[a[i][2]]) { 11561 a.splice(i, 1); 11562 } 11563 } 11564 } 11565 return this._super._kill.call(this, lookup); 11566 }; 11567 })(); 11568 11569 /* 11570 * ---------------------------------------------------------------- 11571 * CSSPlugin 11572 * ---------------------------------------------------------------- 11573 */ 11574 _gsScope._gsDefine("plugins.CSSPlugin", ["plugins.TweenPlugin", "TweenLite"], function (TweenPlugin, TweenLite) { 11575 /** @constructor **/ 11576 var _CSSPlugin = function CSSPlugin() { 11577 TweenPlugin.call(this, "css"); 11578 this._overwriteProps.length = 0; 11579 this.setRatio = _CSSPlugin.prototype.setRatio; //speed optimization (avoid prototype lookup on this "hot" method) 11580 }, 11581 _globals = _gsScope._gsDefine.globals, 11582 _hasPriority, 11583 //turns true whenever a CSSPropTween instance is created that has a priority other than 0. This helps us discern whether or not we should spend the time organizing the linked list or not after a CSSPlugin's _onInitTween() method is called. 11584 _suffixMap, 11585 //we set this in _onInitTween() each time as a way to have a persistent variable we can use in other methods like _parse() without having to pass it around as a parameter and we keep _parse() decoupled from a particular CSSPlugin instance 11586 _cs, 11587 //computed style (we store this in a shared variable to conserve memory and make minification tighter 11588 _overwriteProps, 11589 //alias to the currently instantiating CSSPlugin's _overwriteProps array. We use this closure in order to avoid having to pass a reference around from method to method and aid in minification. 11590 _specialProps = {}, 11591 p = _CSSPlugin.prototype = new TweenPlugin("css"); 11592 p.constructor = _CSSPlugin; 11593 _CSSPlugin.version = "1.20.4"; 11594 _CSSPlugin.API = 2; 11595 _CSSPlugin.defaultTransformPerspective = 0; 11596 _CSSPlugin.defaultSkewType = "compensated"; 11597 _CSSPlugin.defaultSmoothOrigin = true; 11598 p = "px"; //we'll reuse the "p" variable to keep file size down 11599 _CSSPlugin.suffixMap = { 11600 top: p, 11601 right: p, 11602 bottom: p, 11603 left: p, 11604 width: p, 11605 height: p, 11606 fontSize: p, 11607 padding: p, 11608 margin: p, 11609 perspective: p, 11610 lineHeight: "" 11611 }; 11612 var _numExp = /(?:\-|\.|\b)(\d|\.|e\-)+/g, 11613 _relNumExp = /(?:\d|\-\d|\.\d|\-\.\d|\+=\d|\-=\d|\+=.\d|\-=\.\d)+/g,
11614 _valuesExp = /(?:\+=|\-=|\-|\b)[\d\-\.]+[a-zA-Z0-9]*(?:%|\b)/gi, 11615 //finds all the values that begin with numbers or += or -= and then a number. Includes suffixes. We use this to split complex values apart like "1px 5px 20px rgb(255,102,51)" 11616 _NaNExp = /(?![+-]?\d*\.?\d+|[+-]|e[+-]\d+)[^0-9]/g, 11617 //also allows scientific notation and doesn't kill the leading -/+ in -= and += 11618 _suffixExp = /(?:\d|\-|\+|=|#|\.)*/g, 11619 _opacityExp = /opacity *= *([^)]*)/i, 11620 _opacityValExp = /opacity:([^;]*)/i, 11621 _alphaFilterExp = /alpha\(opacity *=.+?\)/i, 11622 _rgbhslExp = /^(rgb|hsl)/, 11623 _capsExp = /([A-Z])/g, 11624 _camelExp = /-([a-z])/gi, 11625 _urlExp = /(^(?:url\(\"|url\())|(?:(\"\))$|\)$)/gi, 11626 //for pulling out urls from url(...) or url("...") strings (some browsers wrap urls in quotes, some don't when reporting things like backgroundImage) 11627 _camelFunc = function _camelFunc(s, g) { 11628 return g.toUpperCase(); 11629 }, 11630 _horizExp = /(?:Left|Right|Width)/i, 11631 _ieGetMatrixExp = /(M11|M12|M21|M22)=[\d\-\.e]+/gi, 11632 _ieSetMatrixExp = /progid\:DXImageTransform\.Microsoft\.Matrix\(.+?\)/i, 11633 _commasOutsideParenExp = /,(?=[^\)]*(?:\(|$))/gi, 11634 //finds any commas that are not within parenthesis 11635 _complexExp = /[\s,\(]/i, 11636 //for testing a string to find if it has a space, comma, or open parenthesis (clues that it's a complex value) 11637 _DEG2RAD = Math.PI / 180, 11638 _RAD2DEG = 180 / Math.PI, 11639 _forcePT = {}, 11640 _dummyElement = { 11641 style: {} 11642 }, 11643 _doc = _gsScope.document || { 11644 createElement: function createElement() { 11645 return _dummyElement; 11646 } 11647 }, 11648 _createElement = function _createElement(type, ns) { 11649 return _doc.createElementNS ? _doc.createElementNS(ns || "http://www.w3.org/1999/xhtml", type) : _doc.createElement(type); 11650 }, 11651 _tempDiv = _createElement("div"), 11652 _tempImg = _createElement("img"), 11653 _internals = _CSSPlugin._internals = { 11654 _specialProps: _specialProps 11655 }, 11656 //provides a hook to a few internal methods that we need to access from inside other plugins 11657 _agent = (_gsScope.navigator || {}).userAgent || "", 11658 _autoRound, 11659 _reqSafariFix, 11660 //we won't apply the Safari transform fix until we actually come across a tween that affects a transform property (to maintain best performance). 11661 11662 _isSafari, 11663 _isFirefox, 11664 //Firefox has a bug that causes 3D transformed elements to randomly disappear unless a repaint is forced after each update on each element. 11665 _isSafariLT6, 11666 //Safari (and Android 4 which uses a flavor of Safari) has a bug that prevents changes to "top" and "left" properties from rendering properly if changed on the same frame as a transform UNLESS we set the element's WebkitBackfaceVisibility to hidden (weird, I know). Doing this for Android 3 and earlier seems to actually cause other problems, though (fun!) 11667 _ieVers, 11668 _supportsOpacity = function () { 11669 //we set _isSafari, _ieVers, _isFirefox, and _supportsOpacity all in one function here to reduce file size slightly, especially in the minified version. 11670 var i = _agent.indexOf("Android"), 11671 a = _createElement("a"); 11672 _isSafari = _agent.indexOf("Safari") !== -1 && _agent.indexOf("Chrome") === -1 && (i === -1 || parseFloat(_agent.substr(i + 8, 2)) > 3); 11673 _isSafariLT6 = _isSafari && parseFloat(_agent.substr(_agent.indexOf("Version/") + 8, 2)) < 6; 11674 _isFirefox = _agent.indexOf("Firefox") !== -1; 11675 if (/MSIE ([0-9]{1,}[\.0-9]{0,})/.exec(_agent) || /Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/.exec(_agent)) { 11676 _ieVers = parseFloat(RegExp.$1); 11677 } 11678 if (!a) { 11679 return false; 11680 } 11681 a.style.cssText = "top:1px;opacity:.55;"; 11682 return /^0.55/.test(a.style.opacity); 11683 }(), 11684 _getIEOpacity = function _getIEOpacity(v) { 11685 return _opacityExp.test(typeof v === "string" ? v : (v.currentStyle ? v.currentStyle.filter : v.style.filter) || "") ? parseFloat(RegExp.$1) / 100 : 1; 11686 }, 11687 _log = function _log(s) { 11688 //for logging messages, but in a way that won't throw errors in old versions of IE. 11689 if (_gsScope.console) { 11690 console.log(s); 11691 } 11692 }, 11693 _target, 11694 //when initting a CSSPlugin, we set this variable so that we can access it from within many other functions without having to pass it around as params 11695 _index, 11696 //when initting a CSSPlugin, we set this variable so that we can access it from within many other functions without having to pass it around as params 11697 11698 _prefixCSS = "", 11699 //the non-camelCase vendor prefix like "-o-", "-moz-", "-ms-", or "-webkit-" 11700 _prefix = "", 11701 //camelCase vendor prefix like "O", "ms", "Webkit", or "Moz". 11702 11703 // @private feed in a camelCase property name like "transform" and it will check to see if it is valid as-is or if it needs a vendor prefix. It returns the corrected camelCase property name (i.e. "WebkitTransform" or "MozTransform" or "transform" or null if no such property is found, like if the browser is IE8 or before, "transform" won't be found at all) 11704 _checkPropPrefix = function _checkPropPrefix(p, e) { 11705 e = e || _tempDiv; 11706 var s = e.style, 11707 a, 11708 i; 11709 if (s[p] !== undefined) { 11710 return p; 11711 } 11712 p = p.charAt(0).toUpperCase() + p.substr(1); 11713 a = ["O", "Moz", "ms", "Ms", "Webkit"]; 11714 i = 5; 11715 while (--i > -1 && s[a[i] + p] === undefined) {} 11716 if (i >= 0) { 11717 _prefix = i === 3 ? "ms" : a[i]; 11718 _prefixCSS = "-" + _prefix.toLowerCase() + "-"; 11719 return _prefix + p; 11720 } 11721 return null; 11722 }, 11723 _getComputedStyle = _doc.defaultView ? _doc.defaultView.getComputedStyle : function () {}, 11724 /** 11725 * @private Returns the css style for a particular property of an element. For example, to get whatever the current "left" css value for an element with an ID of "myElement", you could do: 11726 * var currentLeft = CSSPlugin.getStyle( document.getElementById("myElement"), "left"); 11727 * 11728 * @param {!Object} t Target element whose style property you want to query 11729 * @param {!string} p Property name (like "left" or "top" or "marginTop", etc.) 11730 * @param {Object=} cs Computed style object. This just provides a way to speed processing if you're going to get several properties on the same element in quick succession - you can reuse the result of the getComputedStyle() call. 11731 * @param {boolean=} calc If true, the value will not be read directly from the element's "style" property (if it exists there), but instead the getComputedStyle() result will be used. This can be useful when you want to ensure that the browser itself is interpreting the value. 11732 * @param {string=} dflt Default value that should be returned in the place of null, "none", "auto" or "auto auto". 11733 * @return {?string} The current property value 11734 */ 11735 _getStyle = _CSSPlugin.getStyle = function (t, p, cs, calc, dflt) { 11736 var rv; 11737 if (!_supportsOpacity) if (p === "opacity") { 11738 //several versions of IE don't use the standard "opacity" property - they use things like filter:alpha(opacity=50), so we parse that here. 11739 return _getIEOpacity(t); 11740 } 11741 if (!calc && t.style[p]) { 11742 rv = t.style[p]; 11743 } else if (cs = cs || _getComputedStyle(t)) { 11744 rv = cs[p] || cs.getPropertyValue(p) || cs.getPropertyValue(p.replace(_capsExp, "-$1").toLowerCase()); 11745 } else if (t.currentStyle) { 11746 rv = t.currentStyle[p]; 11747 } 11748 return dflt != null && (!rv || rv === "none" || rv === "auto" || rv === "auto auto") ? dflt : rv; 11749 }, 11750 /** 11751 * @private Pass the target element, the property name, the numeric value, and the suffix (like "%", "em", "px", etc.) and it will spit back the equivalent pixel number. 11752 * @param {!Object} t Target element 11753 * @param {!string} p Property name (like "left", "top", "marginLeft", etc.) 11754 * @param {!number} v Value 11755 * @param {string=} sfx Suffix (like "px" or "%" or "em") 11756 * @param {boolean=} recurse If true, the call is a recursive one. In some browsers (like IE7/8), occasionally the value isn't accurately reported initially, but if we run the function again it will take effect. 11757 * @return {number} value in pixels 11758 */ 11759 _convertToPixels = _internals.convertToPixels = function (t, p, v, sfx, recurse) { 11760 if (sfx === "px" || !sfx && p !== "lineHeight") { 11761 return v; 11762 } 11763 if (sfx === "auto" || !v) { 11764 return 0; 11765 } 11766 var horiz = _horizExp.test(p), 11767 node = t, 11768 style = _tempDiv.style, 11769 neg = v < 0, 11770 precise = v === 1, 11771 pix, 11772 cache, 11773 time; 11774 if (neg) { 11775 v = -v; 11776 } 11777 if (precise) { 11778 v *= 100; 11779 } 11780 if (p === "lineHeight" && !sfx) { 11781 //special case of when a simple lineHeight (without a unit) is used. Set it to the value, read back the computed value, and then revert. 11782 cache = _getComputedStyle(t).lineHeight; 11783 t.style.lineHeight = v; 11784 pix = parseFloat(_getComputedStyle(t).lineHeight); 11785 t.style.lineHeight = cache; 11786 } else if (sfx === "%" && p.indexOf("border") !== -1) { 11787 pix = v / 100 * (horiz ? t.clientWidth : t.clientHeight); 11788 } else { 11789 style.cssText = "border:0 solid red;position:" + _getStyle(t, "position") + ";line-height:0;"; 11790 if (sfx === "%" || !node.appendChild || sfx.charAt(0) === "v" || sfx === "rem") { 11791 node = t.parentNode || _doc.body; 11792 if (_getStyle(node, "display").indexOf("flex") !== -1) { 11793 //Edge and IE11 have a bug that causes offsetWidth to report as 0 if the container has display:flex and the child is position:relative. Switching to position: absolute solves it. 11794 style.position = "absolute"; 11795 } 11796 cache = node._gsCache; 11797 time = TweenLite.ticker.frame; 11798 if (cache && horiz && cache.time === time) { 11799 //performance optimization: we record the width of elements along with the ticker frame so that we can quickly get it again on the same tick (seems relatively safe to assume it wouldn't change on the same tick) 11800 return cache.width * v / 100; 11801 } 11802 style[horiz ? "width" : "height"] = v + sfx; 11803 } else { 11804 style[horiz ? "borderLeftWidth" : "borderTopWidth"] = v + sfx; 11805 } 11806 node.appendChild(_tempDiv); 11807 pix = parseFloat(_tempDiv[horiz ? "offsetWidth" : "offsetHeight"]); 11808 node.removeChild(_tempDiv); 11809 if (horiz && sfx === "%" && _CSSPlugin.cacheWidths !== false) { 11810 cache = node._gsCache = node._gsCache || {}; 11811 cache.time = time; 11812 cache.width = pix / v * 100; 11813 } 11814 if (pix === 0 && !recurse) { 11815 pix = _convertToPixels(t, p, v, sfx, true); 11816 } 11817 } 11818 if (precise) { 11819 pix /= 100; 11820 } 11821 return neg ? -pix : pix; 11822 }, 11823 _calculateOffset = _internals.calculateOffset = function (t, p, cs) { 11824 //for figuring out "top" or "left" in px when it's "auto". We need to factor in margin with the offsetLeft/offsetTop 11825 if (_getStyle(t, "position", cs) !== "absolute") { 11826 return 0; 11827 } 11828 var dim = p === "left" ? "Left" : "Top",
11829 v = _getStyle(t, "margin" + dim, cs); 11830 return t["offset" + dim] - (_convertToPixels(t, p, parseFloat(v), v.replace(_suffixExp, "")) || 0); 11831 }, 11832 // @private returns at object containing ALL of the style properties in camelCase and their associated values. 11833 _getAllStyles = function _getAllStyles(t, cs) { 11834 var s = {}, 11835 i, 11836 tr, 11837 p; 11838 if (cs = cs || _getComputedStyle(t, null)) { 11839 if (i = cs.length) { 11840 while (--i > -1) { 11841 p = cs[i]; 11842 if (p.indexOf("-transform") === -1 || _transformPropCSS === p) { 11843 //Some webkit browsers duplicate transform values, one non-prefixed and one prefixed ("transform" and "WebkitTransform"), so we must weed out the extra one here. 11844 s[p.replace(_camelExp, _camelFunc)] = cs.getPropertyValue(p); 11845 } 11846 } 11847 } else { 11848 //some browsers behave differently - cs.length is always 0, so we must do a for...in loop. 11849 for (i in cs) { 11850 if (i.indexOf("Transform") === -1 || _transformProp === i) { 11851 //Some webkit browsers duplicate transform values, one non-prefixed and one prefixed ("transform" and "WebkitTransform"), so we must weed out the extra one here. 11852 s[i] = cs[i]; 11853 } 11854 } 11855 } 11856 } else if (cs = t.currentStyle || t.style) { 11857 for (i in cs) { 11858 if (typeof i === "string" && s[i] === undefined) { 11859 s[i.replace(_camelExp, _camelFunc)] = cs[i]; 11860 } 11861 } 11862 } 11863 if (!_supportsOpacity) { 11864 s.opacity = _getIEOpacity(t); 11865 } 11866 tr = _getTransform(t, cs, false); 11867 s.rotation = tr.rotation; 11868 s.skewX = tr.skewX; 11869 s.scaleX = tr.scaleX; 11870 s.scaleY = tr.scaleY; 11871 s.x = tr.x; 11872 s.y = tr.y; 11873 if (_supports3D) { 11874 s.z = tr.z; 11875 s.rotationX = tr.rotationX; 11876 s.rotationY = tr.rotationY; 11877 s.scaleZ = tr.scaleZ; 11878 } 11879 if (s.filters) { 11880 delete s.filters; 11881 } 11882 return s; 11883 }, 11884 // @private analyzes two style objects (as returned by _getAllStyles()) and only looks for differences between them that contain tweenable values (like a number or color). It returns an object with a "difs" property which refers to an object c
11884ontaining only those isolated properties and values for tweening, and a "firstMPT" property which refers to the first MiniPropTween instance in a linked list that recorded all the starting values of the different properties so that we can revert to them at the end or beginning of the tween - we don't want the cascading to get messed up. The forceLookup parameter is an optional generic object with properties that should be forced into the results - this is necessary for className tweens that are overwriting others because imagine a scenario where a rollover/rollout adds/removes a class and the user swipes the mouse over the target SUPER fast, thus nothing actually changed yet and the subsequent comparison of the properties would indicate they match (especially when px rounding is taken into consideration), thus no tweening is necessary even though it SHOULD tween and remove those properties after the tween (otherwise the inline styles will contaminate things). See the className SpecialProp code for details. 11885 _cssDif = function _cssDif(t, s1, s2, vars, forceLookup) { 11886 var difs = {}, 11887 style = t.style, 11888 val, 11889 p, 11890 mpt; 11891 for (p in s2) { 11892 if (p !== "cssText") if (p !== "length") if (isNaN(p)) if (s1[p] !== (val = s2[p]) || forceLookup && forceLookup[p]) if (p.indexOf("Origin") === -1) if (typeof val === "number" || typeof val === "string") { 11893 difs[p] = val === "auto" && (p === "left" || p === "top") ? _calculateOffset(t, p) : (val === "" || val === "auto" || val === "none") && typeof s1[p] === "string" && s1[p].replace(_NaNExp, "") !== "" ? 0 : val; //if the ending value is defaulting ("" or "auto"), we check the starting value and if it can be parsed into a number (a string which could have a suffix too, like 700px), then we swap in 0 for "" or "auto" so that things actually tween. 11894 if (style[p] !== undefined) { 11895 //for className tweens, we must remember which properties already existed inline - the ones that didn't should be removed when the tween isn't in progress because they were only introduced to facilitate the transition between classes. 11896 mpt = new MiniPropTween(style, p, style[p], mpt); 11897 } 11898 } 11899 } 11900 if (vars) { 11901 for (p in vars) { 11902 //copy properties (except className) 11903 if (p !== "className") { 11904 difs[p] = vars[p]; 11905 } 11906 } 11907 } 11908 return { 11909 difs: difs, 11910 firstMPT: mpt 11911 }; 11912 }, 11913 _dimensions = { 11914 width: ["Left", "Right"], 11915 height: ["Top", "Bottom"] 11916 }, 11917 _margins = ["marginLeft", "marginRight", "marginTop", "marginBottom"], 11918 /** 11919 * @private Gets the width or height of an element 11920 * @param {!Object} t Target element 11921 * @param {!string} p Property name ("width" or "height") 11922 * @param {Object=} cs Computed style object (if one exists). Just a speed optimization. 11923 * @return {number} Dimension (in pixels) 11924 */ 11925 _getDimension = function _getDimension(t, p, cs) { 11926 if ((t.nodeName + "").toLowerCase() === "svg") { 11927 //Chrome no longer supports offsetWidth/offsetHeight on SVG elements. 11928 return (cs || _getComputedStyle(t))[p] || 0; 11929 } else if (t.getCTM && _isSVG(t)) { 11930 return t.getBBox()[p] || 0; 11931 } 11932 var v = parseFloat(p === "width" ? t.offsetWidth : t.offsetHeight), 11933 a = _dimensions[p], 11934 i = a.length; 11935 cs = cs || _getComputedStyle(t, null); 11936 while (--i > -1) { 11937 v -= parseFloat(_getStyle(t, "padding" + a[i], cs, true)) || 0; 11938 v -= parseFloat(_getStyle(t, "border" + a[i] + "Width", cs, true)) || 0; 11939 } 11940 return v; 11941 }, 11942 // @private Parses position-related complex strings like "top left" or "50px 10px" or "70% 20%", etc. which are used for things like transformOrigin or backgroundPosition. Optionally decorates a supplied object (recObj) with the following properties: "ox" (offsetX), "oy" (offsetY), "oxp" (if true, "ox" is a percentage not a pixel value), and "oxy" (if true, "oy" is a percentage not a pixel value) 11943 _parsePosition2 = function _parsePosition(v, recObj) { 11944 if (v === "contain" || v === "auto" || v === "auto auto") { 11945 //note: Firefox uses "auto auto" as default whereas Chrome uses "auto". 11946 return v + " "; 11947 } 11948 if (v == null || v === "") { 11949 v = "0 0"; 11950 } 11951 var a = v.split(" "), 11952 x = v.indexOf("left") !== -1 ? "0%" : v.indexOf("right") !== -1 ? "100%" : a[0], 11953 y = v.indexOf("top") !== -1 ? "0%" : v.indexOf("bottom") !== -1 ? "100%" : a[1], 11954 i; 11955 if (a.length > 3 && !recObj) { 11956 //multiple positions 11957 a = v.split(", ").join(",").split(","); 11958 v = []; 11959 for (i = 0; i < a.length; i++) { 11960 v.push(_parsePosition2(a[i])); 11961 } 11962 return v.join(","); 11963 } 11964 if (y == null) { 11965 y = x === "center" ? "50%" : "0"; 11966 } else if (y === "center") { 11967 y = "50%"; 11968 } 11969 if (x === "center" || isNaN(parseFloat(x)) && (x + "").indexOf("=") === -1) { 11970 //remember, the user could flip-flop the values and say "bottom center" or "center bottom", etc. "center" is ambiguous because it c
11970ould be used to describe horizontal or vertical, hence the isNaN(). If there's an "=" sign in the value, it's relative. 11971 x = "50%"; 11972 } 11973 v = x + " " + y + (a.length > 2 ? " " + a[2] : ""); 11974 if (recObj) { 11975 recObj.oxp = x.indexOf("%") !== -1; 11976 recObj.oyp = y.indexOf("%") !== -1; 11977 recObj.oxr = x.charAt(1) === "="; 11978 recObj.oyr = y.charAt(1) === "="; 11979 recObj.ox = parseFloat(x.replace(_NaNExp, "")); 11980 recObj.oy = parseFloat(y.replace(_NaNExp, "")); 11981 recObj.v = v; 11982 } 11983 return recObj || v; 11984 }, 11985 /** 11986 * @private Takes an ending value (typically a string, but can be a number) and a starting value and returns the change between the two, looking for relative value indicators like += and -= and it also ignores suffixes (but make sure the ending value starts with a number or +=/-= and that the starting value is a NUMBER!) 11987 * @param {(number|string)} e End value which is typically a string, but could be a number 11988 * @param {(number|string)} b Beginning value which is typically a string but could be a number 11989 * @return {number} Amount of change between the beginning and ending values (relative values that have a "+=" or "-=" are recognized) 11990 */ 11991 _parseChange = function _parseChange(e, b) { 11992 if (typeof e === "function") { 11993 e = e(_index, _target); 11994 } 11995 return typeof e === "string" && e.charAt(1) === "=" ? parseInt(e.charAt(0) + "1", 10) * parseFloat(e.substr(2)) : parseFloat(e) - parseFloat(b) || 0; 11996 }, 11997 /** 11998 * @private Takes a value and a default number, checks if the value is relative, null, or numeric and spits back a normalized number accordingly. Primarily used in the _parseTransform() function. 11999 * @param {Object} v Value to be parsed 12000 * @param {!number} d Default value (which is also used for relative calculations if "+=" or "-=" is found in the first parameter) 12001 * @return {number} Parsed value 12002 */ 12003 _parseVal = function _parseVal(v, d) { 12004 if (typeof v === "function") { 12005 v = v(_index, _target); 12006 } 12007 return v == null ? d : typeof v === "string" && v.charAt(1) === "=" ? parseInt(v.charAt(0) + "1", 10) * parseFloat(v.substr(2)) + d : parseFloat(v) || 0; 12008 }, 12009 /** 12010 * @private Translates strings like "40deg" or "40" or 40rad" or "+=40deg" or "270_short" or "-90_cw" or "+=45_ccw" to a numeric radian angle. Of course a starting/default value must be fed in too so that relative values can be calculated properly. 12011 * @param {Object} v Value to be parsed 12012 * @param {!number} d Default value (which is also used for relative calculations if "+=" or "-=" is found in the first parameter) 12013 * @param {string=} p property name for directionalEnd (optional - only used when the parsed value is directional ("_short", "_cw", or "_ccw" suffix). We need a way to store the uncompensated value so that at the end of the tween, we set it to exactly what was requested with no directional compensation). Property name would be "rotation", "rotationX", or "rotationY" 12014 * @param {Object=} directionalEnd An object that will store the raw end values for directional angles ("_short", "_cw", or "_ccw" suffix). We need a way to store the uncompensated value so that at the end of the tween, we set it to exactly what was requested with no directional compensation. 12015 * @return {number} parsed angle in radians 12016 */ 12017 _parseAngle = function _parseAngle(v, d, p, directionalEnd) { 12018 var min = 0.000001, 12019 cap, 12020 split, 12021 dif, 12022 result, 12023 isRelative; 12024 if (typeof v === "function") { 12025 v = v(_index, _target); 12026 } 12027 if (v == null) { 12028 result = d; 12029 } else if (typeof v === "number") { 12030 result = v; 12031 } else { 12032 cap = 360; 12033 split = v.split("_"); 12034 isRelative = v.charAt(1) === "="; 12035 dif = (isRelative ? parseInt(v.charAt(0) + "1", 10) * parseFloat(split[0].substr(2)) : parseFloat(split[0])
12035) * (v.indexOf("rad") === -1 ? 1 : _RAD2DEG) - (isRelative ? 0 : d); 12036 if (split.length) { 12037 if (directionalEnd) { 12038 directionalEnd[p] = d + dif; 12039 } 12040 if (v.indexOf("short") !== -1) { 12041 dif = dif % cap; 12042 if (dif !== dif % (cap / 2)) { 12043 dif = dif < 0 ? dif + cap : dif - cap; 12044 } 12045 } 12046 if (v.indexOf("_cw") !== -1 && dif < 0) { 12047 dif = (dif + cap * 9999999999) % cap - (dif / cap | 0) * cap; 12048 } else if (v.indexOf("ccw") !== -1 && dif > 0) { 12049 dif = (dif - cap * 9999999999) % cap - (dif / cap | 0) * cap; 12050 } 12051 } 12052 result = d + dif; 12053 } 12054 if (result < min && result > -min) { 12055 result = 0; 12056 } 12057 return result; 12058 }, 12059 _colorLookup = { 12060 aqua: [0, 255, 255], 12061 lime: [0, 255, 0], 12062 silver: [192, 192, 192], 12063 black: [0, 0, 0], 12064 maroon: [128, 0, 0], 12065 teal: [0, 128, 128], 12066 blue: [0, 0, 255], 12067 navy: [0, 0, 128], 12068 white: [255, 255, 255], 12069 fuchsia: [255, 0, 255], 12070 olive: [128, 128, 0], 12071 yellow: [255, 255, 0], 12072 orange: [255, 165, 0], 12073 gray: [128, 128, 128], 12074 purple: [128, 0, 128], 12075 green: [0, 128, 0], 12076 red: [255, 0, 0], 12077 pink: [255, 192, 203], 12078 cyan: [0, 255, 255], 12079 transparent: [255, 255, 255, 0] 12080 }, 12081 _hue = function _hue(h, m1, m2) { 12082 h = h < 0 ? h + 1 : h > 1 ? h - 1 : h; 12083 return (h * 6 < 1 ? m1 + (m2 - m1) * h * 6 : h < 0.5 ? m2 : h * 3 < 2 ? m1 + (m2 - m1) * (2 / 3 - h) * 6 : m1) * 255 + 0.5 | 0; 12084 }, 12085 /** 12086 * @private Parses a color (like #9F0, #FF9900, rgb(255,51,153) or hsl(108, 50%, 10%)) into an array with 3 elements for red, green, and blue or if toHSL parameter is true, it will populate the array with hue, saturation, and lightness values. If a relative value is found in an hsl() or hsla() string, it will preserve those relative prefixes and all the values in the array will be strings instead of numbers (in all other cases it will be populated with numbers). 12087 * @param {(string|number)} v The value the should be parsed which could be a string like #9F0 or rgb(255,102,51) or rgba(255,0,0,0.5) or it could be a number like 0xFF00CC or even a named color like red, blue, purple, etc. 12088 * @param {(boolean)} toHSL If true, an hsl() or hsla() value will be returned instead of rgb() or rgba() 12089 * @return {Array.<number>} An array containing red, green, and blue (and optionally alpha) in that order, or if the toHSL parameter was true, the array will contain hue, saturation and lightness (and optionally alpha) in that order. Always numbers unless there's a relative prefix found in an hsl() or hsla() string and toHSL is true. 12090 */ 12091 _parseColor = _CSSPlugin.parseColor = function (v, toHSL) { 12092 var a, r, g, b, h, s, l, max, min, d, wasHSL; 12093 if (!v) { 12094 a = _colorLookup.black; 12095 } else if (typeof v === "number") { 12096 a = [v >> 16, v >> 8 & 255, v & 255]; 12097 } else { 12098 if (v.charAt(v.length - 1) === ",") { 12099 //sometimes a trailing comma is included and we should chop it off (typically from a comma-delimited list of values like a textShadow:"2px 2px 2px blue, 5px 5px 5px rgb(255,0,0)" - in this example "blue," has a trailing comma. We could strip it out inside parseComplex() but we'd need to do it to the beginning and ending values plus it wouldn't provide protection from other potential scenarios like if the user passes in a similar value. 12100 v = v.substr(0, v.length - 1); 12101 } 12102 if (_colorLookup[v]) { 12103 a = _colorLookup[v]; 12104 } else if (v.charAt(0) === "#") { 12105 if (v.length === 4) { 12106 //for shorthand like #9F0 12107 r = v.charAt(1); 12108 g = v.charAt(2); 12109 b = v.charAt(3); 12110 v = "#" + r + r + g + g + b + b; 12111 } 12112 v = parseInt(v.substr(1), 16); 12113 a = [v >> 16, v >> 8 & 255, v & 255]; 12114 } else if (v.substr(0, 3) === "hsl") { 12115 a = wasHSL = v.match(_numExp); 12116 if (!toHSL) { 12117 h = Number(a[0]) % 360 / 360; 12118 s = Number(a[1]) / 100; 12119 l = Number(a[2]) / 100; 12120 g = l <= 0.5 ? l * (s + 1) : l + s - l * s; 12121 r = l * 2 - g; 12122 if (a.length > 3) { 12123 a[3] = Number(a[3]); 12124 } 12125 a[0] = _hue(h + 1 / 3, r, g); 12126 a[1] = _hue(h, r, g); 12127 a[2] = _hue(h - 1 / 3, r, g); 12128 } else if (v.indexOf("=") !== -1) { 12129 //if relative values are found, just return the raw strings with the relative prefixes in place. 12130 return v.match(_relNumExp); 12131 } 12132 } else { 12133 a = v.match(_numExp) || _colorLookup.transparent; 12134 } 12135 a[0] = Number(a[0]); 12136 a[1] = Number(a[1]); 12137 a[2] = Number(a[2]); 12138 if (a.length > 3) { 12139 a[3] = Number(a[3]); 12140 } 12141 } 12142 if (toHSL && !wasHSL) { 12143 r = a[0] / 255; 12144 g = a[1] / 255; 12145 b = a[2] / 255; 12146 max = Math.max(r, g, b); 12147 min = Math.min(r, g, b); 12148 l = (max + min) / 2; 12149 if (max === min) { 12150 h = s = 0; 12151 } else { 12152 d = max - min; 12153 s = l > 0.5 ? d / (2 - max - min) : d / (max + min); 12154 h = max === r ? (g - b) / d + (g < b ? 6 : 0) : max === g ? (b - r) / d + 2 : (r - g) / d + 4; 12155 h *= 60; 12156 } 12157 a[0] = h + 0.5 | 0; 12158 a[1] = s * 100 + 0.5 | 0; 12159 a[2] = l * 100 + 0.5 | 0; 12160 } 12161 return a; 12162 }, 12163 _formatColors = function _formatColors(s, toHSL) { 12164 var colors = s.match(_colorExp) || [], 12165 charIndex = 0, 12166 parsed = "", 12167 i, 12168 color, 12169 temp; 12170 if (!colors.length) { 12171 return s; 12172 } 12173 for (i = 0; i < colors.length; i++) { 12174 color = colors[i]; 12175 temp = s.substr(charIndex, s.indexOf(color, charIndex) - charIndex); 12176 charIndex += temp.length + color.length; 12177 color = _parseColor(color, toHSL); 12178 if (color.length === 3) { 12179 color.push(1); 12180 } 12181 parsed += temp + (toHSL ? "hsla(" + color[0] + "," + color[1] + "%," + color[2] + "%," + color[3] : "rgba(" + color.
12181join(",")) + ")"; 12182 } 12183 return parsed + s.substr(charIndex); 12184 }, 12185 _colorExp = "(?:\\b(?:(?:rgb|rgba|hsl|hsla)\\(.+?\\))|\\B#(?:[0-9a-f]{3}){1,2}\\b"; //we'll dynamically build this Regular Expression to conserve file size. After building it, it will be able to find rgb(), rgba(), # (hexadecimal), and named color values like red, blue, purple, etc. 12186 12187 for (p in _colorLookup) { 12188 _colorExp += "|" + p + "\\b"; 12189 } 12190 _colorExp = new RegExp(_colorExp + ")", "gi"); 12191 _CSSPlugin.colorStringFilter = function (a) { 12192 var combined = a[0] + " " + a[1], 12193 toHSL; 12194 if (_colorExp.test(combined)) { 12195 toHSL = combined.indexOf("hsl(") !== -1 || combined.indexOf("hsla(") !== -1; 12196 a[0] = _formatColors(a[0], toHSL); 12197 a[1] = _formatColors(a[1], toHSL); 12198 } 12199 _colorExp.lastIndex = 0; 12200 }; 12201 if (!TweenLite.defaultStringFilter) { 12202 TweenLite.defaultStringFilter = _CSSPlugin.colorStringFilter; 12203 } 12204 12205 /** 12206 * @private Returns a formatter function that handles taking a string (or number in some cases) and returning a consistently formatted one in terms of delimiters, quantity of values, etc. For example, we may get boxShadow values defined as "0px red" or "0px 0px 10px rgb(255,0,0)" or "0px 0px 20px 20px #F00" and we need to ensure that what we get back is described with 4 numbers and a color. This allows us to feed it into the _parseComplex() method and split the values up appropriately. The neat thing about this _getFormatter() function is that the dflt defines a pattern as well as a default, so for example, _getFormatter("0px 0px 0px 0px #777", true) not only sets the default as 0px for all distances and #777 for the color, but also sets the pattern such that 4 numbers and a color will always get returned. 12207 * @param {!string} dflt The default value and pattern to follow. So "0px 0px 0px 0px #777" will ensure that 4 numbers and a color will always get returned. 12208 * @param {boolean=} clr If true, the values should be searched for color-related data. For example, boxShadow values typically contain a color whereas borderRadius don't. 12209 * @param {boolean=} collapsible If true, the value is a top/left/right/bottom style one that acts like margin or padding, where if only one value is received, it's used for all 4; if 2 are received, the first is duplicated for 3rd (bottom) and the 2nd is duplicated for the 4th spot (left), etc. 12210 * @return {Function} formatter function 12211 */ 12212 var _getFormatter = function _getFormatter(dflt, clr, collapsible, multi) { 12213 if (dflt == null) { 12214 return function (v) { 12215 return v; 12216 }; 12217 } 12218 var dColor = clr ? (dflt.match(_colorExp) || [""])[0] : "", 12219 dVals = dflt.split(dColor).join("").match(_valuesExp) || [], 12220 pfx = dflt.substr(0, dflt.indexOf(dVals[0])), 12221 sfx = dflt.charAt(dflt.length - 1) === ")" ? ")" : "", 12222 delim = dflt.indexOf(" ") !== -1 ? " " : ",", 12223 numVals = dVals.length, 12224 dSfx = numVals > 0 ? dVals[0].replace(_numExp, "") : "", 12225 _formatter2; 12226 if (!numVals) { 12227 return function (v) { 12228 return v; 12229 }; 12230 } 12231 if (clr) { 12232 _formatter2 = function formatter(v) { 12233 var color, vals, i, a; 12234 if (typeof v === "number") { 12235 v += dSfx; 12236 } else if (multi && _commasOutsideParenExp.test(v)) { 12237 a = v.replace(_commasOutsideParenExp, "|").split("|"); 12238 for (i = 0; i < a.length; i++) { 12239 a[i] = _formatter2(a[i]); 12240 } 12241 return a.join(","); 12242 } 12243 color = (v.match(_colorExp) || [dColor])[0]; 12244 vals = v.split(color).join("").match(_valuesExp) || []; 12245 i = vals.length; 12246 if (numVals > i--) { 12247 while (++i < numVals) { 12248 vals[i] = collapsible ? vals[(i - 1) / 2 | 0] : dVals[i]; 12249 } 12250 } 12251 return pfx + vals.join(delim) + delim + color + sfx + (v.indexOf("inset") !== -1 ? " inset" : ""); 12252 }; 12253 return _formatter2; 12254 } 12255 _formatter2 = function _formatter(v) { 12256 var vals, a, i; 12257 if (typeof v === "number") { 12258 v += dSfx; 12259 } else if (multi && _commasOutsideParenExp.test(v)) { 12260 a = v.replace(_commasOutsideParenExp, "|").split("|"); 12261 for (i = 0; i < a.length; i++) { 12262 a[i] = _formatter2(a[i]); 12263 } 12264 return a.join(","); 12265 } 12266 vals = v.match(_valuesExp) || []; 12267 i = vals.length; 12268 if (numVals > i--) { 12269 while (++i < numVals) { 12270 vals[i] = collapsible ? vals[(i - 1) / 2 | 0] : dVals[i]; 12271 } 12272 } 12273 return pfx + vals.join(delim) + sfx; 12274 }; 12275 return _formatter2; 12276 }, 12277 /** 12278 * @private returns a formatter function that's used for edge-related values like marginTop, marginLeft, paddingBottom, paddingRight, etc. Just pass a comma-delimited list of property names related to the edges. 12279 * @param {!string} props a comma-delimited list of property names in order from top to left, like "marginTop,marginRight,marginBottom,marginLeft" 12280 * @return {Function} a formatter function 12281 */ 12282 _getEdgeParser = function _getEdgeParser(props) { 12283 props = props.split(","); 12284 return function (t, e, p, cssp, pt, plugin, vars) { 12285 var a = (e + "").split(" "), 12286 i; 12287 vars = {}; 12288 for (i = 0; i < 4; i++) { 12289 vars[props[i]] = a[i] = a[i] || a[(i - 1) / 2 >> 0]; 12290 } 12291 return cssp.parse(t, vars, pt, plugin); 12292 }; 12293 }, 12294 // @private used when other plugins must tween values first, like BezierPlugin or ThrowPropsPlugin, etc. That plugin's setRatio() gets called first so that the values are updated, and then we loop through the MiniPropTweens which handle copying the values into their appropriate slots so that they can then be applied correctly in the main CSSPlugin setRatio() method. Remember, we typically create a proxy object that has a bunch of uniquely-named properties that we feed to the sub-plugin and it does its magic normally, and then we must interpret those values and apply them to the css because often numbers must get combined/concatenated, suffixes added, etc. to work with css, like boxShadow could have 4 values plus a color. 12295 _setPluginRatio = _internals._setPluginRatio = function (v) { 12296 this.plugin.setRatio(v); 12297 var d = this.data, 12298 proxy = d.proxy, 12299 mpt = d.firstMPT, 12300 min = 0.000001, 12301 val, 12302 pt, 12303 i, 12304 str, 12305 p; 12306 while (mpt) { 12307 val = proxy[mpt.v]; 12308 if (mpt.r) { 12309 val = Math.round(val); 12310 } else if (val < min && val > -min) { 12311 val = 0; 12312 } 12313 mpt.t[mpt.p] = val; 12314 mpt = mpt._next; 12315 } 12316 if (d.autoRotate) { 12317 d.autoRotate.rotation = d.mod ? d.mod(proxy.rotation, this.t) : proxy.rotation; //special case for ModifyPlugin to hook into an auto-rotating bezier 12318 } 12319 //at the end, we must set the CSSPropTween's "e" (end) value dynamically here because that's what is used in the final setRatio() method. Same for "b" at the beginning. 12320 if (v === 1 || v === 0) { 12321 mpt = d.firstMPT; 12322 p = v === 1 ? "e" : "b"; 12323 while (mpt) { 12324 pt = mpt.t; 12325 if (!pt.type) { 12326 pt[p] = pt.s + pt.xs0; 12327 } else if (pt.type === 1) { 12328 str = pt.xs0 + pt.s + pt.xs1; 12329 for (i = 1; i < pt.l; i++) { 12330 str += pt["xn" + i] + pt["xs" + (i + 1)]; 12331 } 12332 pt[p] = str; 12333 } 12334 mpt = mpt._next; 12335 } 12336 } 12337 }, 12338 /** 12339 * @private @constructor Used by a few SpecialProps to hold important values for proxies. For example, _parseToProxy() creates a MiniPropTween instance for each property that must get tweened on the proxy, and we record the original property name as well as the unique one we create for the proxy, plus whether or not the value needs to be roun
12339ded plus the original value. 12340 * @param {!Object} t target object whose property we're tweening (often a CSSPropTween) 12341 * @param {!string} p property name 12342 * @param {(number|string|object)} v value 12343 * @param {MiniPropTween=} next next MiniPropTween in the linked list 12344 * @param {boolean=} r if true, the tweened value should be rounded to the nearest integer 12345 */ 12346 MiniPropTween = function MiniPropTween(t, p, v, next, r) { 12347 this.t = t; 12348 this.p = p; 12349 this.v = v; 12350 this.r = r; 12351 if (next) { 12352 next._prev = this; 12353 this._next = next; 12354 } 12355 }, 12356 /** 12357 * @private Most other plugins (like BezierPlugin and ThrowPropsPlugin and others) can only tween numeric values, but CSSPlugin must accommodate special values that have a bunch of extra data (like a suffix or strings between numeric values, etc.). For example, boxShadow has values like "10px 10px 20px 30px rgb(255,0,0)" which would utterly confuse other plugins. This method allows us to split that data apart and grab only the numeric data and attach it to uniquely-named properties of a generic proxy object ({}) so that we can feed that to virtually any plugin to have the numbers tweened. However, we must also keep track of which properties from the proxy go with which CSSPropTween values and instances. So we create a linked list of MiniPropTweens. Each one records a target (the original CSSPropTween), property (like "s" or "xn1" or "xn2") that we're tweening and the unique property name that was used for the proxy (like "boxShadow_xn1" and "boxShadow_xn2") and whether or not they need to be rounded. That way, in the _setPluginRatio() method we can simply copy the values over from the proxy to the CSSPropTween instance(s). Then, when the main CSSPlugin setRatio() method runs and applies the CSSPropTween values accordingly, they're updated nicely. So the external plugin tweens the numbers, _setPluginRatio() copies them over, and setRatio() acts normally, applying css-specific values to the element. 12358 * This method returns an object that has the following properties:
12359 * - proxy: a generic object containing the starting values for all the properties that will be tweened by the external plugin. This is what we feed to the external _onInitTween() as the target 12360 * - end: a generic object containing the ending values for all the properties that will be tweened by the external plugin. This is what we feed to the external plugin's _onInitTween() as the destination values 12361 * - firstMPT: the first MiniPropTween in the linked list 12362 * - pt: the first CSSPropTween in the linked list that was created when parsing. If shallow is true, this linked list will NOT attach to the one passed into the _parseToProxy() as the "pt" (4th) parameter. 12363 * @param {!Object} t target object to be tweened 12364 * @param {!(Object|string)} vars the object containing the information about the tweening values (typically the end/destination values) that should be parsed 12365 * @param {!CSSPlugin} cssp The CSSPlugin instance 12366 * @param {CSSPropTween=} pt the next CSSPropTween in the linked list 12367 * @param {TweenPlugin=} plugin the external TweenPlugin instance that will be handling tweening the numeric values 12368 * @param {boolean=} shallow if true, the resulting linked list from the parse will NOT be attached to the CSSPropTween that was passed in as the "pt" (4th) parameter. 12369 * @return An object containing the following properties: proxy, end, firstMPT, and pt (see above for descriptions) 12370 */ 12371 _parseToProxy = _internals._parseToProxy = function (t, vars, cssp, pt, plugin, shallow) { 12372 var bpt = pt, 12373 start = {}, 12374 end = {}, 12375 transform = cssp._transform, 12376 oldForce = _forcePT, 12377 i, 12378 p, 12379 xp, 12380 mpt, 12381 firstPT; 12382 cssp._transform = null; 12383 _forcePT = vars; 12384 pt = firstPT = cssp.parse(t, vars, pt, plugin); 12385 _forcePT = oldForce; 12386 //break off from the linked list so the new ones are isolated. 12387 if (shallow) { 12388 cssp._transform = transform; 12389 if (bpt) { 12390 bpt._prev = null; 12391 if (bpt._prev) { 12392 bpt._prev._next = null; 12393 } 12394 } 12395 } 12396 while (pt && pt !== bpt) { 12397 if (pt.type <= 1) { 12398 p = pt.p; 12399 end[p] = pt.s + pt.c; 12400 start[p] = pt.s; 12401 if (!shallow) { 12402 mpt = new MiniPropTween(pt, "s", p, mpt, pt.r); 12403 pt.c = 0; 12404 } 12405 if (pt.type === 1) { 12406 i = pt.l; 12407 while (--i > 0) { 12408 xp = "xn" + i; 12409 p = pt.p + "_" + xp; 12410 end[p] = pt.data[xp]; 12411 start[p] = pt[xp]; 12412 if (!shallow) { 12413 mpt = new MiniPropTween(pt, xp, p, mpt, pt.rxp[xp]); 12414 } 12415 } 12416 } 12417 } 12418 pt = pt._next; 12419 } 12420 return { 12421 proxy: start, 12422 end: end, 12423 firstMPT: mpt, 12424 pt: firstPT 12425 }; 12426 }, 12427 /** 12428 * @constructor Each property that is tweened has at least one CSSPropTween associated with it. These instances store important information like the target, property, starting value, amount of change, etc. They can also optionally have a number of "extra" strings and numeric values named xs1, xn1, xs2, xn2, xs3, xn3, etc. where "s" indicates string and "n" indicates number. These can be pieced together in a complex-value tween (type:1) that has alternating types of data like a string, number, string, number, etc. For example, boxShadow could be "5px 5px 8px rgb(102, 102, 51)". In that value, there are 6 numbers that may need to tween and then pieced back together into a string again with spaces, suffixes, etc. xs0 is special in that it stores the suffix for standard (type:0) tweens, -OR- the first string (prefix) in a complex-value (type:1) CSSPropTween -OR- it can be the non-tweening value in a type:-1 CSSPropTween. We do this to conserve memory. 12429 * CSSPropTweens have the following optional properties as well (not defined through the constructor): 12430 * - l: Length in terms of the number of extra properties that the CSSPropTween has (default: 0). For example, for a boxShadow we may need to tween 5 numbers in which case l would be 5; Keep in mind that the start/end values for the first number that's tweened are always stored in the s and c properties to conserve memory. All additional values thereafter are stored in xn1, xn2, etc. 12431 * - xfirst: The first instance of any sub-CSSPropTweens that are tweening properties of this instance. For example, we may split up a boxShadow tween so that there's a main CSSPropTween of type:1 that has various xs* and xn* values associated with the h-shadow, v-shadow, blur, color, etc. Then we spawn a CSSPropTween for each of those that has a higher priority and runs BEFORE the main CSSPropTween so that the values are all set by the time it needs to re-assemble them. The xfirst gives us an easy way to identify the first one in that chain which typically ends at the main one (because they're all prepende to the linked list) 12432 * - plugin: The TweenPlugin instance that will handle the tweening of any complex values. For example, sometimes we don't want to use normal subt
12432weens (like xfirst refers to) to tween the values - we might want ThrowPropsPlugin or BezierPlugin some other plugin to do the actual tweening, so we create a plugin instance and store a reference here. We need this reference so that if we get a request to round values or disable a tween, we can pass along that request. 12433 * - data: Arbitrary data that needs to be stored with the CSSPropTween. Typically if we're going to have a plugin handle the tweening of a complex-value tween, we create a generic object that stores the END values that we're tweening to and the CSSPropTween's xs1, xs2, etc. have the starting values. We store that object as data. That way, we can simply pass that object to the plugin and use the CSSPropTween as the target. 12434 * - setRatio: Only used for type:2 tweens that require custom functionality. In this case, we call the CSSPropTween's setRatio() method and pass the ratio each time the tween updates. This isn't quite as efficient as doing things directly in the CSSPlugin's setRatio() method, but it's very convenient and flexible. 12435 * @param {!Object} t Target object whose property will be tweened. Often a DOM element, but not always. It could be anything. 12436 * @param {string} p Property to tween (name). For example, to tween element.width, p would be "width". 12437 * @param {number} s Starting numeric value 12438 * @param {number} c Change in numeric value over the course of the entire tween. For example, if element.width starts at 5 and should end at 100, c would be 95. 12439 * @param {CSSPropTween=} next The next CSSPropTween in the linked list. If one is defined, we will define its _prev as the new instance, and the new instance's _next will be pointed at it. 12440 * @param {number=} type The type of CSSPropTween where -1 = a non-tweening value, 0 = a standard simple tween, 1 = a complex value (like one that has multiple numbers in a comma- or space-delimited string like border:"1px solid red"), and 2 = one that uses a custom setRatio function that does all of the work of applying the values on each update. 12441 * @param {string=} n Name of the property that should be used for overwriting purposes which is typically the same as p but not always. For example, we may need to create a subtween for the 2nd part of a "clip:rect(...)" tween in which case "p" might be xs1 but "n" is still "clip" 12442 * @param {boolean=} r If true, the value(s) should be rounded 12443 * @param {number=} pr Priority in the linked list order. Higher priority CSSPropTweens will be updated before lower priority ones. The default priority is 0. 12444 * @param {string=} b Beginning value. We store this to ensure that it is EXACTLY what it was when the tween began without any risk of interpretation issues. 12445 * @param {string=} e Ending value. We store this to ensure that it is EXACTLY what the user defined at the end of the tween without any risk of interpretation issues. 12446 */ 12447 CSSPropTween = _internals.CSSPropTween = function (t, p, s, c, next, type, n, r, pr, b, e) { 12448 this.t = t; //target 12449 this.p = p; //property 12450 this.s = s; //starting value 12451 this.c = c; //change value 12452 this.n = n || p; //name that this CSSPropTween should be associated to (usually the same as p, but not always - n is what overwriting looks at) 12453 if (!(t instanceof CSSPropTween)) { 12454 _overwriteProps.push(this.n); 12455 } 12456 this.r = r; //round (boolean) 12457 this.type = type || 0; //0 = normal tween, -1 = non-tweening (in which case xs0 will be applied to the target's property, like tp.t[tp.p] = tp.xs0), 1 = complex-value SpecialProp, 2 = custom setRatio() that does all the work 12458 if (pr) { 12459 this.pr = pr; 12460 _hasPriority = true; 12461 } 12462 this.b = b === undefined ? s : b; 12463 this.e = e === undefined ? s + c : e; 12464 if (next) { 12465 this._next = next; 12466 next._prev = this; 12467 } 12468 }, 12469 _addNonTweeningNumericPT = function _addNonTweeningNumericPT(target, prop, start, end, next, overwriteProp) { 12470 //cleans up some code redundancies and helps minification. Just a fast way to add a NUMERIC non-tweening CSSPropTween
12471 var pt = new CSSPropTween(target, prop, start, end - start, next, -1, overwriteProp); 12472 pt.b = start; 12473 pt.e = pt.xs0 = end; 12474 return pt; 12475 }, 12476 /** 12477 * Takes a target, the beginning value and ending value (as strings) and parses them into a CSSPropTween (possibly with child CSSPropTweens) that accommodates multiple numbers, colors, comma-delimited values, etc. For example: 12478 * sp.parseComplex(element, "boxShadow", "5px 10px 20px rgb(255,102,51)", "0px 0px 0px red", true, "0px 0px 0px rgb(0,0,0,0)", pt); 12479 * It will walk through the beginning and ending values (which should be in the same format with the same number and type of values) and figure out which parts are numbers, what strings separate the numeric/tweenable values, and then create the CSSPropTweens accordingly. If a plugin is defined, no child CSSPropTweens will be created. Instead, the ending values will be stored in the "data" property of the returned CSSPropTween like: {s:-5, xn1:-10, xn2:-20, xn3:255, xn4:0, xn5:0} so that it can be fed to any other plugin and it'll be plain numeric tweens but the recomposition of the complex value will be handled inside CSSPlugin's setRatio(). 12480 * If a setRatio is defined, the type of the CSSPropTween will be set to 2 and recomposition of the values will be the responsibility of that method. 12481 * 12482 * @param {!Object} t Target whose property will be tweened 12483 * @param {!string} p Property that will be tweened (its name, like "left" or "backgroundColor" or "boxShadow") 12484 * @param {string} b Beginning value 12485 * @param {string} e Ending value 12486 * @param {boolean} clrs If true, the value could contain a color value like "rgb(255,0,0)" or "#F00" or "red". The default is false, so no colors will be recognized (a performance optimization) 12487 * @param {(string|number|Object)} dflt The default beginning value that should be used if no valid beginning value is defined or if the number of values inside the complex beginning and ending values don't match 12488 * @param {?CSSPropTween} pt CSSPropTween instance that is the current head of the linked list (we'll prepend to this). 12489 * @param {number=} pr Priority in the linked list order. Higher priority properties will be updated before lower priority ones. The default priority is 0. 12490 * @param {TweenPlugin=} plugin If a plugin should handle the tweening of extra properties, pass the plugin instance here. If one is defined, then NO subtweens will be created for any extra properties (the properties will be created - just not additional CSSPropTween instances to tween them) because the plugin is expected to do so. However, the end values WILL be populated in the "data" property, like {s:100, xn1:50, xn2:300} 12491 * @param {function(number)=} setRatio If values should be set in a custom function instead of being pieced together in a type:1 (complex-value) CSSPropTween, define that custom function here. 12492 * @return {CSSPropTween} The first CSSPropTween in the linked list which includes the new one(s) added by the parseComplex() call. 12493 */ 12494 _parseComplex = _CSSPlugin.parseComplex = function (t, p, b, e, clrs, dflt, pt, pr, plugin, setRatio) { 12495 //DEBUG: _log("parseComplex: "+p+", b: "+b+", e: "+e); 12496 b = b || dflt || ""; 12497 if (typeof e === "function") { 12498 e = e(_index, _target); 12499 } 12500 pt = new CSSPropTween(t, p, 0, 0, pt, setRatio ? 2 : 1, null, false, pr, b, e); 12501 e += ""; //ensures it's a string 12502 if (clrs && _colorExp.test(e + b)) { 12503 //if colors are found, normalize the formatting to rgba() or hsla(). 12504 e = [b, e]; 12505 _CSSPlugin.colorStringFilter(e); 12506 b = e[0]; 12507 e = e[1]; 12508 } 12509 var ba = b.split(", ").join(",").split(" "), 12510 //beginning array 12511 ea = e.split(", ").join(",").split(" "), 12512 //ending array 12513 l = ba.length, 12514 autoRound = _autoRound !== false, 12515 i, 12516 xi, 12517 ni, 12518 bv, 12519 ev, 12520 bnums, 12521 enums, 12522 bn, 12523 hasAlpha, 12524 temp, 12525 cv, 12526 str, 12527 useHSL; 12528 if (e.indexOf(",") !== -1 || b.indexOf(",") !== -1) { 12529 if ((e + b).indexOf("rgb") !== -1 || (e + b).indexOf("hsl") !== -1) { 12530 //keep rgb(), rgba(), hsl(), and hsla() values together! (remember, we're splitting on spaces) 12531 ba = ba.join(" ").replace(_commasOutsideParenExp, ", ").split(" "); 12532 ea = ea.join(" ").replace(_commasOutsideParenExp, ", ").split(" "); 12533 } else { 12534 ba = ba.join(" ").split(",").join(", ").split(" "); 12535 ea = ea.join(" ").split(",").join(", ").split(" "); 12536 } 12537 l = ba.length; 12538 } 12539 if (l !== ea.length) { 12540 //DEBUG: _log("mismatched formatting detected on " + p + " (" + b + " vs " + e + ")"); 12541 ba = (dflt || "").split(" "); 12542 l = ba.length; 12543 } 12544 pt.plugin = plugin; 12545 pt.setRatio = setRatio; 12546 _colorExp.lastIndex = 0; 12547 for (i = 0; i < l; i++) { 12548 bv = ba[i]; 12549 ev = ea[i]; 12550 bn = parseFloat(bv); 12551 //if the value begins with a number (most common). It's fine if it has a suffix like px 12552 if (bn || bn === 0) { 12553 pt.appendXtra("", bn, _parseChange(ev, bn), ev.replace(_relNumExp, ""), autoRound && ev.indexOf("px") !== -1, true); 12554 12555 //if the value is a color 12556 } else if (clrs && _colorExp.test(bv)) { 12557 str = ev.indexOf(")") + 1; 12558 str = ")" + (str ? ev.substr(str) : ""); //if there's a comma or ) at the end, retain it. 12559 useHSL = ev.indexOf("hsl") !== -1 && _supportsOpacity; 12560 temp = ev; //original string value so we can look for any prefix later. 12561 bv = _parseColor(bv, useHSL); 12562 ev = _parseColor(ev, useHSL); 12563 hasAlpha = bv.length + ev.length > 6; 12564 if (hasAlpha && !_supportsOpacity && ev[3] === 0) { 12565 //older versions of IE don't support rgba(), so if the destination alpha is 0, just use "transparent" for the end color 12566 pt["xs" + pt.l] += pt.l ? " transparent" : "transparent";
12567 pt.e = pt.e.split(ea[i]).join("transparent"); 12568 } else { 12569 if (!_supportsOpacity) { 12570 //old versions of IE don't support rgba(). 12571 hasAlpha = false; 12572 } 12573 if (useHSL) { 12574 pt.appendXtra(temp.substr(0, temp.indexOf("hsl")) + (hasAlpha ? "hsla(" : "hsl("), bv[0], _parseChange(ev[0], bv[0]), ",", false, true).appendXtra("", bv[1], _parseChange(ev[1], bv[1]), "%,", false).appendXtra("", bv[2], _parseChange(ev[2], bv[2]), hasAlpha ? "%," : "%" + str, false); 12575 } else { 12576 pt.appendXtra(temp.substr(0, temp.indexOf("rgb")) + (hasAlpha ? "rgba(" : "rgb("), bv[0], ev[0] - bv[0], ",", true, true).appendXtra("", bv[1], ev[1] - bv[1], ",", true).appendXtra("", bv[2], ev[2] - bv[2], hasAlpha ? "," : str, true); 12577 } 12578 if (hasAlpha) { 12579 bv = bv.length < 4 ? 1 : bv[3]; 12580 pt.appendXtra("", bv, (ev.length < 4 ? 1 : ev[3]) - bv, str, false); 12581 } 12582 } 12583 _colorExp.lastIndex = 0; //otherwise the test() on the RegExp could move the lastIndex and taint future results. 12584 } else { 12585 bnums = bv.match(_numExp); //gets each group of numbers in the beginning value string and drops them into an array 12586 12587 //if no number is found, treat it as a non-tweening value and just append the string to the current xs. 12588 if (!bnums) { 12589 pt["xs" + pt.l] += pt.l || pt["xs" + pt.l] ? " " + ev : ev; 12590 12591 //loop through all the numbers that are found and construct the extra values on the pt. 12592 } else { 12593 enums = ev.match(_relNumExp); //get each group of numbers in the end value string and drop them into an array. We allow relative values too, like +=50 or -=.5 12594 if (!enums || enums.length !== bnums.length) { 12595 //DEBUG: _log("mismatched formatting detected on " + p + " (" + b + " vs " + e + ")"); 12596 return pt; 12597 } 12598 ni = 0; 12599 for (xi = 0; xi < bnums.length; xi++) { 12600 cv = bnums[xi]; 12601 temp = bv.indexOf(cv, ni); 12602 pt.appendXtra(bv.substr(ni, temp - ni), Number(cv), _parseChange(enums[xi], cv), "", autoRound && bv.substr(temp + cv.length, 2) === "px", xi === 0); 12603 ni = temp + cv.length; 12604 } 12605 pt["xs" + pt.l] += bv.substr(ni); 12606 } 12607 } 12608 } 12609 //if there are relative values ("+=" or "-=" prefix), we need to adjust the ending value to eliminate the prefixes and combine the values properly. 12610 if (e.indexOf("=") !== -1) if (pt.data) { 12611 str = pt.xs0 + pt.data.s; 12612 for (i = 1; i < pt.l; i++) { 12613 str += pt["xs" + i] + pt.data["xn" + i]; 12614 } 12615 pt.e = str + pt["xs" + i]; 12616 } 12617 if (!pt.l) { 12618 pt.type = -1; 12619 pt.xs0 = pt.e; 12620 } 12621 return pt.xfirst || pt; 12622 }, 12623 i = 9; 12624 p = CSSPropTween.prototype; 12625 p.l = p.pr = 0; //length (number of extra properties like xn1, xn2, xn3, etc. 12626 while (--i > 0) { 12627 p["xn" + i] = 0; 12628 p["xs" + i] = ""; 12629 } 12630 p.xs0 = ""; 12631 p._next = p._prev = p.xfirst = p.data = p.plugin = p.setRatio = p.rxp = null; 12632 12633 /** 12634 * Appends and extra tweening value to a CSSPropTween and automatically manages any prefix and suffix strings. The first extra value is stored in the s and c of the main CSSPropTween instance, but thereafter any extras are stored in the xn1, xn2, xn3, etc. The prefixes and suffixes are stored in the xs0, xs1, xs2, etc. properties. For example, if I walk through a clip value like "rect(10px, 5px, 0px, 20px)", the values would be stored like this: 12635 * xs0:"rect(", s:10, xs1:"px, ", xn1:5, xs2:"px, ", xn2:0, xs3:"px, ", xn3:20, xn4:"px)" 12636 * And they'd all get joined together when the CSSPlugin renders (in the setRatio() method). 12637 * @param {string=} pfx Prefix (if any) 12638 * @param {!number} s Starting value 12639 * @param {!number} c Change in numeric value over the course of the entire tween. For example, if the start is 5 and the end is 100, the change would be 95. 12640 * @param {string=} sfx Suffix (if any) 12641 * @param {boolean=} r Round (if true). 12642 * @param {boolean=} pad If true, this extra value should be separated by the previous one by a space. If there is no previous extra and pad is true, it will automatically drop the space. 12643 * @return {CSSPropTween} returns itself so that multiple methods can be chained together. 12644 */ 12645 p.appendXtra = function (pfx, s, c, sfx, r, pad) { 12646 var pt = this, 12647 l = pt.l; 12648 pt["xs" + l] += pad && (l || pt["xs" + l]) ? " " + pfx : pfx || ""; 12649 if (!c) if (l !== 0 && !pt.plugin) { 12650 //typically we'll combine non-changing values right into the xs to optimize performance, but we don't combine them when there's a plugin that will be tweening the values because it may depend on the values being split apart, like for a bezier, if a value doesn't change between the first and second iteration but then it does on the 3rd, we'll run into trouble because there's no xn slot for that value! 12651 pt["xs" + l] += s + (sfx || ""); 12652 return pt; 12653 } 12654 pt.l++; 12655 pt.type = pt.setRatio ? 2 : 1; 12656 pt["xs" + pt.l] = sfx || ""; 12657 if (l > 0) { 12658 pt.data["xn" + l] = s + c; 12659 pt.rxp["xn" + l] = r; //round extra property (we need to tap into this in the _parseToProxy() method) 12660 pt["xn" + l] = s; 12661 if (!pt.plugin) { 12662 pt.xfirst = new CSSPropTween(pt, "xn" + l, s, c, pt.xfirst || pt, 0, pt.n, r, pt.pr); 12663 pt.xfirst.xs0 = 0; //just to ensure that the property stays numeric which helps modern browsers speed up processing. Remember, in the setRatio() method, we do pt.t[pt.p] = val + pt.xs0 so if pt.xs0 is "" (the default), it'll cast the end value as a string. When a property is a number sometimes and a string sometimes, it prevents the compiler from locking in the data type, slowing things down slightly. 12664 } 12665 return pt; 12666 } 12667 pt.data = { 12668 s: s + c 12669 }; 12670 pt.rxp = {}; 12671 pt.s = s; 12672 pt.c = c; 12673 pt.r = r; 12674 return pt; 12675 }; 12676 12677 /** 12678 * @constructor A SpecialProp is basically a css property that needs to be treated in a non-standard way, like if it may contain a complex value like boxShadow:"5px 10px 15px rgb(255, 102, 51)" or if it is associated with another plugin like ThrowPropsPlugin or BezierPlugin. Every SpecialProp is associated with a particular property name like "boxShadow" or "throwProps" or "bezier" and it will intercept those values in the vars object that's passed to the CSSPlugin and handle them accordingly. 12679 * @param {!string} p Property name (like "boxShadow" or "throwProps") 12680 * @param {Object=}
12680 options An object containing any of the following configuration options: 12681 * - defaultValue: the default value 12682 * - parser: A function that should be called when the associated property name is found in the vars. This function should return a CSSPropTween instance and it should ensure that it is properly inserted into the linked list. It will receive 4 paramters: 1) The target, 2) The value defined in the vars, 3) The CSSPlugin instance (whose _firstPT should be used for the linked list), and 4) A computed style object if one was calculated (this is a speed optimization that allows retrieval of starting values quicker) 12683 * - formatter: a function that formats any value received for this special property (for example, boxShadow could take "5px 5px red" and format it to "5px 5px 0px 0px red" so that both the beginning and ending values have a common order and quantity of values.) 12684 * - prefix: if true, we'll determine whether or not this property requires a vendor prefix (like Webkit or Moz or ms or O) 12685 * - color: set this to true if the value for this SpecialProp may contain color-related values like rgb(), rgba(), etc. 12686 * - priority: priority in the linked list order. Higher priority SpecialProps will be updated before lower priority ones. The default priority is 0. 12687 * - multi: if true, the formatter should accommodate a comma-delimited list of values, like boxShadow could have multiple boxShadows listed out. 12688 * - collapsible: if true, the formatter should treat the value like it's a top/right/bottom/left value that could be collapsed, like "5px" would apply to all, "5px, 10px" would use 5px for top/bottom and 10px for right/left, etc. 12689 * - keyword: a special keyword that can [optionally] be found inside the value (like "inset" for boxShadow). This allows us to validate beginning/ending values to make sure they match (if the keyword is found in one, it'll be added to the other for consistency by default). 12690 */ 12691 var SpecialProp = function SpecialProp(p, options) { 12692 options = options || {}; 12693 this.p = options.prefix ? _checkPropPrefix(p) || p : p; 12694 _specialProps[p] = _specialProps[this.p] = this; 12695 this.format = options.formatter || _getFormatter(options.defaultValue, options.color, options.collapsible, options.multi); 12696 if (options.parser) { 12697 this.parse = options.parser; 12698 } 12699 this.clrs = options.color; 12700 this.multi = options.multi; 12701 this.keyword = options.keyword; 12702 this.dflt = options.defaultValue; 12703 this.pr = options.priority || 0; 12704 }, 12705 //shortcut for creating a new SpecialProp that can accept multiple properties as a comma-delimited list (helps minification). dflt can be an array for multiple values (we don't do a comma-delimited list because the default value may contain commas, like rect(0px,0px,0px,0px)). We attach this method to the SpecialProp class/object instead of using a private _createSpecialProp() method so that we can tap into it externally if necessary, like from another plugin. 12706 _registerComplexSpecialProp = _internals._registerComplexSpecialProp = function (p, options, defaults) { 12707 if (_typeof(options) !== "object") { 12708 options = { 12709 parser: defaults 12710 }; //to make backwards compatible with older versions of BezierPlugin and ThrowPropsPlugin 12711 } 12712 var a = p.split(","), 12713 d = options.defaultValue, 12714 i, 12715 temp; 12716 defaults = defaults || [d]; 12717 for (i = 0; i < a.length; i++) { 12718 options.prefix = i === 0 && options.prefix; 12719 options.defaultValue = defaults[i] || d; 12720 temp = new SpecialProp(a[i], options); 12721 } 12722 }, 12723 //creates a placeholder special prop for a plugin so that the property gets caught the first time a tween of it is attempted, and at that time it makes the plugin register itself, thus taking over for all future tweens of that property. This allows us to not mandate that things load in a particular order and it also allows us to log() an error that informs the user when they attempt to tween an external plugin-related property without loading its .js file. 12724 _registerPluginProp = _internals._registerPluginProp = function (p) { 12725 if (!_specialProps[p]) { 12726 var pluginName = p.charAt(0).toUpperCase() + p.substr(1) + "Plugin"; 12727 _registerComplexSpecialProp(p, { 12728 parser: function parser(t, e, p, cssp, pt, plugin, vars) { 12729 var pluginClass = _globals.com.greensock.plugins[pluginName]; 12730 if (!pluginClass) { 12731 _log("Error: " + pluginName + " js file not loaded."); 12732 return pt; 12733 } 12734 pluginClass._cssRegister(); 12735 return _specialProps[p].parse(t, e, p, cssp, pt, plugin, vars); 12736 } 12737 }); 12738 } 12739 }; 12740 p = SpecialProp.prototype; 12741 12742 /** 12743 * Alias for _parseComplex() that automatically plugs in certain values for this SpecialProp, like its property name, whether or not colors should be sensed, the default value, and priority. It also looks for any keyword that the SpecialProp defines (like "inset" for boxSh
12743adow) and ensures that the beginning and ending values have the same number of values for SpecialProps where multi is true (like boxShadow and textShadow can have a comma-delimited list) 12744 * @param {!Object} t target element 12745 * @param {(string|number|object)} b beginning value 12746 * @param {(string|number|object)} e ending (destination) value 12747 * @param {CSSPropTween=} pt next CSSPropTween in the linked list 12748 * @param {TweenPlugin=} plugin If another plugin will be tweening the complex value, that TweenPlugin instance goes here. 12749 * @param {function=} setRatio If a custom setRatio() method should be used to handle this complex value, that goes here. 12750 * @return {CSSPropTween=} First CSSPropTween in the linked list 12751 */ 12752 p.parseComplex = function (t, b, e, pt, plugin, setRatio) { 12753 var kwd = this.keyword, 12754 i, 12755 ba, 12756 ea, 12757 l, 12758 bi, 12759 ei; 12760 //if this SpecialProp's value can contain a comma-delimited list of values (like boxShadow or textShadow), we must parse them in a special way, and look for a keyword (like "inset" for boxShadow) and ensure that the beginning and ending BOTH have it if the end defines it as such. We also must ensure that there are an equal number of values specified (we can't tween 1 boxShadow to 3 for example) 12761 if (this.multi) if (_commasOutsideParenExp.test(e) || _commasOutsideParenExp.test(b)) { 12762 ba = b.replace(_commasOutsideParenExp, "|").split("|"); 12763 ea = e.replace(_commasOutsideParenExp, "|").split("|"); 12764 } else if (kwd) { 12765 ba = [b]; 12766 ea = [e]; 12767 } 12768 if (ea) { 12769 l = ea.length > ba.length ? ea.length : ba.length; 12770 for (i = 0; i < l; i++) { 12771 b = ba[i] = ba[i] || this.dflt; 12772 e = ea[i] = ea[i] || this.dflt; 12773 if (kwd) { 12774 bi = b.indexOf(kwd); 12775 ei = e.indexOf(kwd); 12776 if (bi !== ei) { 12777 if (ei === -1) { 12778 //if the keyword isn't in the end value, remove it from the beginning one. 12779 ba[i] = ba[i].split(kwd).join(""); 12780 } else if (bi === -1) { 12781 //if the keyword isn't in the beginning, add it. 12782 ba[i] += " " + kwd; 12783 } 12784 } 12785 } 12786 } 12787 b = ba.join(", "); 12788 e = ea.join(", "); 12789 } 12790 return _parseComplex(t, this.p, b, e, this.clrs, this.dflt, pt, this.pr, plugin, setRatio); 12791 }; 12792 12793 /** 12794 * Accepts a target and end value and spits back a CSSPropTween that has been inserted into the CSSPlugin's linked list and conforms with all the conventions we use internally, like type:-1, 0, 1, or 2, setting up any extra property tweens, priority, etc. For example, if we have a boxShadow SpecialProp and call: 12795 * this._firstPT = sp.parse(element, "5px 10px 20px rgb(2550,102,51)", "boxShadow", this); 12796 * It should figure out the starting value of the element's boxShadow, compare it to the provided end value and create all the necessary CSSPropTweens of the appropriate types to tween the boxShadow. The CSSPropTween that gets spit back should already be inserted into the linked list (the 4th parameter is the current head, so prepend to that). 12797 * @param {!Object} t Target object whose property is being tweened 12798 * @param {Object} e End value as provided in the vars object (typically a string, but not always - like a throwProps would be an object). 12799 * @param {!string} p Property name 12800 * @param {!CSSPlugin} cssp The CSSPlugin instance that should be associated with this tween. 12801 * @param {?CSSPropTween} pt The CSSPropTween that is the current head of the linked list (we'll prepend to it) 12802 * @param {TweenPlugin=} plugin If a plugin will be used to tween the parsed value, this is the plugin instance. 12803 * @param {Object=} vars Original vars object that contains the data for parsing. 12804 * @return {CSSPropTween} The first CSSPropTween in the linked list which includes the new one(s) added by the parse() call. 12805 */ 12806 p.parse = function (t, e, p, cssp, pt, plugin, vars) { 12807 return this.parseComplex(t.style, this.format(_getStyle(t, this.p, _cs, false, this.dflt)), this.format(e), pt, plugin); 12808 }; 12809 12810 /** 12811 * Registers a special property that should be intercepted from any "css" objects defined in tweens. This allows you to handle them however you want without CSSPlugin doing it for you. The 2nd parameter should be a function that accepts 3 parameters: 12812 * 1) Target object whose property should be tweened (typically a DOM element) 12813 * 2) The end/destination value (could be a string, number, object, or whatever you want) 12814 * 3) The tween instance (you probably don't need to worry about this, but it can be useful for looking up information like the duration) 12815 * 12816 * Then, your function should return a function which will be called each time the tween gets rendered, passing a numeric "ratio" parameter to your function that indicates the change factor (usually between 0 and 1). For example: 12817 * 12818 * CSSPlugin.registerSpecialProp("myCustomProp", function(target, value, tween) { 12819 * var start = target.style.width;
12820 * return function(ratio) { 12821 * target.style.width = (start + value * ratio) + "px"; 12822 * console.log("set width to " + target.style.width); 12823 * } 12824 * }, 0); 12825 * 12826 * Then, when I do this tween, it will trigger my special property: 12827 * 12828 * TweenLite.to(element, 1, {css:{myCustomProp:100}}); 12829 * 12830 * In the example, of course, we're just changing the width, but you can do anything you want. 12831 * 12832 * @param {!string} name Property name (or comma-delimited list of property names) that should be intercepted and handled by your function. For example, if I define "myCustomProp", then it would handle that portion of the following tween: TweenLite.to(element, 1, {css:{myCustomProp:100}}) 12833 * @param {!function(Object, Object, Object, string):function(number)} onInitTween The function that will be called when a tween of this special property is performed. The function will receive 4 parameters: 1) Target object that should be tweened, 2) Value that was passed to the tween, 3) The tween instance itself (rarely used), and 4) The property name that's being tweened. Your function should return a function that should be called on every update of the tween. That function will receive a single parameter that is a "change factor" value (typically between 0 and 1) indicating the amount of change as a ratio. You can use this to determine how to set the values appropriately in your function. 12834 * @param {number=} priority Priority that helps the engine determine the order in which to set the properties (default: 0). Higher priority properties will be updated before lower priority ones. 12835 */ 12836 _CSSPlugin.registerSpecialProp = function (name, onInitTween, priority) { 12837 _registerComplexSpecialProp(name, { 12838 parser: function parser(t, e, p, cssp, pt, plugin, vars) { 12839 var rv = new CSSPropTween(t, p, 0, 0, pt, 2, p, false, priority); 12840 rv.plugin = plugin; 12841 rv.setRatio = onInitTween(t, e, cssp._tween, p); 12842 return rv; 12843 }, 12844 priority: priority 12845 }); 12846 }; 12847 12848 //transform-related methods and properties 12849 _CSSPlugin.useSVGTransformAttr = true; //Safari and Firefox both have some rendering bugs when applying CSS transforms to SVG elements, so default to using the "transform" attribute instead (users can override this). 12850 var _transformProps = "scaleX,scaleY,scaleZ,x,y,z,skewX,skewY,rotation,rotationX,rotationY,perspective,xPercent,yPercent".split(","), 12851 _transformProp = _checkPropPrefix("transform"), 12852 //the Javascript (camelCase) transform property, like msTransform, WebkitTransform, MozTransform, or OTransform. 12853 _transformPropCSS = _prefixCSS + "transform", 12854 _transformOriginProp = _checkPropPrefix("transformOrigin"), 12855 _supports3D = _checkPropPrefix("perspective") !== null, 12856 Transform = _internals.Transform = function () { 12857 this.perspective = parseFloat(_CSSPlugin.defaultTransformPerspective) || 0; 12858 this.force3D = _CSSPlugin.defaultForce3D === false || !_supports3D ? false : _CSSPlugin.defaultForce3D || "auto"; 12859 }, 12860 _SVGElement = _gsScope.SVGElement, 12861 _useSVGTransformAttr, 12862 //Some browsers (like Firefox and IE) don't honor transform-origin properly in SVG elements, so we need to manually adjust the matrix accordingly. We feature detect here rather than always doing the conversion for certain browsers because they may fix the problem at some point in the future. 12863 12864 _createSVG = function _createSVG(type, container, attributes) { 12865 var element = _doc.createElementNS("http://www.w3.org/2000/svg", type), 12866 reg = /([a-z])([A-Z])/g, 12867 p; 12868 for (p in attributes) { 12869 element.setAttributeNS(null, p.replace(reg, "$1-$2").toLowerCase(), attributes[p]); 12870 } 12871 container.appendChild(element); 12872 return element; 12873 }, 12874 _docElement = _doc.documentElement || {}, 12875 _forceSVGTransformAttr = function () { 12876 //IE and Android stock don't support CSS transforms on SVG elements, so we must write them to the "transform" attribute. We populate this variable in the _parseTransform() method, and only if/when we come across an SVG element 12877 var force = _ieVers || /Android/i.test(_agent) && !_gsScope.chrome, 12878 svg, 12879 rect, 12880 width; 12881 if (_doc.createElementNS && !force) { 12882 //IE8 and earlier doesn't support SVG anyway 12883 svg = _createSVG("svg", _docElement); 12884 rect = _createSVG("rect", svg, { 12885 width: 100, 12886 height: 50, 12887 x: 100 12888 }); 12889 width = rect.getBoundingClientRect().width; 12890 rect.style[_transformOriginProp] = "50% 50%"; 12891 rect.style[_transformProp] = "scaleX(0.5)"; 12892 force = width === rect.getBoundingClientRect().width && !(_is
12892Firefox && _supports3D); //note: Firefox fails the test even though it does support CSS transforms in 3D. Since we can't push 3D stuff into the transform attribute, we force Firefox to pass the test here (as long as it does truly support 3D). 12893 _docElement.removeChild(svg); 12894 } 12895 return force; 12896 }(), 12897 _parseSVGOrigin = function _parseSVGOrigin(e, local, decoratee, absolute, smoothOrigin, skipRecord) { 12898 var tm = e._gsTransform, 12899 m = _getMatrix(e, true), 12900 v, 12901 x, 12902 y, 12903 xOrigin, 12904 yOrigin, 12905 a, 12906 b, 12907 c, 12908 d, 12909 tx, 12910 ty, 12911 determinant, 12912 xOriginOld, 12913 yOriginOld; 12914 if (tm) { 12915 xOriginOld = tm.xOrigin; //record the original values before we alter them. 12916 yOriginOld = tm.yOrigin; 12917 } 12918 if (!absolute || (v = absolute.split(" ")).length < 2) { 12919 b = e.getBBox(); 12920 if (b.x === 0 && b.y === 0 && b.width + b.height === 0) { 12921 //some browsers (like Firefox) misreport the bounds if the element has zero width and height (it just assumes it's at x:0, y:0), thus we need to manually grab the position in that case. 12922 b = { 12923 x: parseFloat(e.hasAttribute("x") ? e.getAttribute("x") : e.hasAttribute("cx") ? e.getAttribute("cx") : 0) || 0, 12924 y: parseFloat(e.hasAttribute("y") ? e.getAttribute("y") : e.hasAttribute("cy") ? e.getAttribute("cy") : 0) || 0, 12925 width: 0, 12926 height: 0 12927 }; 12928 } 12929 local = _parsePosition2(local).split(" "); 12930 v = [(local[0].indexOf("%") !== -1 ? parseFloat(local[0]) / 100 * b.width : parseFloat(local[0])) + b.x, (local[1].indexOf("%") !== -1 ? parseFloat(local[1]) / 100 * b.height : parseFloat(local[1])) + b.y]; 12931 } 12932 decoratee.xOrigin = xOrigin = parseFloat(v[0]); 12933 decoratee.yOrigin = yOrigin = parseFloat(v[1]); 12934 if (absolute && m !== _identity2DMatrix) { 12935 //if svgOrigin is being set, we must invert the matrix and determine where the absolute point is, factoring in the current transforms. Otherwise, the svgOrigin would be based on the element's non-transformed position on the canvas. 12936 a = m[0]; 12937 b = m[1]; 12938 c = m[2]; 12939 d = m[3]; 12940 tx = m[4]; 12941 ty = m[5]; 12942 determinant = a * d - b * c; 12943 if (determinant) { 12944 //if it's zero (like if scaleX and scaleY are zero), skip it to avoid errors with dividing by zero. 12945 x = xOrigin * (d / determinant) + yOrigin * (-c / determinant) + (c * ty - d * tx) / determinant; 12946 y = xOrigin * (-b / determinant) + yOrigin * (a / determinant) - (a * ty - b * tx) / determinant; 12947 xOrigin = decoratee.xOrigin = v[0] = x; 12948 yOrigin = decoratee.yOrigin = v[1] = y; 12949 } 12950 } 12951 if (tm) { 12952 //avoid jump when transformOrigin is changed - adjust the x/y values accordingly 12953 if (skipRecord) { 12954 decoratee.xOffset = tm.xOffset; 12955 decoratee.yOffset = tm.yOffset; 12956 tm = decoratee; 12957 } 12958 if (smoothOrigin || smoothOrigin !== false && _CSSPlugin.defaultSmoothOrigin !== false) { 12959 x = xOrigin - xOriginOld; 12960 y = yOrigin - yOriginOld; 12961 //originally, we simply adjusted the x and y values, but that would cause problems if, for example, you created a rotational tween part-way through an x/y tween. Managing the offset in a separate variable gives us ultimate flexibility. 12962 //tm.x -= x - (x * m[0] + y * m[2]); 12963 //tm.y -= y - (x * m[1] + y * m[3]); 12964 tm.xOffset += x * m[0] + y * m[2] - x; 12965 tm.yOffset += x * m[1] + y * m[3] - y; 12966 } else { 12967 tm.xOffset = tm.yOffset = 0; 12968 } 12969 } 12970 if (!skipRecord) { 12971 e.setAttribute("data-svg-origin", v.join(" ")); 12972 } 12973 }, 12974 _getBBoxHack2 = function _getBBoxHack(swapIfPossible) { 12975 //works around issues in some browsers (like Firefox) that don't correctly report getBBox() on SVG elements inside a <defs> element and/or <mask>. We try creating an SVG, adding it to the documentElement and toss the element in there so that it's definitely part of the rendering tree, then grab the bbox and if it works, we actually swap out the original getBBox() method for our own that does these extra steps whenever getBBox is needed. This helps ensure that performance is optimal (only do all these extra steps when absolutely necessary...most elements don't need it). 12976 var svg = _createElement("svg", this.ownerSVGElement && this.ownerSVGElement.getAttribute("xmlns") || "http://www.w3.org/2000/svg"), 12977 oldParent = this.parentNode, 12978 oldSibling = this.nextSibling, 12979 oldCSS = this.style.cssText, 12980 bbox; 12981 _docElement.appendChild(svg); 12982 svg.appendChild(this); 12983 this.style.display = "block"; 12984 if (swapIfPossible) { 12985 try { 12986 bbox = this.getBBox(); 12987 this._originalGetBBox = this.getBBox; 12988 this.getBBox = _getBBoxHack2; 12989 } catch (e) {} 12990 } else if (this._originalGetBBox) { 12991 bbox = this._originalGetBBox(); 12992 } 12993 if (oldSibling) { 12994 oldParent.insertBefore(this, oldSibling); 12995 } else { 12996 oldParent.appendChild(this); 12997 } 12998 _docElement.removeChild(svg); 12999 this.style.cssText = oldCSS; 13000 return bbox; 13001 }, 13002 _getBBox = function _getBBox(e) { 13003 try { 13004 return e.getBBox(); //Firefox throws errors if you try calling getBBox() on an SVG element that's not rendered (like in a <symbol> or <defs>). https://bugzilla.mozilla.org/show_bug.cgi?id=612118 13005 } catch (error) { 13006 return _getBBoxHack2.call(e, true); 13007 } 13008 }, 13009 _isSVG = function _isSVG(e) { 13010 //reports if the element is an SVG on which getBBox() actually works 13011 return !!(_SVGElement && e.getCTM && (!e.parentNode || e.ownerSVGElement) && _getBBox(e)); 13012 }, 13013 _identity2DMatrix = [1, 0, 0, 1, 0, 0], 13014 _getMatrix = function _getMatrix(e, force2D) { 13015 var tm = e._gsTransform || new Transform(), 13016 rnd = 100000, 13017 style = e.style, 13018 isDefault, 13019 s, 13020 m, 13021 n, 13022 dec, 13023 none; 13024 if (_transformProp) { 13025 s = _getStyle(e, _transformPropCSS, null, true); 13026 } else if (e.currentStyle) { 13027 //for older versions of IE, we need to interpret the filter portion that is in the format: progid:DXImageTransform.Microsoft.Matrix(M11=6.123233995736766e-17, M12=-1, M21=1, M22=6.123233995736766e-17, sizingMethod='auto expand') Notice that we need to swap b and c compared to a normal matrix. 13028 s = e.currentStyle.filter.match(_ieGetMatrixExp); 13029 s = s && s.length === 4 ? [s[0].substr(4), Number(s[2].substr(4)), Number(s[1].substr(4)), s[3].substr(4), tm.x || 0, tm.y || 0].join(",") : ""; 13030 }
13031 isDefault = !s || s === "none" || s === "matrix(1, 0, 0, 1, 0, 0)"; 13032 if (_transformProp && ((none = !_getComputedStyle(e) || _getComputedStyle(e).display === "none") || !e.parentNode)) { 13033 //note: Firefox returns null for getComputedStyle() if the element is in an iframe that has display:none. https://bugzilla.mozilla.org/show_bug.cgi?id=548397 13034 if (none) { 13035 //browsers don't report transforms accurately unless the element is in the DOM and has a display value that's not "none". Firefox and Microsoft browsers have a partial bug where they'll report transforms even if display:none BUT not any percentage-based values like translate(-50%, 8px) will be reported as if it's translate(0, 8px). 13036 n = style.display; 13037 style.display = "block"; 13038 } 13039 if (!e.parentNode) { 13040 dec = 1; //flag 13041 _docElement.appendChild(e); 13042 } 13043 s = _getStyle(e, _transformPropCSS, null, true); 13044 isDefault = !s || s === "none" || s === "matrix(1, 0, 0, 1, 0, 0)"; 13045 if (n) { 13046 style.display = n; 13047 } else if (none) { 13048 _removeProp(style, "display"); 13049 } 13050 if (dec) { 13051 _docElement.removeChild(e); 13052 } 13053 } 13054 if (tm.svg || e.getCTM && _isSVG(e)) { 13055 if (isDefault && (style[_transformProp] + "").indexOf("matrix") !== -1) { 13056 //some browsers (like Chrome 40) don't correctly report transforms that are applied inline on an SVG element (they don't get included in the computed style), so we double-check here and accept matrix values 13057 s = style[_transformProp]; 13058 isDefault = 0; 13059 } 13060 m = e.getAttribute("transform"); 13061 if (isDefault && m) { 13062 m = e.transform.baseVal.consolidate().matrix; //ensures that even complex values like "translate(50,60) rotate(135,0,0)" are parsed because it mashes it into a matrix. 13063 s = "matrix(" + m.a + "," + m.b + "," + m.c + "," + m.d + "," + m.e + "," + m.f + ")"; 13064 isDefault = 0; 13065 } 13066 } 13067 if (isDefault) { 13068 return _identity2DMatrix; 13069 } 13070 //split the matrix values out into an array (m for matrix) 13071 m = (s || "").match(_numExp) || []; 13072 i = m.length; 13073 while (--i > -1) { 13074 n = Number(m[i]); 13075 m[i] = (dec = n - (n |= 0)) ? (dec * rnd + (dec < 0 ? -0.5 : 0.5) | 0) / rnd + n : n; //convert strings to Numbers and round to 5 decimal places to avoid issues with tiny numbers. Roughly 20x faster than Number.toFixed(). We also must make sure to round before dividing so that values like 0.9999999999 become 1 to avoid glitches in browser rendering and interpretation of flipped/rotated 3D matrices. And don't just multiply the number by rnd, floor it, and then divide by rnd because the bitwise operations max out at a 32-bit signed integer, thus it could get clipped at a relatively low value (like 22,000.00000 for example). 13076 } 13077 return force2D && m.length > 6 ? [m[0], m[1], m[4], m[5], m[12], m[13]] : m; 13078 }, 13079 /** 13080 * Parses the transform values for an element, returning an object with x, y, z, scaleX, scaleY, scaleZ, rotation, rotationX, rotationY, skewX, and skewY properties. Note: by default (for performance reasons), all skewing is combined into skewX and rotation but skewY still has a place in the transform object so that we can record how much of the skew is attributed to skewX vs skewY. Remember, a skewY of 10 looks the same as a rotation of 10 and skewX of -10. 13081 * @param {!Object} t target element 13082 * @param {Object=} cs computed style object (optional) 13083 * @param {boolean=} rec if true, the transform values will be recorded to the target element's _gsTransform object, like target._gsTransform = {x:0, y:0, z:0, scaleX:1...} 13084 * @param {boolean=} parse if true, we'll ignore any _gsTransform values that already exist on the element, and force a reparsing of the css (calculated style) 13085 * @return {object}
13085 object containing all of the transform properties/values like {x:0, y:0, z:0, scaleX:1...} 13086 */ 13087 _getTransform = _internals.getTransform = function (t, cs, rec, parse) { 13088 if (t._gsTransform && rec && !parse) { 13089 return t._gsTransform; //if the element already has a _gsTransform, use that. Note: some browsers don't accurately return the calculated style for the transform (particularly for SVG), so it's almost always safest to just use the values we've already applied rather than re-parsing things. 13090 } 13091 var tm = rec ? t._gsTransform || new Transform() : new Transform(), 13092 invX = tm.scaleX < 0, 13093 //in order to interpret things properly, we need to know if the user applied a negative scaleX previously so that we can adjust the rotation and skewX accordingly. Otherwise, if we always interpret a flipped matrix as affecting scaleY and the user only wants to tween the scaleX on multiple sequential tweens, it would keep the negative scaleY without that being the user's intent. 13094 min = 0.00002, 13095 rnd = 100000, 13096 zOrigin = _supports3D ? parseFloat(_getStyle(t, _transformOriginProp, cs, false, "0 0 0").split(" ")[2]) || tm.zOrigin || 0 : 0, 13097 defaultTransformPerspective = parseFloat(_CSSPlugin.defaultTransformPerspective) || 0, 13098 m, 13099 i, 13100 scaleX, 13101 scaleY, 13102 rotation, 13103 skewX; 13104 tm.svg = !!(t.getCTM && _isSVG(t)); 13105 if (tm.svg) { 13106 _parseSVGOrigin(t, _getStyle(t, _transformOriginProp, cs, false, "50% 50%") + "", tm, t.getAttribute("data-svg-origin")); 13107 _useSVGTransformAttr = _CSSPlugin.useSVGTransformAttr || _forceSVGTransformAttr; 13108 } 13109 m = _getMatrix(t); 13110 if (m !== _identity2DMatrix) { 13111 if (m.length === 16) { 13112 //we'll only look at these position-related 6 variables first because if x/y/z all match, it's relatively safe to assume we don't need to re-parse everything which risks losing important rotational information (like rotationX:180 plus rotationY:180 would look the same as rotation:180 - there's no way to know for sure which direction was taken based solely on the matrix3d() values) 13113 var a11 = m[0], 13114 a21 = m[1], 13115 a31 = m[2], 13116 a41 = m[3], 13117 a12 = m[4], 13118 a22 = m[5], 13119 a32 = m[6], 13120 a42 = m[7], 13121 a13 = m[8], 13122 a23 = m[9], 13123 a33 = m[10], 13124 a14 = m[12], 13125 a24 = m[13], 13126 a34 = m[14], 13127 a43 = m[11], 13128 angle = Math.atan2(a32, a33), 13129 t1, 13130 t2, 13131 t3, 13132 t4, 13133 cos, 13134 sin; 13135 //we manually compensate for non-zero z component of transformOrigin to work around bugs in Safari 13136 if (tm.zOrigin) { 13137 a34 = -tm.zOrigin; 13138 a14 = a13 * a34 - m[12]; 13139 a24 = a23 * a34 - m[13]; 13140 a34 = a33 * a34 + tm.zOrigin - m[14]; 13141 } 13142 //note for possible future consolidation: rotationX: Math.atan2(a32, a33), rotationY: Math.atan2(-a31, Math.sqrt(a33 * a33 + a32 * a32)), rotation: Math.atan2(a21, a11), skew: Math.atan2(a12, a22). However, it doesn't seem to be quite as reliable as the full-on backwards rotation procedure. 13143 tm.rotationX = angle * _RAD2DEG; 13144 //rotationX 13145 if (angle) { 13146 cos = Math.cos(-angle); 13147 sin = Math.sin(-angle); 13148 t1 = a12 * cos + a13 * sin; 13149 t2 = a22 * cos + a23 * sin; 13150 t3 = a32 * cos + a33 * sin; 13151 a13 = a12 * -sin + a13 * cos; 13152 a23 = a22 * -sin + a23 * cos; 13153 a33 = a32 * -sin + a33 * cos; 13154 a43 = a42 * -sin + a43 * cos; 13155 a12 = t1; 13156 a22 = t2; 13157 a32 = t3; 13158 } 13159 //rotationY 13160 angle = Math.atan2(-a31, a33); 13161 tm.rotationY = angle * _RAD2DEG; 13162 if (angle) { 13163 cos = Math.cos(-angle); 13164 sin = Math.sin(-angle); 13165 t1 = a11 * cos - a13 * sin; 13166 t2 = a21 * cos - a23 * sin; 13167 t3 = a31 * cos - a33 * sin; 13168 a23 = a21 * sin + a23 * cos; 13169 a33 = a31 * sin + a33 * cos; 13170 a43 = a41 * sin + a43 * cos; 13171 a11 = t1; 13172 a21 = t2; 13173 a31 = t3; 13174 } 13175 //rotationZ 13176 angle = Math.atan2(a21, a11); 13177 tm.rotation = angle * _RAD2DEG; 13178 if (angle) { 13179 cos = Math.cos(angle); 13180 sin = Math.sin(angle); 13181 t1 = a11 * cos + a21 * sin; 13182 t2 = a12 * cos + a22 * sin; 13183 t3 = a13 * cos + a23 * sin; 13184 a21 = a21 * cos - a11 * sin; 13185 a22 = a22 * cos - a12 * sin; 13186 a23 = a23 * cos - a13 * sin; 13187 a11 = t1; 13188 a12 = t2; 13189 a13 = t3; 13190 } 13191 if (tm.rotationX && Math.abs(tm.rotationX) + Math.abs(tm.rotation) > 359.9) { 13192 //when rotationY is set, it will often be parsed as 180 degrees different than it should be, and rotationX and rotation both being 180 (it looks the same), so we adjust for that here. 13193 tm.rotationX = tm.rotation = 0; 13194 tm.rotationY = 180 - tm.rotationY; 13195 } 13196 13197 //skewX 13198 angle = Math.atan2(a12, a22); 13199 13200 //scales 13201 tm.scaleX = (Math.sqrt(a11 * a11 + a21 * a21 + a31 * a31) * rnd + 0.5 | 0) / rnd; 13202 tm.scaleY = (Math.sqrt(a22 * a22 + a32 * a32) * rnd + 0.5 | 0) / rnd; 13203 tm.scaleZ = (Math.sqrt(a13 * a13 + a23 * a23 + a33 * a33) * rnd + 0.5 | 0) / rnd; 13204 a11 /= tm.scaleX; 13205 a12 /= tm.scaleY; 13206 a21 /= tm.scaleX; 13207 a22 /= tm.scaleY; 13208 if (Math.abs(angle) > min) { 13209 tm.skewX = angle * _RAD2DEG; 13210 a12 = 0;
13210 //unskews 13211 if (tm.skewType !== "simple") { 13212 tm.scaleY *= 1 / Math.cos(angle); //by default, we compensate the scale based on the skew so that the element maintains a similar proportion when skewed, so we have to alter the scaleY here accordingly to match the default (non-adjusted) skewing that CSS does (stretching more and more as it skews). 13213 } 13214 } else { 13215 tm.skewX = 0; 13216 } 13217 13218 /* //for testing purposes 13219 var transform = "matrix3d(", 13220 comma = ",", 13221 zero = "0"; 13222 a13 /= tm.scaleZ; 13223 a23 /= tm.scaleZ; 13224 a31 /= tm.scaleX; 13225 a32 /= tm.scaleY; 13226 a33 /= tm.scaleZ; 13227 transform += ((a11 < min && a11 > -min) ? zero : a11) + comma + ((a21 < min && a21 > -min) ? zero : a21) + comma + ((a31 < min && a31 > -min) ? zero : a31); 13228 transform += comma + ((a41 < min && a41 > -min) ? zero : a41) + comma + ((a12 < min && a12 > -min) ? zero : a12) + comma + ((a22 < min && a22 > -min) ? zero : a22); 13229 transform += comma + ((a32 < min && a32 > -min) ? zero : a32) + comma + ((a42 < min && a42 > -min) ? zero : a42) + comma + ((a13 < min && a13 > -min) ? zero : a13); 13230 transform += comma + ((a23 < min && a23 > -min) ? zero : a23) + comma + ((a33 < min && a33 > -min) ? zero : a33) + comma + ((a43 < min && a43 > -min) ? zero : a43) + comma; 13231 transform += a14 + comma + a24 + comma + a34 + comma + (tm.perspective ? (1 + (-a34 / tm.perspective)) : 1) + ")"; 13232 console.log(transform); 13233 document.querySelector(".test").style[_transformProp] = transform; 13234 */ 13235 13236 tm.perspective = a43 ? 1 / (a43 < 0 ? -a43 : a43) : 0; 13237 tm.x = a14; 13238 tm.y = a24; 13239 tm.z = a34; 13240 if (tm.svg) { 13241 tm.x -= tm.xOrigin - (tm.xOrigin * a11 - tm.yOrigin * a12); 13242 tm.y -= tm.yOrigin - (tm.yOrigin * a21 - tm.xOrigin * a22); 13243 } 13244 } else if (!_supports3D || parse || !m.length || tm.x !== m[4] || tm.y !== m[5] || !tm.rotationX && !tm.rotationY) { 13245 //sometimes a 6-element matrix is returned even when we performed 3D transforms, like if rotationX and rotationY are 180. In cases like this, we still need to honor the 3D transforms. If we just rely on the 2D info, it could affect how the data is interpreted, like scaleY might get set to -1 or rotation could get offset by 180 degrees. For example, do a TweenLite.to(element, 1, {css:{rotationX:180, rotationY:180}}) and then later, TweenLite.to(element, 1, {css:{rotationX:0}}) and without this conditional logic in place, it'd jump to a state of being unrotated when the 2nd tween starts. Then again, we need to honor the fact that the user COULD alter the transforms outside of CSSPlugin, like by manually applying new css, so we try to sense that by looking at x and y because if those changed, we know the changes were made outside CSSPlugin and we force a reinterpretation of the matrix values. Also, in Webkit browsers, if the element's "display" is "none", its calculated style value will always return empty, so if we've already recorded the values in the _gsTransform object, we'll just rely on those. 13246 var k = m.length >= 6, 13247 a = k ? m[0] : 1, 13248 b = m[1] || 0, 13249 c = m[2] || 0, 13250 d = k ? m[3] : 1; 13251 tm.x = m[4] || 0; 13252 tm.y = m[5] || 0; 13253 scaleX = Math.sqrt(a * a + b * b); 13254 scaleY = Math.sqrt(d * d + c * c); 13255 rotation = a || b ? Math.atan2(b, a) * _RAD2DEG : tm.rotation || 0; //note: if scaleX is 0, we cannot accurately measure rotation. Same for skewX with a scaleY of 0. Therefore, we default to the previously recorded value (or zero if that doesn't exist). 13256 skewX = c || d ? Math.atan2(c, d) * _RAD2DEG + rotation : tm.skewX || 0; 13257 tm.scaleX = scaleX; 13258 tm.scaleY = scaleY; 13259 tm.rotation = rotation; 13260 tm.skewX = skewX; 13261 if (_supports3D) { 13262 tm.rotationX = tm.rotationY = tm.z = 0; 13263 tm.perspective = defaultTransformPerspective; 13264 tm.scaleZ = 1; 13265 } 13266 if (tm.svg) { 13267 tm.x -= tm.xOrigin - (tm.xOrigin * a + tm.yOrigin * c); 13268 tm.y -= tm.yOrigin - (tm.xOrigin * b + tm.yOrigin * d); 13269 } 13270 } 13271 if (Math.abs(tm.skewX) > 90 && Math.abs(tm.skewX) < 270) { 13272 if (invX) { 13273 tm.scaleX *= -1; 13274 tm.skewX += tm.rotation <= 0 ? 180 : -180; 13275 tm.rotation += tm.rotation <= 0 ? 180 : -180; 13276 } else { 13277 tm.scaleY *= -1; 13278 tm.skewX += tm.skewX <= 0 ? 180 : -180; 13279 } 13280 } 13281 tm.zOrigin = zOrigin;
13282 //some browsers have a hard time with very small values like 2.4492935982947064e-16 (notice the "e-" towards the end) and would render the object slightly off. So we round to 0 in these cases. The conditional logic here is faster than calling Math.abs(). Also, browsers tend to render a SLIGHTLY rotated object in a fuzzy way, so we need to snap to exactly 0 when appropriate. 13283 for (i in tm) { 13284 if (tm[i] < min) if (tm[i] > -min) { 13285 tm[i] = 0; 13286 } 13287 } 13288 } 13289 //DEBUG: _log("parsed rotation of " + t.getAttribute("id")+": "+(tm.rotationX)+", "+(tm.rotationY)+", "+(tm.rotation)+", scale: "+tm.scaleX+", "+tm.scaleY+", "+tm.scaleZ+", position: "+tm.x+", "+tm.y+", "+tm.z+", perspective: "+tm.perspective+ ", origin: "+ tm.xOrigin+ ","+ tm.yOrigin); 13290 if (rec) { 13291 t._gsTransform = tm; //record to the object's _gsTransform which we use so that tweens can control individual properties independently (we need all the properties to accurately recompose the matrix in the setRatio() method) 13292 if (tm.svg) { 13293 //if we're supposed to apply transforms to the SVG element's "transform" attribute, make sure there aren't any CSS transforms applied or they'll override the attribute ones. Also clear the transform attribute if we're using CSS, just to be clean. 13294 if (_useSVGTransformAttr && t.style[_transformProp]) { 13295 TweenLite.delayedCall(0.001, function () { 13296 //if we apply this right away (before anything has rendered), we risk there being no transforms for a brief moment and it also interferes with adjusting the transformOrigin in a tween with immediateRender:true (it'd try reading the matrix and it wouldn't have the appropriate data in place because we just removed it). 13297 _removeProp(t.style, _transformProp); 13298 }); 13299 } else if (!_useSVGTransformAttr && t.getAttribute("transform")) { 13300 TweenLite.delayedCall(0.001, function () { 13301 t.removeAttribute("transform"); 13302 }); 13303 } 13304 } 13305 } 13306 return tm; 13307 }, 13308 //for setting 2D transforms in IE6, IE7, and IE8 (must use a "filter" to emulate the behavior of modern day browser transforms) 13309 _setIETransformRatio = function _setIETransformRatio(v) { 13310 var t = this.data, 13311 //refers to the element's _gsTransform object 13312 ang = -t.rotation * _DEG2RAD, 13313 skew = ang + t.skewX * _DEG2RAD, 13314 rnd = 100000, 13315 a = (Math.cos(ang) * t.scaleX * rnd | 0) / rnd, 13316 b = (Math.sin(ang) * t.scaleX * rnd | 0) / rnd, 13317 c = (Math.sin(skew) * -t.scaleY * rnd | 0) / rnd, 13318 d = (Math.cos(skew) * t.scaleY * rnd | 0) / rnd, 13319 style = this.t.style, 13320 cs = this.t.currentStyle, 13321 filters, 13322 val; 13323 if (!cs) { 13324 return; 13325 } 13326 val = b; //just for swapping the variables an inverting them (reused "val" to avoid creating another variable in memory). IE's filter matrix uses a non-standard matrix configuration (angle goes the opposite way, and b and c are reversed and inverted) 13327 b = -c; 13328 c = -val; 13329 filters = cs.filter; 13330 style.filter = ""; //remove filters so that we can accurately measure offsetWidth/offsetHeight 13331 var w = this.t.offsetWidth, 13332 h = this.t.offsetHeight, 13333 clip = cs.position !== "absolute", 13334 m = "progid:DXImageTransform.Microsoft.Matrix(M11=" + a + ", M12=" + b + ", M21=" + c + ", M22=" + d, 13335 ox = t.x + w * t.xPercent / 100, 13336 oy = t.y + h * t.yPercent / 100, 13337 dx, 13338 dy; 13339 13340 //if transformOrigin is being used, adjust the offset x and y 13341 if (t.ox != null) { 13342 dx = (t.oxp ? w * t.ox * 0.01 : t.ox) - w / 2; 13343 dy = (t.oyp ? h * t.oy * 0.01 : t.oy) - h / 2; 13344 ox += dx - (dx * a + dy * b); 13345 oy += dy - (dx * c + dy * d); 13346 } 13347 if (!clip) { 13348 m += ", sizingMethod='auto expand')"; 13349 } else { 13350 dx = w / 2; 13351 dy = h / 2; 13352 //translate to ensure that transformations occur around the correct origin (default is center). 13353 m += ", Dx=" + (dx - (dx * a + dy * b) + ox) + ", Dy=" + (dy - (dx * c + dy * d) + oy) + ")"; 13354 } 13355 if (filters.indexOf("DXImageTransform.Microsoft.Matrix(") !== -1) {
13356 style.filter = filters.replace(_ieSetMatrixExp, m); 13357 } else { 13358 style.filter = m + " " + filters; //we must always put the transform/matrix FIRST (before alpha(opacity=xx)) to avoid an IE bug that slices part of the object when rotation is applied with alpha. 13359 } 13360 13361 //at the end or beginning of the tween, if the matrix is normal (1, 0, 0, 1) and opacity is 100 (or doesn't exist), remove the filter to improve browser performance. 13362 if (v === 0 || v === 1) if (a === 1) if (b === 0) if (c === 0) if (d === 1) if (!clip || m.indexOf("Dx=0, Dy=0") !== -1) if (!_opacityExp.test(filters) || parseFloat(RegExp.$1) === 100) if (filters.indexOf("gradient(" && filters.indexOf("Alpha")) === -1) { 13363 style.removeAttribute("filter"); 13364 } 13365 13366 //we must set the margins AFTER applying the filter in order to avoid some bugs in IE8 that could (in rare scenarios) cause them to be ignored intermittently (vibration). 13367 if (!clip) { 13368 var mult = _ieVers < 8 ? 1 : -1, 13369 //in Internet Explorer 7 and before, the box model is broken, causing the browser to treat the width/height of the actual rotated filtered image as the width/height of the box itself, but Microsoft corrected that in IE8. We must use a negative offset in IE8 on the right/bottom 13370 marg, 13371 prop, 13372 dif; 13373 dx = t.ieOffsetX || 0; 13374 dy = t.ieOffsetY || 0; 13375 t.ieOffsetX = Math.round((w - ((a < 0 ? -a : a) * w + (b < 0 ? -b : b) * h)) / 2 + ox); 13376 t.ieOffsetY = Math.round((h - ((d < 0 ? -d : d) * h + (c < 0 ? -c : c) * w)) / 2 + oy); 13377 for (i = 0; i < 4; i++) { 13378 prop = _margins[i]; 13379 marg = cs[prop]; 13380 //we need to get the current margin in case it is being tweened separately (we want to respect that tween's changes) 13381 val = marg.indexOf("px") !== -1 ? parseFloat(marg) : _convertToPixels(this.t, prop, parseFloat(marg), marg.replace(_suffixExp, "")) || 0; 13382 if (val !== t[prop]) { 13383 dif = i < 2 ? -t.ieOffsetX : -t.ieOffsetY; //if another tween is controlling a margin, we cannot only apply the difference in the ieOffsets, so we essentially zero-out the dx and dy here in that case. We record the margin(s) later so that we can keep comparing them, making this code very flexible. 13384 } else { 13385 dif = i < 2 ? dx - t.ieOffsetX : dy - t.ieOffsetY; 13386 } 13387 style[prop] = (t[prop] = Math.round(val - dif * (i === 0 || i === 2 ? 1 : mult))) + "px"; 13388 } 13389 } 13390 }, 13391 /* translates a super small decimal to a string WITHOUT scientific notation 13392 _safeDecimal = function(n) { 13393 var s = (n < 0 ? -n : n) + "", 13394 a = s.split("e-"); 13395 return (n < 0 ? "-0." : "0.") + new Array(parseInt(a[1], 10) || 0).join("0") + a[0].split(".").join(""); 13396 }, 13397 */ 13398 13399 _setTransformRatio = _internals.set3DTransformRatio = _internals.setTransformRatio = function (v) { 13400 var t = this.data, 13401 //refers to the element's _gsTransform object 13402 style = this.t.style, 13403 angle = t.rotation, 13404 rotationX = t.rotationX, 13405 rotationY = t.rotationY, 13406 sx = t.scaleX, 13407 sy = t.scaleY, 13408 sz = t.scaleZ, 13409 x = t.x, 13410 y = t.y, 13411 z = t.z, 13412 isSVG = t.svg, 13413 perspective = t.perspective, 13414 force3D = t.force3D, 13415 skewY = t.skewY, 13416 skewX = t.skewX, 13417 t1, 13418 a11, 13419 a12, 13420 a13, 13421 a21, 13422 a22, 13423 a23, 13424 a31, 13425 a32, 13426 a33, 13427 a41, 13428 a42, 13429 a43, 13430 zOrigin, 13431 min, 13432 cos, 13433 sin, 13434 t2, 13435 transform, 13436 comma, 13437 zero, 13438 skew, 13439 rnd; 13440 if (skewY) { 13441 //for performance reasons, we combine all skewing into the skewX and rotation values. Remember, a skewY of 10 degrees looks the same as a rotation of 10 degrees plus a skewX of 10 degrees. 13442 skewX += skewY; 13443 angle += skewY; 13444 } 13445 13446 //check to see if we should render as 2D (and SVGs must use 2D when _useSVGTransformAttr is true) 13447 if (((v === 1 || v === 0) && force3D === "auto" && (this.tween._totalTime === this.tween._totalDuration || !this.tween._totalTime) || !force3D) && !z && !perspective && !rotationY && !rotationX && sz === 1 || _useSVGTransformAttr && isSVG || !_supports3D) { 13448 //on the final render (which could be 0 for a from tween), if there are no 3D aspects, render in 2D to free up memory and improve performance especially on mobile devices. Check the tween's totalTime/totalDuration too in order to make sure it doesn't happen between repeats if it's a repeating tween. 13449 13450 //2D 13451 if (angle || skewX || isSVG) { 13452 angle *= _DEG2RAD; 13453 skew = skewX * _DEG2RAD; 13454 rnd = 100000; 13455 a11 = Math.cos(angle) * sx; 13456 a21 = Math.sin(angle) * sx; 13457 a12 = Math.sin(angle - skew) * -sy;
13458 a22 = Math.cos(angle - skew) * sy; 13459 if (skew && t.skewType === "simple") { 13460 //by default, we compensate skewing on the other axis to make it look more natural, but you can set the skewType to "simple" to use the uncompensated skewing that CSS does 13461 t1 = Math.tan(skew - skewY * _DEG2RAD); 13462 t1 = Math.sqrt(1 + t1 * t1); 13463 a12 *= t1; 13464 a22 *= t1; 13465 if (skewY) { 13466 t1 = Math.tan(skewY * _DEG2RAD); 13467 t1 = Math.sqrt(1 + t1 * t1); 13468 a11 *= t1; 13469 a21 *= t1; 13470 } 13471 } 13472 if (isSVG) { 13473 x += t.xOrigin - (t.xOrigin * a11 + t.yOrigin * a12) + t.xOffset; 13474 y += t.yOrigin - (t.xOrigin * a21 + t.yOrigin * a22) + t.yOffset; 13475 if (_useSVGTransformAttr && (t.xPercent || t.yPercent)) { 13476 //The SVG spec doesn't support percentage-based translation in the "transform" attribute, so we merge it into the matrix to simulate it. 13477 min = this.t.getBBox(); 13478 x += t.xPercent * 0.01 * min.width; 13479 y += t.yPercent * 0.01 * min.height; 13480 } 13481 min = 0.000001; 13482 if (x < min) if (x > -min) { 13483 x = 0; 13484 } 13485 if (y < min) if (y > -min) { 13486 y = 0; 13487 } 13488 } 13489 transform = (a11 * rnd | 0) / rnd + "," + (a21 * rnd | 0) / rnd + "," + (a12 * rnd | 0) / rnd + "," + (a22 * rnd | 0) / rnd + "," + x + "," + y + ")"; 13490 if (isSVG && _useSVGTransformAttr) {
13491 this.t.setAttribute("transform", "matrix(" + transform); 13492 } else { 13493 //some browsers have a hard time with very small values like 2.4492935982947064e-16 (notice the "e-" towards the end) and would render the object slightly off. So we round to 5 decimal places. 13494 style[_transformProp] = (t.xPercent || t.yPercent ? "translate(" + t.xPercent + "%," + t.yPercent + "%) matrix(" : "matrix(") + transform; 13495 } 13496 } else { 13497 style[_transformProp] = (t.xPercent || t.yPercent ? "translate(" + t.xPercent + "%," + t.yPercent + "%) matrix(" : "matrix(") + sx + ",0,0," + sy + "," + x + "," + y + ")"; 13498 } 13499 return; 13500 } 13501 if (_isFirefox) { 13502 //Firefox has a bug (at least in v25) that causes it to render the transparent part of 32-bit PNG images as black when displayed inside an iframe and the 3D scale is very small and doesn't change sufficiently enough between renders (like if you use a Power4.easeInOut to scale from 0 to 1 where the beginning values only change a tiny amount to begin the tween before accelerating). In this case, we force the scale to be 0.00002 instead which is visually the same but works around the Firefox issue. 13503 min = 0.0001; 13504 if (sx < min && sx > -min) { 13505 sx = sz = 0.00002; 13506 } 13507 if (sy < min && sy > -min) { 13508 sy = sz = 0.00002; 13509 } 13510 if (perspective && !t.z && !t.rotationX && !t.rotationY) { 13511 //Firefox has a bug that causes elements to have an odd super-thin, broken/dotted black border on elements that have a perspective set but aren't utilizing 3D space (no rotationX, rotationY, or z). 13512 perspective = 0; 13513 } 13514 } 13515 if (angle || skewX) { 13516 angle *= _DEG2RAD; 13517 cos = a11 = Math.cos(angle); 13518 sin = a21 = Math.sin(angle); 13519 if (skewX) { 13520 angle -= skewX * _DEG2RAD; 13521 cos = Math.cos(angle); 13522 sin = Math.sin(angle); 13523 if (t.skewType === "simple") { 13524 //by default, we compensate skewing on the other axis to make it look more natural, but you can set the skewType to "simple" to use the uncompensated skewing that CSS does 13525 t1 = Math.tan((skewX - skewY) * _DEG2RAD); 13526 t1 = Math.sqrt(1 + t1 * t1); 13527 cos *= t1; 13528 sin *= t1; 13529 if (t.skewY) { 13530 t1 = Math.tan(skewY * _DEG2RAD); 13531 t1 = Math.sqrt(1 + t1 * t1); 13532 a11 *= t1; 13533 a21 *= t1; 13534 } 13535 } 13536 } 13537 a12 = -sin; 13538 a22 = cos; 13539 } else if (!rotationY && !rotationX && sz === 1 && !perspective && !isSVG) { 13540 //if we're only translating and/or 2D scaling, this is faster... 13541 style[_transformProp] = (t.xPercent || t.yPercent ? "translate(" + t.xPercent + "%," + t.yPercent + "%) translate3d(" : "translate3d(") + x + "px," + y + "px," + z + "px)" + (sx !== 1 || sy !== 1 ? " scale(" + sx + "," + sy + ")" : ""); 13542 return; 13543 } else { 13544 a11 = a22 = 1; 13545 a12 = a21 = 0; 13546 } 13547 // KEY INDEX AFFECTS a[row][column] 13548 // a11 0 rotation, rotationY, scaleX 13549 // a21 1 rotation, rotationY, scaleX 13550 // a31 2 rotationY, scaleX 13551 // a41 3 rotationY, scaleX 13552 // a12 4 rotation, skewX, rotationX, scaleY 13553 // a22 5 rotation, skewX, rotationX, scaleY 13554 // a32 6 rotationX, scaleY 13555 // a42 7 rotationX, scaleY 13556 // a13 8 rotationY, rotationX, scaleZ 13557 // a23 9 rotationY, rotationX, scaleZ 13558 // a33 10 rotationY, rotationX, scaleZ 13559 // a43 11 rotationY, rotationX, perspective, scaleZ 13560 // a14 12 x, zOrigin, svgOrigin 13561 // a24 13 y, zOrigin, svgOrigin 13562 // a34 14 z, zOrigin 13563 // a44 15 13564 // rotation: Math.atan2(a21, a11) 13565 // rotationY: Math.atan2(a13, a33) (or Math.atan2(a13, a11)) 13566 // rotationX: Math.atan2(a32, a33) 13567 a33 = 1; 13568 a13 = a23 = a31 = a32 = a41 = a42 = 0; 13569 a43 = perspective ? -1 / perspective : 0; 13570 zOrigin = t.zOrigin; 13571 min = 0.000001; //threshold below which browsers use scientific notation which w
13571on't work. 13572 comma = ","; 13573 zero = "0"; 13574 angle = rotationY * _DEG2RAD; 13575 if (angle) { 13576 cos = Math.cos(angle); 13577 sin = Math.sin(angle); 13578 a31 = -sin; 13579 a41 = a43 * -sin; 13580 a13 = a11 * sin; 13581 a23 = a21 * sin; 13582 a33 = cos; 13583 a43 *= cos; 13584 a11 *= cos; 13585 a21 *= cos; 13586 } 13587 angle = rotationX * _DEG2RAD; 13588 if (angle) { 13589 cos = Math.cos(angle); 13590 sin = Math.sin(angle); 13591 t1 = a12 * cos + a13 * sin; 13592 t2 = a22 * cos + a23 * sin; 13593 a32 = a33 * sin; 13594 a42 = a43 * sin; 13595 a13 = a12 * -sin + a13 * cos; 13596 a23 = a22 * -sin + a23 * cos; 13597 a33 = a33 * cos; 13598 a43 = a43 * cos; 13599 a12 = t1; 13600 a22 = t2; 13601 } 13602 if (sz !== 1) { 13603 a13 *= sz; 13604 a23 *= sz; 13605 a33 *= sz; 13606 a43 *= sz; 13607 } 13608 if (sy !== 1) { 13609 a12 *= sy; 13610 a22 *= sy; 13611 a32 *= sy; 13612 a42 *= sy; 13613 } 13614 if (sx !== 1) { 13615 a11 *= sx; 13616 a21 *= sx; 13617 a31 *= sx; 13618 a41 *= sx; 13619 } 13620 if (zOrigin || isSVG) { 13621 if (zOrigin) { 13622 x += a13 * -zOrigin; 13623 y += a23 * -zOrigin; 13624 z += a33 * -zOrigin + zOrigin; 13625 } 13626 if (isSVG) { 13627 //due to bugs in some browsers, we need to manage the transform-origin of SVG manually 13628 x += t.xOrigin - (t.xOrigin * a11 + t.yOrigin * a12) + t.xOffset; 13629 y += t.yOrigin - (t.xOrigin * a21 + t.yOrigin * a22) + t.yOffset; 13630 } 13631 if (x < min && x > -min) { 13632 x = zero; 13633 } 13634 if (y < min && y > -min) { 13635 y = zero; 13636 } 13637 if (z < min && z > -min) { 13638 z = 0; //don't use string because we calculate perspective later and need the number. 13639 } 13640 } 13641 13642 //optimized way of concatenating all the values into a string. If we do it all in one shot, it's slower because of the way browsers have to create temp strings and the way it affects memory. If we do it piece-by-piece with +=, it's a bit slower too. We found that doing it in these sized chunks works best overall: 13643 transform = t.xPercent || t.yPercent ? "translate(" + t.xPercent + "%," + t.yPercent + "%) matrix3d(" : "matrix3d("; 13644 transform += (a11 < min && a11 > -min ? zero : a11) + comma + (a21 < min && a21 > -min ? zero : a21) + comma + (a31 < min && a31 > -min ? zero : a31); 13645 transform += comma + (a41 < min && a41 > -min ? zero : a41) + comma + (a12 < min && a12 > -min ? zero : a12) + comma + (a22 < min && a22 > -min ? zero : a22); 13646 if (rotationX || rotationY || sz !== 1) { 13647 //performance optimization (often there's no rotationX or rotationY, so we can skip these calculations) 13648 transform += comma + (a32 < min && a32 > -min ? zero : a32) + comma + (a42 < min && a42 > -min ? zero : a42) + comma + (a13 < min && a13 > -min ? zero : a13); 13649 transform += comma + (a23 < min && a23 > -min ? zero : a23) + comma + (a33 < min && a33 > -min ? zero : a33) + comma + (a43 < min && a43 > -min ? zero : a43) + comma; 13650 } else { 13651 transform += ",0,0,0,0,1,0,"; 13652 } 13653 transform += x + comma + y + comma + z + comma + (perspective ? 1 + -z / perspective : 1) + ")"; 13654 style[_transformProp] = transform; 13655 }; 13656 p = Transform.prototype; 13657 p.x = p.y = p.z = p.skewX = p.skewY = p.rotation = p.rotationX = p.rotationY = p.zOrigin = p.xPercent = p.yPercent = p.xOffset = p.yOffset = 0; 13658 p.scaleX = p.scaleY = p.scaleZ = 1; 13659 _registerComplexSpecialProp("transform,scale,scaleX,scaleY,scaleZ,x,y,z,rotation,rotationX,rotationY,rotationZ,skewX,skewY,shortRotation,shortRotationX,shortRotationY,shortRotationZ,transformOrigin,svgOrigin,transformPerspective,directionalRotation,parseTransform,force3D,skewType,xPercent,yPercent,smoothOrigin", { 13660 parser: function parser(t, e, parsingProp, cssp, pt, plugin, vars) { 13661 if (cssp._lastParsedTransform === vars) { 13662 return pt; 13663 } //only need to parse the transform once, and only if the browser supports it. 13664 cssp._lastParsedTransform = vars; 13665 var scaleFunc = vars.scale && typeof vars.scale === "function" ? vars.scale : 0, 13666 //if there's a function-based "scale" value, swap in the resulting numeric value temporarily. Otherwise, if it's called for both scaleX and scaleY independently, they may not match (like if the function uses Math.random()). 13667 swapFunc; 13668 if (typeof vars[parsingProp] === "function") { 13669 //whatever property triggers the initial parsing might be a function-based value in which case it already got called in parse(), thus we don't want to call it again in here. The most efficient way to avoid this is to temporarily swap the value directly into the vars object, and then after we do all our parsing in this function, we'll swap it back again. 13670 swapFunc = vars[parsingProp]; 13671 vars[parsingProp] = e; 13672 } 13673 if (scaleFunc) { 13674 vars.scale = scaleFunc(_index, t); 13675 } 13676 var originalGSTransform = t._gsTransform, 13677 style = t.style, 13678 min = 0.000001, 13679 i = _transformProps.length, 13680 v = vars, 13681 endRotations = {}, 13682 transformOriginString = "transformOrigin", 13683 m1 = _getTransform(t, _cs, true, v.parseTransform), 13684 orig = v.transform && (typeof v.transform === "function" ? v.transform(_index, _target) : v.transform), 13685 m2, 13686 copy, 13687 has3D, 13688 hasChange, 13689 dr, 13690 x, 13691 y, 13692 matrix, 13693 p; 13694 m1.skewType = v.skewType || m1.skewType || _CSSPlugin.defaultSkewType; 13695 cssp._transform = m1; 13696 if (orig && typeof orig === "string" && _transformProp) { 13697 //for values like transform:"rotate(60deg) scale(0.5, 0.8)" 13698 copy = _tempDiv.style; //don't use the original target because it might be SVG in which case some browsers don't report computed style correctly. 13699 copy[_transformProp] = orig; 13700 copy.display = "block"; //if display is "none", the browser often refuses to report the transform properties correctly. 13701 copy.position = "absolute"; 13702 _doc.body.appendChild(_tempDiv); 13703 m2 = _getTransform(_tempDiv, null, false); 13704 if (m1.skewType === "simple") { 13705 //the default _getTransform() reports the skewX/scaleY as if skewType is "compensated", thus we need to adjust that here if skewType is "simple". 13706 m2.scaleY *= Math.cos(m2.skewX * _DEG2RAD); 13707 } 13708 if (m1.svg) { 13709 //if it's an SVG element, x/y part of the matrix will be affected by whatever we use as the origin and the offsets, so compensate here... 13710 x = m1.xOrigin; 13711 y = m1.yOrigin; 13712 m2.x -= m1.xOffset; 13713 m2.y -= m1.yOffset; 13714 if (v.transformOrigin || v.svgOrigin) { 13715 //if this tween is altering the origin, we must factor that in here. The actual work of recording the transformOrigin values and setting up the PropTween is done later (still inside this function) so we cannot leave the changes intact here - we only want to update the x/y accordingly. 13716 orig = {}; 13717 _parseSVGOrigin(t, _parsePosition2(v.transformOrigin), orig, v.svgOrigin, v.smoothOrigin, true); 13718 x = orig.xOrigin; 13719 y = orig.yOrigin; 13720 m2.x -= orig.xOffset - m1.xOffset; 13721 m2.y -= orig.yOffset - m1.yOffset; 13722 } 13723 if (x || y) { 13724 matrix = _getMatrix(_tempDiv, true); 13725 m2.x -= x - (x * matrix[0] + y * matrix[2]); 13726 m2.y -= y - (x * matrix[1] + y * matrix[3]); 13727 } 13728 } 13729 _doc.body.removeChild(_tempDiv); 13730 if (!m2.perspective) { 13731 m2.perspective = m1.perspective; //tweening to no perspective gives very unintuitive results - just keep the same perspective in that case. 13732 } 13733 if (v.xPercent != null) { 13734 m2.xPercent = _parseVal(v.xPercent, m1.xPercent); 13735 } 13736 if (v.yPercent != null) { 13737 m2.yPercent = _parseVal(v.yPercent, m1.yPercent); 13738 } 13739 } else if (_typeof(v) === "object") { 13740 //for values like scaleX, scaleY, rotation, x, y, skewX, and skewY or transform:{...} (object) 13741 m2 = { 13742 scaleX: _parseVal(v.scaleX != null ? v.scaleX : v.scale, m1.scaleX), 13743 scaleY: _parseVal(v.scaleY != null ? v.scaleY : v.scale, m1.scaleY), 13744 scaleZ: _parseVal(v.scaleZ, m1.scaleZ), 13745 x: _parseVal(v.x, m1.x), 13746 y: _parseVal(v.y, m1.y), 13747 z: _parseVal(v.z, m1.z), 13748 xPercent: _parseVal(v.xPercent, m1.xPercent), 13749 yPercent: _parseVal(v.yPercent, m1.yPercent), 13750 perspective: _parseVal(v.transformPerspective, m1.perspective) 13751 }; 13752 dr = v.directionalRotation; 13753 if (dr != null) { 13754 if (_typeof(dr) === "object") { 13755 for (copy in dr) { 13756 v[copy] = dr[copy]; 13757 } 13758 } else { 13759 v.rotation = dr; 13760 } 13761 } 13762 if (typeof v.x === "string" && v.x.indexOf("%") !== -1) { 13763 m2.x = 0; 13764 m2.xPercent = _parseVal(v.x, m1.xPercent); 13765 } 13766 if (typeof v.y === "string" && v.y.indexOf("%") !== -1) { 13767 m2.y = 0; 13768 m2.yPercent = _parseVal(v.y, m1.yPercent); 13769 } 13770 m2.rotation = _parseAngle("rotation" in v ? v.rotation : "shortRotation" in v ? v.shortRotation + "_short" : "rotationZ" in v ? v.rotationZ : m1.rotation, m1.rotation, "rotation", endRotations); 13771 if (_supports3D) { 13772 m2.rotationX = _parseAngle("rotationX" in v ? v.rotationX : "shortRotationX" in v ? v.shortRotationX + "_short" : m1.rotationX || 0, m1.rotationX, "rotationX", endRotations); 13773 m2.rotationY = _parseAngle("rotationY" in v ? v.rotationY : "shortRotationY" in v ? v.shortRotationY + "_short" : m1.rotationY || 0, m1.rotationY, "rotationY", endRotations); 13774 }
13775 m2.skewX = _parseAngle(v.skewX, m1.skewX); 13776 m2.skewY = _parseAngle(v.skewY, m1.skewY); 13777 } 13778 if (_supports3D && v.force3D != null) { 13779 m1.force3D = v.force3D; 13780 hasChange = true; 13781 } 13782 has3D = m1.force3D || m1.z || m1.rotationX || m1.rotationY || m2.z || m2.rotationX || m2.rotationY || m2.perspective; 13783 if (!has3D && v.scale != null) { 13784 m2.scaleZ = 1; //no need to tween scaleZ. 13785 } 13786 while (--i > -1) { 13787 p = _transformProps[i]; 13788 orig = m2[p] - m1[p]; 13789 if (orig > min || orig < -min || v[p] != null || _forcePT[p] != null) { 13790 hasChange = true; 13791 pt = new CSSPropTween(m1, p, m1[p], orig, pt); 13792 if (p in endRotations) { 13793 pt.e = endRotations[p]; //directional rotations typically have compensated values during the tween, but we need to make sure they end at exactly what the user requested 13794 } 13795 pt.xs0 = 0; //ensures the value stays numeric in setRatio() 13796 pt.plugin = plugin; 13797 cssp._overwriteProps.push(pt.n); 13798 } 13799 } 13800 orig = v.transformOrigin; 13801 if (m1.svg && (orig || v.svgOrigin)) { 13802 x = m1.xOffset; //when we change the origin, in order to prevent things from jumping we adjust the x/y so we must record those here so that we can create PropTweens for them and flip them at the same time as the origin 13803 y = m1.yOffset; 13804 _parseSVGOrigin(t, _parsePosition2(orig), m2, v.svgOrigin, v.smoothOrigin); 13805 pt = _addNonTweeningNumericPT(m1, "xOrigin", (originalGSTransform ? m1 : m2).xOrigin, m2.xOrigin, pt, transformOriginString); //note: if there wasn't a transformOrigin defined yet, just start with the destination one; it's wasteful otherwise, and it causes problems with fromTo() tweens. For example, TweenLite.to("#wheel", 3, {rotation:180, transformOrigin:"50% 50%", delay:1}); TweenLite.fromTo("#wheel", 3, {scale:0.5, transformOrigin:"50% 50%"}, {scale:1, delay:2}); would cause a jump when the from values revert at the beginning of the 2nd tween. 13806 pt = _addNonTweeningNumericPT(m1, "yOrigin", (originalGSTransform ? m1 : m2).yOrigin, m2.yOrigin, pt, transformOriginString); 13807 if (x !== m1.xOffset || y !== m1.yOffset) { 13808 pt = _addNonTweeningNumericPT(m1, "xOffset", originalGSTransform ? x : m1.xOffset, m1.xOffset, pt, transformOriginString); 13809 pt = _addNonTweeningNumericPT(m1, "yOffset", originalGSTransform ? y : m1.yOffset, m1.yOffset, pt, transformOriginString); 13810 } 13811 orig = "0px 0px"; //certain browsers (like firefox) completely botch transform-origin, so we must remove it to prevent it from contaminating transforms. We manage it ourselves with xOrigin and yOrigin 13812 } 13813 if (orig || _supports3D && has3D && m1.zOrigin) { 13814 //if anything 3D is happening and there's a transformOrigin with a z component that's non-zero, we must ensure that the transformOrigin's z-component is set to 0 so that we can manually do those calculations to get around Safari bugs. Even if the user didn't specifically define a "transformOrigin" in this particular tween (maybe they did it via css directly). 13815 if (_transformProp) { 13816 hasChange = true; 13817 p = _transformOriginProp; 13818 orig = (orig || _getStyle(t, p, _cs, false, "50% 50%")) + ""; //cast as string to avoid errors 13819 pt = new CSSPropTween(style, p, 0, 0, pt, -1, transformOriginString); 13820 pt.b = style[p]; 13821 pt.plugin = plugin; 13822 if (_supports3D) { 13823 copy = m1.zOrigin; 13824 orig = orig.split(" "); 13825 m1.zOrigin = (orig.length > 2 && !(copy !== 0 && orig[2] === "0px") ? parseFloat(orig[2]) : copy) || 0; //Safari doesn't handle the z part of transformOrigin correctly, so we'll manually handle it in the _set3DTransformRatio() method. 13826 pt.xs0 = pt.e = orig[0] + " " + (orig[1] || "50%") + " 0px"; //we must define a z value of 0px specifically otherwise iOS 5 Safari will stick with the old one (if one was defined)! 13827 pt = new CSSPropTween(m1, "zOrigin", 0, 0, pt, -1, pt.n); //we must create a CSSPropTween for the _gsTransform.zOrigin so that it gets reset properly at the beginning if the tween runs backward (as opposed to just setting m1.zOrigin here) 13828 pt.b = copy; 13829 pt.xs0 = pt.e = m1.zOrigin; 13830 } else { 13831 pt.xs0 = pt.e = orig; 13832 } 13833 13834 //for older versions of IE (6-8), we need to manually calculate things inside the setRatio() function. We record origin x and y (ox and oy) and whether or not the values are percentages (oxp and oyp). 13835 } else { 13836 _parsePosition2(orig + "", m1); 13837 } 13838 } 13839 if (hasChange) { 13840 cssp._transformType = !(m1.svg && _useSVGTransformAttr) && (has3D || this._transformType === 3) ? 3 : 2; //quicker than calling cssp._enableTransforms(); 13841 } 13842 if (swapFunc) { 13843 vars[parsingProp] = swapFunc; 13844 } 13845 if (scaleFunc) { 13846 vars.scale = scaleFunc; 13847 } 13848 return pt; 13849 }, 13850 prefix: true 13851 }); 13852 _registerComplexSpecialProp("boxShadow", { 13853 defaultValue: "0px 0px 0px 0px #999", 13854 prefix: true, 13855 color: true, 13856 multi: true, 13857 keyword: "inset" 13858 }); 13859 _registerComplexSpecialProp("borderRadius", { 13860 defaultValue: "0px", 13861 parser: function parser(t, e, p, cssp, pt, plugin) { 13862 e = this.format(e); 13863 var props = ["borderTopLeftRadius", "borderTopRightRadius", "borderBottomRightRadius", "borderBottomLeftRadius"], 13864 style = t.style, 13865 ea1, 13866 i, 13867 es2, 13868 bs2, 13869 bs, 13870 es, 13871 bn, 13872 en, 13873 w, 13874 h, 13875 esfx, 13876 bsfx, 13877 rel, 13878 hn, 13879 vn, 13880 em; 13881 w = parseFloat(t.offsetWidth); 13882 h = parseFloat(t.offsetHeight); 13883 ea1 = e.split(" "); 13884 for (i = 0; i < props.length; i++) { 13885 //if we're dealing with percentages, we must convert things separately for the horizontal and vertical axis! 13886 if (this.p.indexOf("border")) { 13887 //older browsers used a prefix 13888 props[i] = _checkPropPrefix(props[i]); 13889 }
13890 bs = bs2 = _getStyle(t, props[i], _cs, false, "0px"); 13891 if (bs.indexOf(" ") !== -1) { 13892 bs2 = bs.split(" "); 13893 bs = bs2[0]; 13894 bs2 = bs2[1]; 13895 } 13896 es = es2 = ea1[i]; 13897 bn = parseFloat(bs); 13898 bsfx = bs.substr((bn + "").length); 13899 rel = es.charAt(1) === "="; 13900 if (rel) { 13901 en = parseInt(es.charAt(0) + "1", 10); 13902 es = es.substr(2); 13903 en *= parseFloat(es); 13904 esfx = es.substr((en + "").length - (en < 0 ? 1 : 0)) || ""; 13905 } else { 13906 en = parseFloat(es); 13907 esfx = es.substr((en + "").length); 13908 } 13909 if (esfx === "") { 13910 esfx = _suffixMap[p] || bsfx; 13911 } 13912 if (esfx !== bsfx) { 13913 hn = _convertToPixels(t, "borderLeft", bn, bsfx); //horizontal number (we use a bogus "borderLeft" property just because the _convertToPixels() method searches for the keywords "Left", "Right", "Top", and "Bottom" to determine of it's a horizontal or vertical property, and we need "border" in the name so that it knows it should measure relative to the element itself, not its parent. 13914 vn = _convertToPixels(t, "borderTop", bn, bsfx); //vertical number 13915 if (esfx === "%") { 13916 bs = hn / w * 100 + "%"; 13917 bs2 = vn / h * 100 + "%"; 13918 } else if (esfx === "em") { 13919 em = _convertToPixels(t, "borderLeft", 1, "em"); 13920 bs = hn / em + "em"; 13921 bs2 = vn / em + "em"; 13922 } else { 13923 bs = hn + "px"; 13924 bs2 = vn + "px"; 13925 } 13926 if (rel) { 13927 es = parseFloat(bs) + en + esfx; 13928 es2 = parseFloat(bs2) + en + esfx; 13929 } 13930 } 13931 pt = _parseComplex(style, props[i], bs + " " + bs2, es + " " + es2, false, "0px", pt); 13932 } 13933 return pt; 13934 }, 13935 prefix: true, 13936 formatter: _getFormatter("0px 0px 0px 0px", false, true) 13937 }); 13938 _registerComplexSpecialProp("borderBottomLeftRadius,borderBottomRightRadius,borderTopLeftRadius,borderTopRightRadius", { 13939 defaultValue: "0px", 13940 parser: function parser(t, e, p, cssp, pt, plugin) { 13941 return _parseComplex(t.style, p, this.format(_getStyle(t, p, _cs, false, "0px 0px")), this.format(e), false, "0px", pt); 13942 }, 13943 prefix: true, 13944 formatter: _getFormatter("0px 0px", false, true) 13945 }); 13946 _registerComplexSpecialProp("backgroundPosition", { 13947 defaultValue: "0 0", 13948 parser: function parser(t, e, p, cssp, pt, plugin) { 13949 var bp = "background-position", 13950 cs = _cs || _getComputedStyle(t, null), 13951 bs = this.format((cs ? _ieVers ? cs.getPropertyValue(bp + "-x") + " " + cs.getPropertyValue(bp + "-y") : cs.getPropertyValue(bp) : t.currentStyle.backgroundPositionX + " " + t.currentStyle.backgroundPositionY) || "0 0"), 13952 //Internet Explorer doesn't report background-position correctly - we must query background-position-x and background-position-y and combine them (even in IE10). Before IE9, we must do the same with the currentStyle object and use camelCase 13953 es = this.format(e), 13954 ba, 13955 ea, 13956 i, 13957 pct, 13958 overlap, 13959 src; 13960 if (bs.indexOf("%") !== -1 !== (es.indexOf("%") !== -1) && es.split(",").length < 2) { 13961 src = _getStyle(t, "backgroundImage").replace(_urlExp, ""); 13962 if (src && src !== "none") { 13963 ba = bs.split(" "); 13964 ea = es.split(" "); 13965 _tempImg.setAttribute("src", src); //set the temp IMG's src to the background-image so that we can measure its width/height 13966 i = 2; 13967 while (--i > -1) { 13968 bs = ba[i]; 13969 pct = bs.indexOf("%") !== -1; 13970 if (pct !== (ea[i].indexOf("%") !== -1)) { 13971 overlap = i === 0 ? t.offsetWidth - _tempImg.width : t.offsetHeight - _tempImg.height; 13972 ba[i] = pct ? parseFloat(bs) / 100 * overlap + "px" : parseFloat(bs) / overlap * 100 + "%"; 13973 } 13974 } 13975 bs = ba.join(" "); 13976 } 13977 } 13978 return this.parseComplex(t.style, bs, es, pt, plugin); 13979 }, 13980 formatter: _parsePosition2 13981 }); 13982 _registerComplexSpecialProp("backgroundSize", { 13983 defaultValue: "0 0", 13984 formatter: function formatter(v) { 13985 v += ""; //ensure it's a string 13986 return _parsePosition2(v.indexOf(" ") === -1 ? v + " " + v : v); //if set to something like "100% 100%", Safari typically reports the computed style as just "100%" (no 2nd value), but we should ensure that there are two values, so copy the first one. Otherwise, it'd be interpreted as "100% 0" (wrong). 13987 } 13988 }); 13989 _registerComplexSpecialProp("perspective", { 13990 defaultValue: "0px", 13991 prefix: true 13992 }); 13993 _registerComplexSpecialProp("perspectiveOrigin", { 13994 defaultValue: "50% 50%", 13995 prefix: true 13996 }); 13997 _registerComplexSpecialProp("transformStyle", { 13998 prefix: true 13999 }); 14000 _registerComplexSpecialProp("backfaceVisibility", { 14001 prefix: true 14002 }); 14003 _registerComplexSpecialProp("userSelect", { 14004 prefix: true 14005 }); 14006 _registerComplexSpecialProp("margin", { 14007 parser: _getEdgeParser("marginTop,marginRight,marginBottom,marginLeft") 14008 }); 14009 _registerComplexSpecialProp("padding", { 14010 parser: _getEdgeParser("paddingTop,paddingRight,paddingBottom,paddingLeft") 14011 }); 14012 _registerComplexSpecialProp("clip", { 14013 defaultValue: "rect(0px,0px,0px,0px)", 14014 parser: function parser(t, e, p, cssp, pt, plugin) { 14015 var b, cs, delim; 14016 if (_ieVers < 9) { 14017 //IE8 and earlier don't report a "clip" value in the currentStyle - instead, the values are split apart into clipTop, clipRight, clipBottom, and clipLeft. Also, in IE7 and earlier, the values inside rect() are space-delimited, not comma-delimited. 14018 cs = t.currentStyle; 14019 delim = _ieVers < 8 ? " " : ","; 14020 b = "rect(" + cs.clipTop + delim + cs.clipRight + delim + cs.clipBottom + delim + cs.clipLeft + ")"; 14021 e = this.format(e).split(",").join(delim); 14022 } else { 14023 b = this.format(_getStyle(t, this.p, _cs, false, this.dflt)); 14024 e = this.format(e); 14025 } 14026 return this.parseComplex(t.style, b, e, pt, plugin); 14027 } 14028 }); 14029 _registerComplexSpecialProp("textShadow", { 14030 defaultValue: "0px 0px 0px #999", 14031 color: true, 14032 multi: true 14033 }); 14034 _registerComplexSpecialProp("autoRound,strictUnits", { 14035 parser: function parser(t, e, p, cssp, pt) { 14036 return pt; 14037 } 14038 }); //just so that we can ignore these properties (not tween them) 14039 _registerComplexSpecialProp("border", { 14040 defaultValue: "0px solid #000", 14041 parser: function parser(t, e, p, cssp, pt, plugin) { 14042 var bw = _getStyle(t, "borderTopWidth", _cs, false, "0px"), 14043 end = this.format(e).split(" "), 14044 esfx = end[0].replace(_suffixExp, ""); 14045 if (esfx !== "px") { 14046 //if we're animating to a non-px value, we need to convert the beginning width to that unit. 14047 bw = parseFloat(bw) / _convertToPixels(t, "borderTopWidth", 1, esfx) + esfx; 14048 } 14049 return this.parseComplex(t.style, this.format(bw + " " + _getStyle(t, "borderTopStyle", _cs, false, "solid") + " " + _getStyle(t, "borderTopColor", _cs, false, "#000")), end.join(" "), pt, plugin); 14050 }, 14051 color: true, 14052 formatter: function formatter(v) { 14053 var a = v.split(" "); 14054 return a[0] + " " + (a[1] || "solid") + " " + (v.match(_colorExp) || ["#000"])[0]; 14055 } 14056 }); 14057 _registerComplexSpecialProp("borderWidth", { 14058 parser: _getEdgeParser("borderTopWidth,borderRightWidth,borderBottomWidth,borderLeftWidth") 14059 }); //Firefox doesn't pick up on borderWidth set in style sheets (only inline). 14060 _registerComplexSpecialProp("float,cssFloat,styleFloat", { 14061 parser: function parser(t, e, p, cssp, pt, plugin) { 14062 var s = t.style, 14063 prop = "cssFloat" in s ? "cssFloat" : "styleFloat"; 14064 return new CSSPropTween(s, prop, 0, 0, pt, -1, p, false, 0, s[prop], e); 14065 } 14066 }); 14067 14068 //opacity-related 14069 var _setIEOpacityRatio = function _setIEOpacityRatio(v) { 14070 var t = this.t, 14071 //refers to the element's style property 14072 filters = t.filter || _getStyle(this.data, "filter") || "", 14073 val = this.s + this.c * v | 0, 14074 skip; 14075 if (val === 100) { 14076 //for older versions of IE that need to use a filter to apply opacity, we should remove the filter if opacity hits 1 in order to improve performance, but make sure there isn't a transform (matrix) or gradient in the filters. 14077 if (filters.indexOf("atrix(") === -1 && filters.indexOf("radient(") === -1 && filters.indexOf("oader(") === -1) { 14078 t.removeAttribute("filter"); 14079 skip = !_getStyle(this.data, "filter"); //if a class is applied that has an alpha filter, it will take effect (we don't want that), so re-apply our alpha filter in that case. We must first remove it and then check. 14080 } else {
14081 t.filter = filters.replace(_alphaFilterExp, ""); 14082 skip = true; 14083 } 14084 } 14085 if (!skip) { 14086 if (this.xn1) { 14087 t.filter = filters = filters || "alpha(opacity=" + val + ")"; //works around bug in IE7/8 that prevents changes to "visibility" from being applied properly if the filter is changed to a different alpha on the same frame. 14088 } 14089 if (filters.indexOf("pacity") === -1) { 14090 //only used if browser doesn't support the standard opacity style property (IE 7 and 8). We omit the "O" to avoid case-sensitivity issues 14091 if (val !== 0 || !this.xn1) { 14092 //bugs in IE7/8 won't render the filter properly if opacity is ADDED on the same frame/render as "visibility" changes (this.xn1 is 1 if this tween is an "autoAlpha" tween) 14093 t.filter = filters + " alpha(opacity=" + val + ")"; //we round the value because otherwise, bugs in IE7/8 can prevent "visibility" changes from being applied properly. 14094 } 14095 } else { 14096 t.filter = filters.replace(_opacityExp, "opacity=" + val); 14097 } 14098 } 14099 }; 14100 _registerComplexSpecialProp("opacity,alpha,autoAlpha", { 14101 defaultValue: "1", 14102 parser: function parser(t, e, p, cssp, pt, plugin) { 14103 var b = parseFloat(_getStyle(t, "opacity", _cs, false, "1")), 14104 style = t.style, 14105 isAutoAlpha = p === "autoAlpha"; 14106 if (typeof e === "string" && e.charAt(1) === "=") { 14107 e = (e.charAt(0) === "-" ? -1 : 1) * parseFloat(e.substr(2)) + b; 14108 } 14109 if (isAutoAlpha && b === 1 && _getStyle(t, "visibility", _cs) === "hidden" && e !== 0) { 14110 //if visibility is initially set to "hidden", we should interpret that as intent to make opacity 0 (a convenience) 14111 b = 0; 14112 } 14113 if (_supportsOpacity) { 14114 pt = new CSSPropTween(style, "opacity", b, e - b, pt); 14115 } else { 14116 pt = new CSSPropTween(style, "opacity", b * 100, (e - b) * 100, pt); 14117 pt.xn1 = isAutoAlpha ? 1 : 0; //we need to record whether or not this is an autoAlpha so that in the setRatio(), we know to duplicate the setting of the alpha in order to work around a bug in IE7 and IE8 that prevents changes to "visibility" from taking effect if the filter is changed to a different alpha(opacity) at the same time. Setting it to the SAME value first, then the new value works around the IE7/8 bug. 14118 style.zoom = 1; //helps correct an IE issue. 14119 pt.type = 2; 14120 pt.b = "alpha(opacity=" + pt.s + ")"; 14121 pt.e = "alpha(opacity=" + (pt.s + pt.c) + ")"; 14122 pt.data = t; 14123 pt.plugin = plugin; 14124 pt.setRatio = _setIEOpacityRatio; 14125 } 14126 if (isAutoAlpha) { 14127 //we have to create the "visibility" PropTween after the opacity one in the linked list so that they run in the order that works properly in IE8 and earlier 14128 pt = new CSSPropTween(style, "visibility", 0, 0, pt, -1, null, false, 0, b !== 0 ? "inherit" : "hidden", e === 0 ? "hidden" : "inherit"); 14129 pt.xs0 = "inherit"; 14130 cssp._overwriteProps.push(pt.n); 14131 cssp._overwriteProps.push(p); 14132 } 14133 return pt; 14134 } 14135 }); 14136 var _removeProp = function _removeProp(s, p) { 14137 if (p) { 14138 if (s.removeProperty) { 14139 if (p.substr(0, 2) === "ms" || p.substr(0, 6) === "webkit") { 14140 //Microsoft and some Webkit browsers don't conform to the standard of capitalizing the first prefix character, so we adjust so that when we prefix the caps with a dash, it's correct (otherwise it'd be "ms-transform" instead of "-ms-transform" for IE9, for example) 14141 p = "-" + p; 14142 } 14143 s.removeProperty(p.replace(_capsExp, "-$1").toLowerCase()); 14144 } else { 14145 //note: old versions of IE use "removeAttribute()" instead of "removeProperty()" 14146 s.removeAttribute(p); 14147 } 14148 } 14149 }, 14150 _setClassNameRatio = function _setClassNameRatio(v) { 14151 this.t._gsClassPT = this; 14152 if (v === 1 || v === 0) { 14153 this.t.setAttribute("class", v === 0 ? this.b : this.e); 14154 var mpt = this.data, 14155 //first MiniPropTween 14156 s = this.t.style; 14157 while (mpt) { 14158 if (!mpt.v) { 14159 _removeProp(s, mpt.p); 14160 } else { 14161 s[mpt.p] = mpt.v; 14162 } 14163 mpt = mpt._next; 14164 } 14165 if (v === 1 && this.t._gsClassPT === this) { 14166 this.t._gsClassPT = null; 14167 } 14168 } else if (this.t.getAttribute("class") !== this.e) { 14169 this.t.setAttribute("class", this.e); 14170 } 14171 }; 14172 _registerComplexSpecialProp("className", { 14173 parser: function parser(t, e, p, cssp, pt, plugin, vars) { 14174 var b = t.getAttribute("class") || "", 14175 //don't use t.className because it doesn't work consistently on SVG elements; getAttribute("class") and setAttribute("class", value") is more reliable. 14176 cssText = t.style.cssText, 14177 difData, 14178 bs, 14179 cnpt, 14180 cnptLookup, 14181 mpt; 14182 pt = cssp._classNamePT = new CSSPropTween(t, p, 0, 0, pt, 2); 14183 pt.setRatio = _setClassNameRatio; 14184 pt.pr = -11; 14185 _hasPriority = true; 14186 pt.b = b; 14187 bs = _getAllStyles(t, _cs); 14188 //if there's a className tween already operating on the target, force it to its end so that the necessary inline styles are removed and the class name is applied before we determine the end state (we don't want inline styles interfer
14188ing that were there just for class-specific values) 14189 cnpt = t._gsClassPT; 14190 if (cnpt) { 14191 cnptLookup = {}; 14192 mpt = cnpt.data; //first MiniPropTween which stores the inline styles - we need to force these so that the inline styles don't contaminate things. Otherwise, there's a small chance that a tween could start and the inline values match the destination values and they never get cleaned. 14193 while (mpt) { 14194 cnptLookup[mpt.p] = 1; 14195 mpt = mpt._next; 14196 } 14197 cnpt.setRatio(1); 14198 } 14199 t._gsClassPT = pt; 14200 pt.e = e.charAt(1) !== "=" ? e : b.replace(new RegExp("(?:\\s|^)" + e.substr(2) + "(?![\\w-])"), "") + (e.charAt(0) === "+" ? " " + e.substr(2) : ""); 14201 t.setAttribute("class", pt.e); 14202 difData = _cssDif(t, bs, _getAllStyles(t), vars, cnptLookup); 14203 t.setAttribute("class", b); 14204 pt.data = difData.firstMPT; 14205 t.style.cssText = cssText; //we recorded cssText before we swapped classes and ran _getAllStyles() because in cases when a className tween is overwritten, we remove all the related tweening properties from that class change (otherwise class-specific stuff can't override properties we've directly set on the target's style object due to specificity). 14206 pt = pt.xfirst = cssp.parse(t, difData.difs, pt, plugin); //we record the CSSPropTween as the xfirst so that we can handle overwriting propertly (if "className" gets overwritten, we must kill all the properties associated with the className part of the tween, so we can loop through from xfirst to the pt itself) 14207 return pt; 14208 } 14209 }); 14210 var _setClearPropsRatio = function _setClearPropsRatio(v) { 14211 if (v === 1 || v === 0) if (this.data._totalTime === this.data._totalDuration && this.data.data !== "isFromStart") { 14212 //this.data refers to the tween. Only clear at the END of the tween (remember, from() tweens make the ratio go from 1 to 0, so we can't just check that and if the tween is the zero-duration one that's created internally to render the starting values in a from() tween, ignore that because otherwise, for example, from(...{height:100, clearProps:"height", delay:1}) would wipe the height at the beginning of the tween and after 1 second, it'd kick back in). 14213 var s = this.t.style, 14214 transformParse = _specialProps.transform.parse, 14215 a, 14216 p, 14217 i, 14218 clearTransform, 14219 transform; 14220 if (this.e === "all") { 14221 s.cssText = ""; 14222 clearTransform = true; 14223 } else { 14224 a = this.e.split(" ").join("").split(","); 14225 i = a.length; 14226 while (--i > -1) { 14227 p = a[i]; 14228 if (_specialProps[p]) { 14229 if (_specialProps[p].parse === transformParse) { 14230 clearTransform = true; 14231 } else { 14232 p = p === "transformOrigin" ? _transformOriginProp : _specialProps[p].p; //ensures that special properties use the proper browser-specific property name, like "scaleX" might be "-webkit-transform" or "boxShadow" might be "-moz-box-shadow" 14233 } 14234 } 14235 _removeProp(s, p); 14236 } 14237 } 14238 if (clearTransform) { 14239 _removeProp(s, _transformProp); 14240 transform = this.t._gsTransform; 14241 if (transform) { 14242 if (transform.svg) { 14243 this.t.removeAttribute("data-svg-origin"); 14244 this.t.removeAttribute("transform"); 14245 } 14246 delete this.t._gsTransform; 14247 } 14248 } 14249 } 14250 }; 14251 _registerComplexSpecialProp("clearProps", { 14252 parser: function parser(t, e, p, cssp, pt) { 14253 pt = new CSSPropTween(t, p, 0, 0, pt, 2); 14254 pt.setRatio = _setClearPropsRatio; 14255 pt.e = e; 14256 pt.pr = -10; 14257 pt.data = cssp._tween; 14258 _hasPriority = true; 14259 return pt; 14260 } 14261 }); 14262 p = "bezier,throwProps,physicsProps,physics2D".split(","); 14263 i = p.length; 14264 while (i--) { 14265 _registerPluginProp(p[i]); 14266 } 14267 p = _CSSPlugin.prototype; 14268 p._firstPT = p._lastParsedTransform = p._transform = null; 14269 14270 //gets called when the tween renders for the first time. This kicks everything off, recording start/end values, etc. 14271 p._onInitTween = function (target, vars, tween, index) { 14272 if (!target.nodeType) { 14273 //css is only for dom elements 14274 return false;
14275 } 14276 this._target = _target = target; 14277 this._tween = tween; 14278 this._vars = vars; 14279 _index = index; 14280 _autoRound = vars.autoRound; 14281 _hasPriority = false; 14282 _suffixMap = vars.suffixMap || _CSSPlugin.suffixMap; 14283 _cs = _getComputedStyle(target, ""); 14284 _overwriteProps = this._overwriteProps; 14285 var style = target.style, 14286 v, 14287 pt, 14288 pt2, 14289 first, 14290 last, 14291 next, 14292 zIndex, 14293 tpt, 14294 threeD; 14295 if (_reqSafariFix) if (style.zIndex === "") { 14296 v = _getStyle(target, "zIndex", _cs); 14297 if (v === "auto" || v === "") { 14298 //corrects a bug in [non-Android] Safari that prevents it from repainting elements in their new positions if they don't have a zIndex set. We also can't just apply this inside _parseTransform() because anything that's moved in any way (like using "left" or "top" instead of transforms like "x" and "y") can be affected, so it is best to ensure that anything that's tweening has a z-index. Setting "WebkitPerspective" to a non-zero value worked too except that on iOS Safari things would flicker randomly. Plus zIndex is less memory-intensive. 14299 this._addLazySet(style, "zIndex", 0); 14300 } 14301 } 14302 if (typeof vars === "string") { 14303 first = style.cssText; 14304 v = _getAllStyles(target, _cs); 14305 style.cssText = first + ";" + vars; 14306 v = _cssDif(target, v, _getAllStyles(target)).difs; 14307 if (!_supportsOpacity && _opacityValExp.test(vars)) { 14308 v.opacity = parseFloat(RegExp.$1); 14309 } 14310 vars = v; 14311 style.cssText = first; 14312 } 14313 if (vars.className) { 14314 //className tweens will combine any differences they find in the css with the vars that are passed in, so {className:"myClass", scale:0.5, left:20} would work. 14315 this._firstPT = pt = _specialProps.className.parse(target, vars.className, "className", this, null, null, vars); 14316 } else { 14317 this._firstPT = pt = this.parse(target, vars, null); 14318 } 14319 if (this._transformType) { 14320 threeD = this._transformType === 3; 14321 if (!_transformProp) { 14322 style.zoom = 1; //helps correct an IE issue. 14323 } else if (_isSafari) { 14324 _reqSafariFix = true; 14325 //if zIndex isn't set, iOS Safari doesn't repaint things correctly sometimes (seemingly at random). 14326 if (style.zIndex === "") { 14327 zIndex = _getStyle(target, "zIndex", _cs); 14328 if (zIndex === "auto" || zIndex === "") { 14329 this._addLazySet(style, "zIndex", 0); 14330 } 14331 } 14332 //Setting WebkitBackfaceVisibility corrects 3 bugs: 14333 // 1) [non-Android] Safari skips rendering changes to "top" and "left" that are made on the same frame/render as a transform update. 14334 // 2) iOS Safari sometimes neglects to repaint elements in their new positions. Setting "WebkitPerspective" to a non-zero value worked too except that on iOS Safari things would flicker randomly. 14335 // 3) Safari sometimes displayed odd artifacts when tweening the transform (or WebkitTransform) property, like ghosts of the edges of the element remained. Definitely a browser bug. 14336 //Note: we allow the user to override the auto-setting by defining WebkitBackfaceVisibility in the vars of the tween. 14337 if (_isSafariLT6) { 14338 this._addLazySet(style, "WebkitBackfaceVisibility", this._vars.WebkitBackfaceVisibility || (threeD ? "visible" : "hidden")); 14339 } 14340 } 14341 pt2 = pt; 14342 while (pt2 && pt2._next) { 14343 pt2 = pt2._next; 14344 } 14345 tpt = new CSSPropTween(target, "transform", 0, 0, null, 2); 14346 this._linkCSSP(tpt, null, pt2); 14347 tpt.setRatio = _transformProp ? _setTransformRatio : _setIETransformRatio; 14348 tpt.data = this._transform || _getTransform(target, _cs, true); 14349 tpt.tween = tween; 14350 tpt.pr = -1; //ensures that the transforms get applied after the components are updated. 14351 _overwriteProps.pop(); //we don't want to force the overwrite of all "transform" tweens of the target - we only care about individual transform properties like scaleX, rotation, etc. The CSSPropTween constructor automatically adds the property to _overwriteProps which is why we need to pop() here. 14352 } 14353 if (_hasPriority) { 14354 //reorders the linked list in order of pr (priority) 14355 while (pt) { 14356 next = pt._next; 14357 pt2 = first; 14358 while (pt2 && pt2.pr > pt.pr) { 14359 pt2 = pt2._next; 14360 } 14361 if (pt._prev = pt2 ? pt2._prev : last) { 14362 pt._prev._next = pt; 14363 } else { 14364 first = pt; 14365 } 14366 if (pt._next = pt2) { 14367 pt2._prev = pt; 14368 } else { 14369 last = pt; 14370 } 14371 pt = next; 14372 } 14373 this._firstPT = first; 14374 } 14375 return true; 14376 }; 14377 p.parse = function (target, vars, pt, plugin) { 14378 var style = target.style, 14379 p, 14380 sp, 14381 bn, 14382 en, 14383 bs, 14384 es, 14385 bsfx, 14386 esfx, 14387 isStr, 14388 rel; 14389 for (p in vars) { 14390 es = vars[p]; //ending value string 14391 if (typeof es === "function") { 14392 es = es(_index, _target); 14393 } 14394 sp = _specialProps[p]; //SpecialProp lookup. 14395 if (sp) { 14396 pt = sp.parse(target, es, p, this, pt, plugin, vars); 14397 } else if (p.substr(0, 2) === "--") { 14398 //for tweening CSS variables (which always start with "--"). To maximize performance and simplicity, we bypass CSSPlugin altogether and just add a normal property tween to the tween instance itself. 14399 this._tween._propLookup[p] = this._addTween.call(this._tween, target.style, "setProperty", _getComputedStyle(target).getPropertyValue(p) + "", es + "", p, false, p); 14400 continue; 14401 } else { 14402 bs = _getStyle(target, p, _cs) + ""; 14403 isStr = typeof es === "string"; 14404 if (p === "color" || p === "fill" || p === "stroke" || p.indexOf("Color") !== -1 || isStr && _rgbhslExp.test(es)) { 14405 //Opera uses background: to define color sometimes in addition to backgroundColor: 14406 if (!isStr) { 14407 es = _parseColor(es); 14408 es = (es.length > 3 ? "rgba(" : "rgb(") + es.join(",") + ")"; 14409 } 14410 pt = _parseComplex(style, p, bs, es, true, "transparent", pt, 0, plugin); 14411 } else if (isStr && _complexExp.test(es)) { 14412 pt = _parseComplex(style, p, bs, es, true, null, pt, 0, plugin); 14413 } else { 14414 bn = parseFloat(bs); 14415 bsfx = bn || bn === 0 ? bs.substr((bn + "").length) : ""; //remember, bs could be non-numeric like "normal" for fontWeight, so we should default to a blank suffix in that case. 14416 14417 if (bs === "" || bs === "auto") { 14418 if (p === "width" || p === "height") { 14419 bn = _getDimension(target, p, _cs); 14420 bsfx = "px"; 14421 } else if (p === "left" || p === "top") {
14422 bn = _calculateOffset(target, p, _cs); 14423 bsfx = "px"; 14424 } else { 14425 bn = p !== "opacity" ? 0 : 1; 14426 bsfx = ""; 14427 } 14428 } 14429 rel = isStr && es.charAt(1) === "="; 14430 if (rel) { 14431 en = parseInt(es.charAt(0) + "1", 10); 14432 es = es.substr(2); 14433 en *= parseFloat(es); 14434 esfx = es.replace(_suffixExp, ""); 14435 } else { 14436 en = parseFloat(es); 14437 esfx = isStr ? es.replace(_suffixExp, "") : ""; 14438 } 14439 if (esfx === "") { 14440 esfx = p in _suffixMap ? _suffixMap[p] : bsfx; //populate the end suffix, prioritizing the map, then if none is found, use the beginning suffix. 14441 } 14442 es = en || en === 0 ? (rel ? en + bn : en) + esfx : vars[p]; //ensures that any += or -= prefixes are taken care of. Record the end value before normalizing the suffix because we always want to end the tween on exactly what they intended even if it doesn't match the beginning value's suffix. 14443 //if the beginning/ending suffixes don't match, normalize them... 14444 if (bsfx !== esfx) if (esfx !== "" || p === "lineHeight") if (en || en === 0) if (bn) { 14445 //note: if the beginning value (bn) is 0, we don't need to convert units! 14446 bn = _convertToPixels(target, p, bn, bsfx); 14447 if (esfx === "%") { 14448 bn /= _convertToPixels(target, p, 100, "%") / 100; 14449 if (vars.strictUnits !== true) { 14450 //some browsers report only "px" values instead of allowing "%" with getComputedStyle(), so we assume that if we're tweening to a %, we should start there too unless strictUnits:true is defined. This approach is particularly useful for responsive designs that use from() tweens. 14451 bs = bn + "%"; 14452 } 14453 } else if (esfx === "em" || esfx === "rem" || esfx === "vw" || esfx === "vh") { 14454 bn /= _convertToPixels(target, p, 1, esfx); 14455 14456 //otherwise convert to pixels. 14457 } else if (esfx !== "px") { 14458 en = _convertToPixels(target, p, en, esfx); 14459 esfx = "px"; //we don't use bsfx after this, so we don't need to set it to px too. 14460 } 14461 if (rel) if (en || en === 0) { 14462 es = en + bn + esfx; //the changes we made affect relative calculations, so adjust the end value here. 14463 } 14464 } 14465 if (rel) { 14466 en += bn; 14467 } 14468 if ((bn || bn === 0) && (en || en === 0)) { 14469 //faster than isNaN(). Also, previously we required en !== bn but that doesn't really gain much performance and it prevents _parseToProxy() from working properly if beginning and ending values match but need to get tweened by an external plugin anyway. For example, a bezier tween where the target starts at left:0 and has these points: [{left:50},{left:0}] wouldn't work properly because when parsing the last point, it'd match the first (current) one and a non-tweening CSSPropTween would be recorded when we actually need a normal tween (type:0) so that things get updated during the tween properly. 14470 pt = new CSSPropTween(style, p, bn, en - bn, pt, 0, p, _autoRound !== false && (esfx === "px" || p === "zIndex"), 0, bs, es); 14471 pt.xs0 = esfx; 14472 //DEBUG: _log("tween "+p+" from "+pt.b+" ("+bn+esfx+") to "+pt.e+" with suffix: "+pt.xs0); 14473 } else if (style[p] === undefined || !es && (es + "" === "NaN" || es == null)) { 14474 _log("invalid " + p + " tween value: " + vars[p]); 14475 } else { 14476 pt = new CSSPropTween(style, p, en || bn || 0, 0, pt, -1, p, false, 0, bs, es); 14477 pt.xs0 = es === "none" && (p === "display" || p.indexOf("Style") !== -1) ? bs : es; //intermediate value should typically be set immediately (end value) except for "display" or things like borderTopStyle, borderBottomStyle, etc. which should use the beginning value during the tween. 14478 //DEBUG: _log("non-tweening value "+p+": "+pt.xs0); 14479 } 14480 } 14481 } 14482 if (plugin) if (pt && !pt.plugin) { 14483 pt.plugin = plugin; 14484 } 14485 } 14486 return pt; 14487 }; 14488 14489 //gets called every time the tween updates, passing the new ratio (typically a value between 0 and 1, but not always (for example, if an Elastic.easeOut is used, the value can jump above 1 mid-tween). It will always start and 0 and end at 1. 14490 p.setRatio = function (v) { 14491 var pt = this._firstPT, 14492 min = 0.000001, 14493 val, 14494 str, 14495 i; 14496 //at the end of the tween, we set the values to exactly what we received in order to make sure non-tweening values (like "position" or "float" or whatever) are set and so that if the beginning/ending suffixes (units) didn't match and we normalized to px, the value that the user passed in is used here. We check to see if the tween is at its beginning in case it's a from() tween in which case the ratio will actually go from 1 to 0 over the course of the tween (backwards). 14497 if (v === 1 && (this._tween._time === this._tween._duration || this._tween._time === 0)) { 14498 while (pt) { 14499 if (pt.type !== 2) { 14500 if (pt.r && pt.type !== -1) { 14501 val = Math.round(pt.s + pt.c); 14502 if (!pt.type) { 14503 pt.t[pt.p] = val + pt.xs0; 14504 } else if (pt.type === 1) { 14505 //complex value (one that typically has multiple numbers inside a string, like "rect(5px,10px,20px,25px)" 14506 i = pt.l; 14507 str = pt.xs0 + val + pt.xs1; 14508 for (i = 1; i < pt.l; i++) { 14509 str += pt["xn" + i] + pt["xs" + (i + 1)]; 14510 } 14511 pt.t[pt.p] = str; 14512 } 14513 } else { 14514 pt.t[pt.p] = pt.e; 14515 } 14516 } else { 14517 pt.setRatio(v); 14518 } 14519 pt = pt._next; 14520 } 14521 } else if (v || !(this._tween._time === this._tween._duration || this._tween._time === 0) || this._tween._rawPrevTime === -0.000001) { 14522 while (pt) { 14523 val = pt.c * v + pt.s; 14524 if (pt.r) { 14525 val = Math.round(val); 14526 } else if (val < min) if (val > -min) { 14527 val = 0; 14528 } 14529 if (!pt.type) { 14530 pt.t[pt.p] = val + pt.xs0; 14531 } else if (pt.type === 1) { 14532 //complex value (one that typically has multiple numbers inside a string, like "rect(5px,10px,20px,25px)" 14533 i = pt.l; 14534 if (i === 2) { 14535 pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2; 14536 } else if (i === 3) { 14537 pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3; 14538 } else if (i === 4) { 14539 pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3 + pt.xn3 + pt.xs4; 14540 } else if (i === 5) { 14541 pt.t[pt.p] = pt.xs0 + val + pt.xs1 + pt.xn1 + pt.xs2 + pt.xn2 + pt.xs3 + pt.xn3 + pt.xs4 + pt.xn4 + pt.xs5; 14542 } else { 14543 str = pt.xs0 + val + pt.xs1; 14544 for (i = 1; i < pt.l; i++) { 14545 str += pt["xn" + i] + pt["xs" + (i + 1)]; 14546 } 14547 pt.t[pt.p] = str; 14548 } 14549 } else if (pt.type === -1) { 14550 //non-tweening value 14551 pt.t[pt.p] = pt.xs0; 14552 }
14552 else if (pt.setRatio) { 14553 //custom setRatio() for things like SpecialProps, external plugins, etc. 14554 pt.setRatio(v); 14555 } 14556 pt = pt._next; 14557 } 14558 14559 //if the tween is reversed all the way back to the beginning, we need to restore the original values which may have different units (like % instead of px or em or whatever). 14560 } else { 14561 while (pt) { 14562 if (pt.type !== 2) { 14563 pt.t[pt.p] = pt.b; 14564 } else { 14565 pt.setRatio(v); 14566 } 14567 pt = pt._next; 14568 } 14569 } 14570 }; 14571 14572 /** 14573 * @private 14574 * Forces rendering of the target's transforms (rotation, scale, etc.) whenever the CSSPlugin's setRatio() is called. 14575 * Basically, this tells the CSSPlugin to create a CSSPropTween (type 2) after instantiation that runs last in the linked 14576 * list and calls the appropriate (3D or 2D) rendering function. We separate this into its own method so that we can call 14577 * it from other plugins like BezierPlugin if, for example, it needs to apply an autoRotation and this CSSPlugin 14578 * doesn't have any transform-related properties of its own. You can call this method as many times as you 14579 * want and it won't create duplicate CSSPropTweens. 14580 * 14581 * @param {boolean} threeD if true, it should apply 3D tweens (otherwise, just 2D ones are fine and typically faster) 14582 */ 14583 p._enableTransforms = function (threeD) { 14584 this._transform = this._transform || _getTransform(this._target, _cs, true); //ensures that the element has a _gsTransform property with the appropriate values. 14585 this._transformType = !(this._transform.svg && _useSVGTransformAttr) && (threeD || this._transformType === 3) ? 3 : 2; 14586 }; 14587 var lazySet = function lazySet(v) { 14588 this.t[this.p] = this.e; 14589 this.data._linkCSSP(this, this._next, null, true); //we purposefully keep this._next even though it'd make sense to null it, but this is a performance optimization, as this happens during the while (pt) {} loop in setRatio() at the bottom of which it sets pt = pt._next, so if we null it, the linked list will be broken in that loop. 14590 }; 14591 /** @private Gives us a way to set a value on the first render (and only the first render). **/ 14592 p._addLazySet = function (t, p, v) { 14593 var pt = this._firstPT = new CSSPropTween(t, p, 0, 0, this._firstPT, 2); 14594 pt.e = v; 14595 pt.setRatio = lazySet; 14596 pt.data = this; 14597 }; 14598 14599 /** @private **/ 14600 p._linkCSSP = function (pt, next, prev, remove) { 14601 if (pt) { 14602 if (next) { 14603 next._prev = pt; 14604 } 14605 if (pt._next) { 14606 pt._next._prev = pt._prev; 14607 } 14608 if (pt._prev) { 14609 pt._prev._next = pt._next; 14610 } else if (this._firstPT === pt) { 14611 this._firstPT = pt._next; 14612 remove = true; //just to prevent resetting this._firstPT 5 lines down in case pt._next is null. (optimized for speed) 14613 } 14614 if (prev) { 14615 prev._next = pt; 14616 } else if (!remove && this._firstPT === null) { 14617 this._firstPT = pt; 14618 } 14619 pt._next = next; 14620 pt._prev = prev; 14621 } 14622 return pt; 14623 }; 14624 p._mod = function (lookup) { 14625 var pt = this._firstPT; 14626 while (pt) { 14627 if (typeof lookup[pt.p] === "function" && lookup[pt.p] === Math.round) { 14628 //only gets called by RoundPropsPlugin (ModifyPlugin manages all the rendering internally for CSSPlugin properties that need modification). Remember, we handle rounding a bit differently in this plugin for performance reasons, leveraging "r" as an indicator that the value should be rounded internally.. 14629 pt.r = 1; 14630 } 14631 pt = pt._next; 14632 } 14633 }; 14634 14635 //we need to make sure that if alpha or autoAlpha is killed, opacity is too. And autoAlpha affects the "visibility" property. 14636 p._kill = function (lookup) { 14637 var copy = lookup, 14638 pt, 14639 p, 14640 xfirst; 14641 if (lookup.autoAlpha || lookup.alpha) { 14642 copy = {}; 14643 for (p in lookup) { 14644 //copy the lookup so that we're not changing the original which may be passed elsewhere. 14645 copy[p] = lookup[p]; 14646 } 14647 copy.opacity = 1; 14648 if (copy.autoAlpha) { 14649 copy.visibility = 1; 14650 } 14651 } 14652 if (lookup.className && (pt = this._classNamePT)) { 14653 //for className tweens, we need to kill any associated CSSPropTweens too; a linked list starts at the className's "xfirst". 14654 xfirst = pt.xfirst; 14655 if (xfirst && xfirst._prev) { 14656 this._linkCSSP(xfirst._prev, pt._next, xfirst._prev._prev); //break off the prev 14657 } else if (xfirst === this._firstPT) { 14658 this._firstPT = pt._next; 14659 } 14660 if (pt._next) { 14661 this._linkCSSP(pt._next, pt._next._next, xfirst._prev); 14662 } 14663 this._classNamePT = null; 14664 } 14665 pt = this._firstPT; 14666 while (pt) { 14667 if (pt.plugin && pt.plugin !== p && pt.plugin._kill) { 14668 //for plugins that are registered with CSSPlugin, we should notify them of the kill. 14669 pt.plugin._kill(lookup); 14670 p = pt.plugin; 14671 } 14672 pt = pt._next; 14673 } 14674 return TweenPlugin.prototype._kill.call(this, copy); 14675 }; 14676 14677 //used by cascadeTo() for gathering all the style properties of each child element into an array for c
14677omparison. 14678 var _getChildStyles2 = function _getChildStyles(e, props, targets) { 14679 var children, i, child, type; 14680 if (e.slice) { 14681 i = e.length; 14682 while (--i > -1) { 14683 _getChildStyles2(e[i], props, targets); 14684 } 14685 return; 14686 } 14687 children = e.childNodes; 14688 i = children.length; 14689 while (--i > -1) { 14690 child = children[i]; 14691 type = child.type; 14692 if (child.style) { 14693 props.push(_getAllStyles(child)); 14694 if (targets) { 14695 targets.push(child); 14696 } 14697 } 14698 if ((type === 1 || type === 9 || type === 11) && child.childNodes.length) { 14699 _getChildStyles2(child, props, targets); 14700 } 14701 } 14702 }; 14703 14704 /** 14705 * Typically only useful for className tweens that may affect child elements, this method creates a TweenLite 14706 * and then compares the style properties of all the target's child elements at the tween's start and end, and 14707 * if any are different, it also creates tweens for those and returns an array containing ALL of the resulting 14708 * tweens (so that you can easily add() them to a TimelineLite, for example). The reason this functionality is 14709 * wrapped into a separate static method of CSSPlugin instead of being integrated into all regular className tweens 14710 * is because it creates entirely new tweens that may have completely different targets than the original tween, 14711 * so if they were all lumped into the original tween instance, it would be inconsistent with the rest of the API 14712 * and it would create other problems. For example: 14713 * - If I create a tween of elementA, that tween instance may suddenly change its target to include 50 other elements (unintuitive if I specifically defined the target I wanted) 14714 * - We can't just create new independent tweens because otherwise, what happens if the original/parent tween is reversed or pause or dropped into a TimelineLite for tight control? You'd expect that tween's behavior to affect all the others. 14715 * - Analyzing every style property of every child before and after the tween is an expensive operation when there are many children, so this behavior shouldn't be imposed on all className tweens by default, especially since it's probably rare that this extra functionality is needed. 14716 * 14717 * @param {Object} target object to be tweened 14718 * @param {number} Duration in seconds (or frames for frames-based tweens) 14719 * @param {Object} Object containing the end values, like {className:"newClass", ease:Linear.easeNone} 14720 * @return {Array} An array of TweenLite instances 14721 */ 14722 _CSSPlugin.cascadeTo = function (target, duration, vars) { 14723 var tween = TweenLite.to(target, duration, vars), 14724 results = [tween], 14725 b = [], 14726 e = [], 14727 targets = [], 14728 _reservedProps = TweenLite._internals.reservedProps, 14729 i, 14730 difs, 14731 p, 14732 from; 14733 target = tween._targets || tween.target; 14734 _getChildStyles2(target, b, targets); 14735 tween.render(duration, true, true); 14736 _getChildStyles2(target, e); 14737 tween.render(0, true, true); 14738 tween._enabled(true); 14739 i = targets.length; 14740 while (--i > -1) { 14741 difs = _cssDif(targets[i], b[i], e[i]); 14742 if (difs.firstMPT) { 14743 difs = difs.difs; 14744 for (p in vars) { 14745 if (_reservedProps[p]) { 14746 difs[p] = vars[p]; 14747 } 14748 } 14749 from = {}; 14750 for (p in difs) { 14751 from[p] = b[i][p]; 14752 } 14753 results.push(TweenLite.fromTo(targets[i], duration, from, difs)); 14754 } 14755 } 14756 return results; 14757 }; 14758 TweenPlugin.activate([_CSSPlugin]); 14759 return _CSSPlugin; 14760 }, true); 14761 14762 /* 14763 * ---------------------------------------------------------------- 14764 * RoundPropsPlugin 14765 * ---------------------------------------------------------------- 14766 */ 14767 (function () { 14768 var RoundPropsPlugin = _gsScope._gsDefine.plugin({ 14769 propName: "roundProps", 14770 version: "1.6.0", 14771 priority: -1, 14772 API: 2, 14773 //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run. 14774 init: function init(target, value, tween) { 14775 this._tween = tween; 14776 return true; 14777 } 14778 }), 14779 _roundLinkedList = function _roundLinkedList(node) { 14780 while (node) { 14781 if (!node.f && !node.blob) { 14782 node.m = Math.round; 14783 } 14784 node = node._next; 14785 } 14786 }, 14787 p = RoundPropsPlugin.prototype; 14788 p._onInitAllProps = function () { 14789 var tween = this._tween,
14790 rp = tween.vars.roundProps.join ? tween.vars.roundProps : tween.vars.roundProps.split(","), 14791 i = rp.length, 14792 lookup = {}, 14793 rpt = tween._propLookup.roundProps, 14794 prop, 14795 pt, 14796 next; 14797 while (--i > -1) { 14798 lookup[rp[i]] = Math.round; 14799 } 14800 i = rp.length; 14801 while (--i > -1) { 14802 prop = rp[i]; 14803 pt = tween._firstPT; 14804 while (pt) { 14805 next = pt._next; //record here, because it may get removed 14806 if (pt.pg) { 14807 pt.t._mod(lookup); 14808 } else if (pt.n === prop) { 14809 if (pt.f === 2 && pt.t) { 14810 //a blob (text containing multiple numeric values) 14811 _roundLinkedList(pt.t._firstPT); 14812 } else { 14813 this._add(pt.t, prop, pt.s, pt.c); 14814 //remove from linked list 14815 if (next) { 14816 next._prev = pt._prev; 14817 } 14818 if (pt._prev) { 14819 pt._prev._next = next; 14820 } else if (tween._firstPT === pt) { 14821 tween._firstPT = next; 14822 } 14823 pt._next = pt._prev = null; 14824 tween._propLookup[prop] = rpt; 14825 } 14826 } 14827 pt = next; 14828 } 14829 } 14830 return false; 14831 }; 14832 p._add = function (target, p, s, c) { 14833 this._addTween(target, p, s, s + c, p, Math.round); 14834 this._overwriteProps.push(p); 14835 }; 14836 })(); 14837 14838 /* 14839 * ---------------------------------------------------------------- 14840 * AttrPlugin 14841 * ---------------------------------------------------------------- 14842 */ 14843 14844 (function () { 14845 _gsScope._gsDefine.plugin({ 14846 propName: "attr", 14847 API: 2, 14848 version: "0.6.1", 14849 //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run. 14850 init: function init(target, value, tween, index) { 14851 var p, end; 14852 if (typeof target.setAttribute !== "function") { 14853 return false; 14854 } 14855 for (p in value) { 14856 end = value[p]; 14857 if (typeof end === "function") { 14858 end = end(index, target); 14859 } 14860 this._addTween(target, "setAttribute", target.getAttribute(p) + "", end + "", p, false, p); 14861 this._overwriteProps.push(p); 14862 } 14863 return true; 14864 } 14865 }); 14866 })(); 14867 14868 /* 14869 * ---------------------------------------------------------------- 14870 * DirectionalRotationPlugin 14871 * ---------------------------------------------------------------- 14872 */ 14873 _gsScope._gsDefine.plugin({ 14874 propName: "directionalRotation", 14875 version: "0.3.1", 14876 API: 2, 14877 //called when the tween renders for the first time. This is where initial values should be recorded and any setup routines should run. 14878 init: function init(target, value, tween, index) { 14879 if (_typeof(value) !== "object") { 14880 value = { 14881 rotation: value 14882 }; 14883 } 14884 this.finals = {}; 14885 var cap = value.useRadians === true ? Math.PI * 2 : 360, 14886 min = 0.000001, 14887 p, 14888 v, 14889 start, 14890 end, 14891 dif, 14892 split; 14893 for (p in value) { 14894 if (p !== "useRadians") { 14895 end = value[p]; 14896 if (typeof end === "function") { 14897 end = end(index, target); 14898 } 14899 split = (end + "").split("_"); 14900 v = split[0]; 14901 start = parseFloat(typeof target[p] !== "function" ? target[p] : target[p.indexOf("set") || typeof target["get" + p.substr(3)] !== "function" ? p : "get" + p.substr(3)]()); 14902 end = this.finals[p] = typeof v === "string" && v.charAt(1) === "=" ? start + parseInt(v.charAt(0) + "1", 10) * Number(v.substr(2)) : Number(v) || 0; 14903 dif = end - start; 14904 if (split.length) { 14905 v = split.join("_"); 14906 if (v.indexOf("short") !== -1) { 14907 dif = dif % cap; 14908 if (dif !== dif % (cap / 2)) { 14909 dif = dif < 0 ? dif + cap : dif - cap; 14910 } 14911 } 14912 if (v.indexOf("_cw") !== -1 && dif < 0) { 14913 dif = (dif + cap * 9999999999) % cap - (dif / cap | 0) * cap; 14914 } else if (v.indexOf("ccw") !== -1 && dif > 0) { 14915 dif = (dif - cap * 9999999999) % cap - (dif / cap | 0) * cap; 14916 } 14917 } 14918 if (dif > min || dif < -min) { 14919 this._addTween(target, p, start, start + dif, p); 14920 this._overwriteProps.push(p); 14921 } 14922 } 14923 } 14924 return true; 14925 }, 14926 //called each time the values should be updated, and the ratio gets passed as the only parameter (typically it's a value between 0 and 1, but it can exceed those when using an ease like Elastic.easeOut or Back.easeOut, etc.) 14927 set: function set(ratio) { 14928 var pt; 14929 if (ratio !== 1) { 14930 this._super.setRatio.call(this, ratio); 14931 } else { 14932 pt = this._firstPT; 14933 while (pt) { 14934 if (pt.f) { 14935 pt.t[pt.p](this.finals[pt.p]); 14936 } else { 14937 pt.t[pt.p] = this.finals[pt.p]; 14938 } 14939 pt = pt._next; 14940 } 14941 } 14942 } 14943 })._autoCSS = true; 14944 14945 /* 14946 * ---------------------------------------------------------------- 14947 * EasePack 14948 * ---------------------------------------------------------------- 14949 */ 14950 _gsScope._gsDefine("easing.Back", ["easing.Ease"], function (Ease) { 14951 var w = _gsScope.GreenSockGlobals || _gsScope, 14952 gs = w.com.greensock, 14953 _2PI = Math.PI * 2, 14954 _HALF_PI = Math.PI / 2, 14955 _class = gs._class, 14956 _create = function _create(n, f) { 14957 var C = _class("easing." + n, function () {}, true), 14958 p = C.prototype = new Ease(); 14959 p.constructor = C; 14960 p.getRatio = f; 14961 return C; 14962 }, 14963 _easeReg = Ease.register || function () {}, 14964 //put an empty function in place just as a safety measure in case someone loads an OLD version of TweenLite.js where Ease.register doesn't exist. 14965 _wrap = function _wrap(name, EaseOut, EaseIn, EaseInOut, aliases) { 14966 var C = _class("easing." + name, { 14967 easeOut: new EaseOut(),
14968 easeIn: new EaseIn(), 14969 easeInOut: new EaseInOut() 14970 }, true); 14971 _easeReg(C, name); 14972 return C; 14973 }, 14974 EasePoint = function EasePoint(time, value, next) { 14975 this.t = time; 14976 this.v = value; 14977 if (next) { 14978 this.next = next; 14979 next.prev = this; 14980 this.c = next.v - value; 14981 this.gap = next.t - time; 14982 } 14983 }, 14984 //Back 14985 _createBack = function _createBack(n, f) { 14986 var C = _class("easing." + n, function (overshoot) { 14987 this._p1 = overshoot || overshoot === 0 ? overshoot : 1.70158; 14988 this._p2 = this._p1 * 1.525; 14989 }, true), 14990 p = C.prototype = new Ease(); 14991 p.constructor = C; 14992 p.getRatio = f; 14993 p.config = function (overshoot) { 14994 return new C(overshoot); 14995 }; 14996 return C; 14997 }, 14998 Back = _wrap("Back", _createBack("BackOut", function (p) { 14999 return (p = p - 1) * p * ((this._p1 + 1) * p + this._p1) + 1; 15000 }), _createBack("BackIn", function (p) { 15001 return p * p * ((this._p1 + 1) * p - this._p1); 15002 }), _createBack("BackInOut", function (p) { 15003 return (p *= 2) < 1 ? 0.5 * p * p * ((this._p2 + 1) * p - this._p2) : 0.5 * ((p -= 2) * p * ((this._p2 + 1) * p + this._p2) + 2); 15004 })), 15005 //SlowMo 15006 SlowMo = _class("easing.SlowMo", function (linearRatio, power, yoyoMode) { 15007 power = power || power === 0 ? power : 0.7; 15008 if (linearRatio == null) { 15009 linearRatio = 0.7; 15010 } else if (linearRatio > 1) { 15011 linearRatio = 1; 15012 } 15013 this._p = linearRatio !== 1 ? power : 0; 15014 this._p1 = (1 - linearRatio) / 2; 15015 this._p2 = linearRatio; 15016 this._p3 = this._p1 + this._p2; 15017 this._calcEnd = yoyoMode === true; 15018 }, true), 15019 p = SlowMo.prototype = new Ease(), 15020 SteppedEase, 15021 ExpoScaleEase, 15022 RoughEase, 15023 _createElastic; 15024 p.constructor = SlowMo; 15025 p.getRatio = function (p) { 15026 var r = p + (0.5 - p) * this._p; 15027 if (p < this._p1) { 15028 return this._calcEnd ? 1 - (p = 1 - p / this._p1) * p : r - (p = 1 - p / this._p1) * p * p * p * r; 15029 } else if (p > this._p3) { 15030 return this._calcEnd ? p === 1 ? 0 : 1 - (p = (p - this._p3) / this._p1) * p : r + (p - r) * (p = (p - this._p3) / this._p1) * p * p * p; //added p === 1 ? 0 to avoid floating point rounding errors from affecting the final value, like 1 - 0.7 = 0.30000000000000004 instead of 0.3 15031 } 15032 return this._calcEnd ? 1 : r; 15033 }; 15034 SlowMo.ease = new SlowMo(0.7, 0.7); 15035 p.config = SlowMo.config = function (linearRatio, power, yoyoMode) { 15036 return new SlowMo(linearRatio, power, yoyoMode); 15037 }; 15038 15039 //SteppedEase 15040 SteppedEase = _class("easing.SteppedEase", function (steps, immediateStart) { 15041 steps = steps || 1; 15042 this._p1 = 1 / steps; 15043 this._p2 = steps + (immediateStart ? 0 : 1); 15044 this._p3 = immediateStart ? 1 : 0; 15045 }, true); 15046 p = SteppedEase.prototype = new Ease(); 15047 p.constructor = SteppedEase; 15048 p.getRatio = function (p) { 15049 if (p < 0) { 15050 p = 0; 15051 } else if (p >= 1) { 15052 p = 0.999999999; 15053 } 15054 return ((this._p2 * p | 0) + this._p3) * this._p1; 15055 }; 15056 p.config = SteppedEase.config = function (steps, immediateStart) { 15057 return new SteppedEase(steps, immediateStart); 15058 }; 15059 15060 //ExpoScaleEase 15061 ExpoScaleEase = _class("easing.ExpoScaleEase", function (start, end, ease) { 15062 this._p1 = Math.log(end / start); 15063 this._p2 = end - start; 15064 this._p3 = start; 15065 this._ease = ease; 15066 }, true); 15067 p = ExpoScaleEase.prototype = new Ease(); 15068 p.constructor = ExpoScaleEase; 15069 p.getRatio = function (p) { 15070 if (this._ease) { 15071 p = this._ease.getRatio(p); 15072 } 15073 return (this._p3 * Math.exp(this._p1 * p) - this._p3) / this._p2; 15074 }; 15075 p.config = ExpoScaleEase.config = function (start, end, ease) { 15076 return new ExpoScaleEase(start, end, ease); 15077 }; 15078 15079 //RoughEase 15080 RoughEase = _class("easing.RoughEase", function (vars) { 15081 vars = vars || {}; 15082 var taper = vars.taper || "none", 15083 a = [], 15084 cnt = 0, 15085 points = (vars.points || 20) | 0, 15086 i = points, 15087 randomize = vars.randomize !== false, 15088 clamp = vars.clamp === true, 15089 template = vars.template instanceof Ease ? vars.template : null, 15090 strength = typeof vars.strength === "number" ? vars.strength * 0.4 : 0.4, 15091 x, 15092 y, 15093 bump, 15094 invX, 15095 obj, 15096 pnt; 15097 while (--i > -1) { 15098 x = randomize ? Math.random() : 1 / points * i; 15099 y = template ? template.getRatio(x) : x; 15100 if (taper === "none") { 15101 bump = strength; 15102 } else if (taper === "out") { 15103 invX = 1 - x; 15104 bump = invX * invX * strength; 15105 } else if (taper === "in") { 15106 bump = x * x * strength; 15107 } else if (x < 0.5) { 15108 //"both" (start) 15109 invX = x * 2; 15110 bump = invX * invX * 0.5 * strength; 15111 } else { 15112 //"both" (end) 15113 invX = (1 - x) * 2; 15114 bump = invX * invX * 0.5 * strength; 15115 } 15116 if (randomize) { 15117 y += Math.random() * bump - bump * 0.5; 15118 } else if (i % 2) { 15119 y += bump * 0.5; 15120 } else { 15121 y -= bump * 0.5; 15122 } 15123 if (clamp) { 15124 if (y > 1) { 15125 y = 1; 15126 } else if (y < 0) { 15127 y = 0; 15128 } 15129 } 15130 a[cnt++] = { 15131 x: x, 15132 y: y 15133 }; 15134 } 15135 a.sort(function (a, b) { 15136 return a.x - b.x; 15137 }); 15138 pnt = new EasePoint(1, 1, null); 15139 i = points; 15140 while (--i > -1) { 15141 obj = a[i]; 15142 pnt = new EasePoint(obj.x, obj.y, pnt); 15143 } 15144 this._prev = new EasePoint(0, 0, pnt.t !== 0 ? pnt : pnt.next); 15145 }, true); 15146 p = RoughEase.prototype = new Ease(); 15147 p.constructor = RoughEase; 15148 p.getRatio = function (p) { 15149 var pnt = this._prev; 15150 if (p > pnt.t) { 15151 while (pnt.next && p >= pnt.t) { 15152 pnt = pnt.next; 15153 } 15154 pnt = pnt.prev; 15155 } else { 15156 while (pnt.prev && p <= pnt.t) { 15157 pnt = pnt.prev; 15158 } 15159 } 15160 this._prev = pnt; 15161 return pnt.v + (p - pnt.t) / pnt.gap * pnt.c; 15162 }; 15163 p.config = function (vars) { 15164 return new RoughEase(vars); 15165 }; 15166 RoughEase.ease = new RoughEase(); 15167 15168 //Bounce 15169 _wrap("Bounce", _create("BounceOut", function (p) { 15170 if (p < 1 / 2.75) { 15171 return 7.5625 * p * p; 15172 } else if (p < 2 / 2.75) { 15173 return 7.5625 * (p -= 1.5 / 2.75) * p + 0.75; 15174 } else if (p < 2.5 / 2.75) { 15175 return 7.5625 * (p -= 2.25 / 2.75) * p + 0.9375; 15176 } 15177 return 7.5625 * (p -= 2.625 / 2.75) * p + 0.984375; 15178 }), _create("BounceIn", function (p) { 15179 if ((p = 1 - p) < 1 / 2.75) { 15180 return 1 - 7.5625 * p * p; 15181 } else if (p < 2 / 2.75) { 15182 return 1 - (7.5625 * (p -= 1.5 / 2.75) * p + 0.75); 15183 } else if (p < 2.5 / 2.75) { 15184 return 1 - (7.5625 * (p -= 2.25 / 2.75) * p + 0.9375); 15185 } 15186 return 1 - (7.5625 * (p -= 2.625 / 2.75) * p + 0.984375); 15187 }), _create("BounceInOut", function (p) { 15188 var invert = p < 0.5; 15189 if (invert) { 15190 p = 1 - p * 2; 15191 } else { 15192 p = p * 2 - 1; 15193 } 15194 if (p < 1 / 2.75) { 15195 p = 7.5625 * p * p; 15196 } else if (p < 2 / 2.75) { 15197 p = 7.5625 * (p -= 1.5 / 2.75) * p + 0.75; 15198 } else if (p < 2.5 / 2.75) { 15199 p = 7.5625 * (p -= 2.25 / 2.75) * p + 0.9375; 15200 } else { 15201 p = 7.5625 * (p -= 2.625 / 2.75) * p + 0.984375; 15202 } 15203 return invert ? (1 - p) * 0.5 : p * 0.5 + 0.5; 15204 })); 15205 15206 //CIRC 15207 _wrap("Circ", _create("CircOut", function (p) { 15208 return Math.sqrt(1 - (p = p - 1) * p); 15209 }), _create("CircIn", function (p) { 15210 return -(Math.sqrt(1 - p * p) - 1); 15211 }), _create("CircInOut", function (p) { 15212 return (p *= 2) < 1 ? -0.5 * (Math.sqrt(1 - p * p) - 1) : 0.5 * (Math.sqrt(1 - (p -= 2) * p) + 1); 15213 })); 15214 15215 //Elastic 15216 _createElastic = function _createElastic(n, f, def) { 15217 var C = _class("easing." + n, function (amplitude, period) { 15218 this._p1 = amplitude >= 1 ? amplitude : 1;
15218 //note: if amplitude is < 1, we simply adjust the period for a more natural feel. Otherwise the math doesn't work right and the curve starts at 1. 15219 this._p2 = (period || def) / (amplitude < 1 ? amplitude : 1); 15220 this._p3 = this._p2 / _2PI * (Math.asin(1 / this._p1) || 0); 15221 this._p2 = _2PI / this._p2; //precalculate to optimize 15222 }, true), 15223 p = C.prototype = new Ease(); 15224 p.constructor = C; 15225 p.getRatio = f; 15226 p.config = function (amplitude, period) { 15227 return new C(amplitude, period); 15228 }; 15229 return C; 15230 }; 15231 _wrap("Elastic", _createElastic("ElasticOut", function (p) { 15232 return this._p1 * Math.pow(2, -10 * p) * Math.sin((p - this._p3) * this._p2) + 1; 15233 }, 0.3), _createElastic("ElasticIn", function (p) { 15234 return -(this._p1 * Math.pow(2, 10 * (p -= 1)) * Math.sin((p - this._p3) * this._p2)); 15235 }, 0.3), _createElastic("ElasticInOut", function (p) { 15236 return (p *= 2) < 1 ? -0.5 * (this._p1 * Math.pow(2, 10 * (p -= 1)) * Math.sin((p - this._p3) * this._p2)) : this._p1 * Math.pow(2, -10 * (p -= 1)) * Math.sin((p - this._p3) * this._p2) * 0.5 + 1; 15237 }, 0.45)); 15238 15239 //Expo 15240 _wrap("Expo", _create("ExpoOut", function (p) { 15241 return 1 - Math.pow(2, -10 * p); 15242 }), _create("ExpoIn", function (p) { 15243 return Math.pow(2, 10 * (p - 1)) - 0.001; 15244 }), _create("ExpoInOut", function (p) { 15245 return (p *= 2) < 1 ? 0.5 * Math.pow(2, 10 * (p - 1)) : 0.5 * (2 - Math.pow(2, -10 * (p - 1))); 15246 })); 15247 15248 //Sine 15249 _wrap("Sine", _create("SineOut", function (p) { 15250 return Math.sin(p * _HALF_PI); 15251 }), _create("SineIn", function (p) { 15252 return -Math.cos(p * _HALF_PI) + 1; 15253 }), _create("SineInOut", function (p) { 15254 return -0.5 * (Math.cos(Math.PI * p) - 1); 15255 })); 15256 _class("easing.EaseLookup", { 15257 find: function find(s) { 15258 return Ease.map[s]; 15259 } 15260 }, true); 15261 15262 //register the non-standard eases 15263 _easeReg(w.SlowMo, "SlowMo", "ease,"); 15264 _easeReg(RoughEase, "RoughEase", "ease,"); 15265 _easeReg(SteppedEase, "SteppedEase", "ease,"); 15266 return Back; 15267 }, true); 15268}); 15269if (_gsScope._gsDefine) { 15270 _gsScope._gsQueue.pop()(); 15271} //necessary in case TweenLite was already loaded separately. 15272 15273/* 15274 * ---------------------------------------------------------------- 15275 * Base classes like TweenLite, SimpleTimeline, Ease, Ticker, etc. 15276 * ---------------------------------------------------------------- 15277 */ 15278(function (window, moduleName) { 15279 "use strict"; 15280 15281 var _exports = {}, 15282 _doc = window.document, 15283 _globals = window.GreenSockGlobals = window.GreenSockGlobals || window; 15284 if (_globals.TweenLite) { 15285 return; //in case the core set of classes is already loaded, don't instantiate twice. 15286 } 15287 var _namespace = function _namespace(ns) { 15288 var a = ns.split("."), 15289 p = _globals, 15290 i; 15291 for (i = 0; i < a.length; i++) { 15292 p[a[i]] = p = p[a[i]] || {}; 15293 } 15294 return p; 15295 }, 15296 gs = _namespace("com.greensock"), 15297 _tinyNum = 0.0000000001, 15298 _slice = function _slice(a) { 15299 //don't use Array.prototype.slice.call(target, 0) because that doesn't work in IE8 with a NodeList that's returned by querySelectorAll() 15300 var b = [], 15301 l = a.length, 15302 i; 15303 for (i = 0; i !== l; b.push(a[i++])) {} 15304 return b; 15305 }, 15306 _emptyFunc = function _emptyFunc() {}, 15307 _isArray = function () { 15308 //works around issues in iframe environments where the Array global isn't shared, thus if the object originates in a different window/iframe, "(obj instanceof Array)" will evaluate false. We added some speed optimizations to avoid Object.prototype.toString.call() unless it's absolutely necessary because it's VERY slow (like 20x slower) 15309 var toString = Object.prototype.toString, 15310 array = toString.call([]); 15311 return function (obj) { 15312 return obj != null && (obj instanceof Array || _typeof(obj) === "object" && !!obj.push && toString.call(obj) === array); 15313 }; 15314 }(), 15315 a, 15316 i, 15317 p, 15318 _ticker, 15319 _tickerActive, 15320 _defLookup = {}, 15321 /** 15322 * @constructor 15323 * Defines a GreenSock class, optionally with an array of dependencies that must be instantiated first and passed into the definition. 15324 * This allows users to load GreenSock JS files in any order even if they have interdependencies (like CSSPlugin extends TweenPlugin which is 15325 * inside TweenLite.js, but if CSSPlugin is loaded first, it should wait to run its code until TweenLite.js loads and instantiates TweenPlugin 15326 * and then pass TweenPlugin to CSSPlugin's definition). This is all done automatically and internally. 15327 * 15328 * Every definition will be added to a "com.greensock" global object (typically window, but if a window.GreenSockGlobals object is found, 15329 * it will go there as of v1.7). For example, TweenLite will be found at window.com.greensock.TweenLite and since it's a global class that should be available anywhere, 15330 * it is ALSO referenced at window.TweenLite. However some classes aren't considered global, like the base com.greensock.core.Animation class, so 15331 * those will only be at the package like window.com.greensock.core.Animation. Again, if you define a GreenSockGlobals object on the window, everything 15332 * gets tucked neatly inside there instead of on the window directly. This allows you to do advanced things like load multiple versions of GreenSock 15333 * files and put them into distinct objects (imagine a banner ad uses a newer version but the main site uses an older one). In that case, you could
15334 * sandbox the banner one like: 15335 * 15336 * <script> 15337 * var gs = window.GreenSockGlobals = {}; //the newer version we're about to load could now be referenced in a "gs" object, like gs.TweenLite.to(...). Use whatever alias you want as long as it's unique, "gs" or "banner" or whatever. 15338 * </script> 15339 * <script src="js/greensock/v1.7/TweenMax.js"></script> 15340 * <script> 15341 * window.GreenSockGlobals = window._gsQueue = window._gsDefine = null; //reset it back to null (along with the special _gsQueue variable) so that the next load of TweenMax affects the window and we can reference things directly like TweenLite.to(...) 15342 * </script> 15343 * <script src="js/greensock/v1.6/TweenMax.js"></script> 15344 * <script> 15345 * gs.TweenLite.to(...); //would use v1.7 15346 * TweenLite.to(...); //would use v1.6 15347 * </script> 15348 * 15349 * @param {!string} ns The namespace of the class definition, leaving off "com.greensock." as that's assumed. For example, "TweenLite" or "plugins.CSSPlugin" or "easing.Back". 15350 * @param {!Array.<string>} dependencies An array of dependencies (described as their namespaces minus "com.greensock." prefix). For example ["TweenLite","plugins.TweenPlugin","core.Animation"] 15351 * @param {!function():Object} func The function that should be called and passed the resolved dependencies which will return the actual class for this definition. 15352 * @param {boolean=} global If true, the class will be added to the global scope (typically window unless you define a window.GreenSockGlobals object) 15353 */ 15354 _Definition = function Definition(ns, dependencies, func, global) { 15355 this.sc = _defLookup[ns] ? _defLookup[ns].sc : []; //subclasses 15356 _defLookup[ns] = this; 15357 this.gsClass = null; 15358 this.func = func; 15359 var _classes = []; 15360 this.check = function (init) { 15361 var i = dependencies.length, 15362 missing = i, 15363 cur, 15364 a, 15365 n, 15366 cl; 15367 while (--i > -1) { 15368 if ((cur = _defLookup[dependencies[i]] || new _Definition(dependencies[i], [])).gsClass) { 15369 _classes[i] = cur.gsClass; 15370 missing--; 15371 } else if (init) { 15372 cur.sc.push(this); 15373 } 15374 } 15375 if (missing === 0 && func) { 15376 a = ("com.greensock." + ns).split("."); 15377 n = a.pop(); 15378 cl = _namespace(a.join("."))[n] = this.gsClass = func.apply(func, _classes); 15379 15380 //exports to multiple environments 15381 if (global) { 15382 _globals[n] = _exports[n] = cl; //provides a way to avoid global namespace pollution. By default, the main classes like TweenLite, Power1, Strong, etc. are added to window unless a GreenSockGlobals is defined. So if you want to have things added to a custom object instead, just do something like window.GreenSockGlobals = {} before loading any GreenSock files. You can even set up an alias like window.GreenSockGlobals = windows.gs = {} so that you can access everything like gs.TweenLite. Also remember that ALL classes are added to the window.com.greensock object (in their respective packages, like com.greensock.easing.Power1, com.greensock.TweenLite, etc.) 15383 if (typeof module !== "undefined" && module.exports) { 15384 //node 15385 if (ns === moduleName) { 15386 module.exports = _exports[moduleName] = cl; 15387 for (i in _exports) { 15388 cl[i] = _exports[i]; 15389 } 15390 } else if (_exports[moduleName]) { 15391 _exports[moduleName][n] = cl; 15392 } 15393 } else if (typeof define === "function" && define.amd) { 15394 //AMD 15395 define((window.GreenSockAMDPath ? window.GreenSockAMDPath + "/" : "") + ns.split(".").pop(), [], function () { 15396 return cl; 15397 }); 15398 } 15399 } 15400 for (i = 0; i < this.sc.length; i++) { 15401 this.sc[i].check(); 15402 } 15403 } 15404 }; 15405 this.check(true); 15406 }, 15407 //used to create Definition instances (which basically registers a class that has dependencies). 15408 _gsDefine = window._gsDefine = function (ns, dependencies, func, global) { 15409 return new _Definition(ns, dependencies, func, global); 15410 }, 15411 //a quick way to create a class that doesn't have any dependencies. Returns the class, but first registers it in the GreenSock namespace so that other classes can grab it (other classes might be dependent on the class). 15412 _class = gs._class = function (ns, func, global) { 15413 func = func || function () {}; 15414 _gsDefine(ns, [], function () { 15415 return func; 15416 }, global); 15417 return func; 15418 }; 15419 _gsDefine.globals = _globals; 15420 15421 /* 15422 * ---------------------------------------------------------------- 15423 * Ease 15424 * ---------------------------------------------------------------- 15425 */ 15426 var _baseParams = [0, 0, 1, 1], 15427 Ease = _class("easing.Ease", function (func, extraParams, type, power) { 15428 this._func = func; 15429 this._type = type || 0; 15430 this._power = power || 0; 15431 this._params = extraParams ? _baseParams.concat(extraParams) : _baseParams; 15432 }, true), 15433 _easeMap = Ease.map = {}, 15434 _easeReg = Ease.register = function (ease, names, types, create) { 15435 var na = names.split(","), 15436 i = na.length, 15437 ta = (types || "easeIn,easeOut,easeInOut").split(","), 15438 e, 15439 name, 15440 j, 15441 type; 15442 while (--i > -1) { 15443 name = na[i]; 15444 e = create ? _class("easing." + name, null, true) : gs.easing[name] || {}; 15445 j = ta.length; 15446 while (--j > -1) { 15447 type = ta[j]; 15448 _easeMap[name + "." + type] = _easeMap[type + name] = e[type] = ease.getRatio ? ease : ease[type] || new ease(); 15449 } 15450 } 15451 }; 15452 p = Ease.prototype; 15453 p._calcEnd = false;
15454 p.getRatio = function (p) { 15455 if (this._func) { 15456 this._params[0] = p; 15457 return this._func.apply(null, this._params); 15458 } 15459 var t = this._type, 15460 pw = this._power, 15461 r = t === 1 ? 1 - p : t === 2 ? p : p < 0.5 ? p * 2 : (1 - p) * 2; 15462 if (pw === 1) { 15463 r *= r; 15464 } else if (pw === 2) { 15465 r *= r * r; 15466 } else if (pw === 3) { 15467 r *= r * r * r; 15468 } else if (pw === 4) { 15469 r *= r * r * r * r; 15470 } 15471 return t === 1 ? 1 - r : t === 2 ? r : p < 0.5 ? r / 2 : 1 - r / 2; 15472 }; 15473 15474 //create all the standard eases like Linear, Quad, Cubic, Quart, Quint, Strong, Power0, Power1, Power2, Power3, and Power4 (each with easeIn, easeOut, and easeInOut) 15475 a = ["Linear", "Quad", "Cubic", "Quart", "Quint,Strong"]; 15476 i = a.length; 15477 while (--i > -1) { 15478 p = a[i] + ",Power" + i; 15479 _easeReg(new Ease(null, null, 1, i), p, "easeOut", true); 15480 _easeReg(new Ease(null, null, 2, i), p, "easeIn" + (i === 0 ? ",easeNone" : "")); 15481 _easeReg(new Ease(null, null, 3, i), p, "easeInOut"); 15482 } 15483 _easeMap.linear = gs.easing.Linear.easeIn; 15484 _easeMap.swing = gs.easing.Quad.easeInOut; //for jQuery folks 15485 15486 /* 15487 * ---------------------------------------------------------------- 15488 * EventDispatcher 15489 * ---------------------------------------------------------------- 15490 */ 15491 var EventDispatcher = _class("events.EventDispatcher", function (target) { 15492 this._listeners = {}; 15493 this._eventTarget = target || this; 15494 }); 15495 p = EventDispatcher.prototype; 15496 p.addEventListener = function (type, callback, scope, useParam, priority) { 15497 priority = priority || 0; 15498 var list = this._listeners[type], 15499 index = 0, 15500 listener, 15501 i; 15502 if (this === _ticker && !_tickerActive) { 15503 _ticker.wake(); 15504 } 15505 if (list == null) { 15506 this._listeners[type] = list = []; 15507 } 15508 i = list.length; 15509 while (--i > -1) { 15510 listener = list[i]; 15511 if (listener.c === callback && listener.s === scope) { 15512 list.splice(i, 1); 15513 } else if (index === 0 && listener.pr < priority) { 15514 index = i + 1; 15515 } 15516 } 15517 list.splice(index, 0, { 15518 c: callback, 15519 s: scope, 15520 up: useParam, 15521 pr: priority 15522 }); 15523 }; 15524 p.removeEventListener = function (type, callback) { 15525 var list = this._listeners[type], 15526 i; 15527 if (list) { 15528 i = list.length; 15529 while (--i > -1) { 15530 if (list[i].c === callback) { 15531 list.splice(i, 1); 15532 return; 15533 } 15534 } 15535 } 15536 }; 15537 p.dispatchEvent = function (type) { 15538 var list = this._listeners[type], 15539 i, 15540 t, 15541 listener; 15542 if (list) { 15543 i = list.length; 15544 if (i > 1) { 15545 list = list.slice(0); //in case addEventListener() is called from within a listener/callback (otherwise the index could change, resulting in a skip) 15546 } 15547 t = this._eventTarget; 15548 while (--i > -1) { 15549 listener = list[i]; 15550 if (listener) { 15551 if (listener.up) { 15552 listener.c.call(listener.s || t, { 15553 type: type, 15554 target: t 15555 }); 15556 } else { 15557 listener.c.call(listener.s || t); 15558 } 15559 } 15560 } 15561 } 15562 }; 15563 15564 /* 15565 * ---------------------------------------------------------------- 15566 * Ticker 15567 * ---------------------------------------------------------------- 15568 */ 15569 var _reqAnimFrame = window.requestAnimationFrame, 15570 _cancelAnimFrame = window.cancelAnimationFrame, 15571 _getTime = Date.now || function () { 15572 return new Date().getTime(); 15573 }, 15574 _lastUpdate = _getTime(); 15575 15576 //now try to determine the requestAnimationFrame and cancelAnimationFrame functions and if none are found, we'll use a setTimeout()/clearTimeout() polyfill. 15577 a = ["ms", "moz", "webkit", "o"]; 15578 i = a.length; 15579 while (--i > -1 && !_reqAnimFrame) { 15580 _reqAnimFrame = window[a[i] + "RequestAnimationFrame"]; 15581 _cancelAnimFrame = window[a[i] + "CancelAnimationFrame"] || window[a[i] + "CancelRequestAnimationFrame"]; 15582 } 15583 _class("Ticker", function (fps, useRAF) { 15584 var _self = this, 15585 _startTime = _getTime(), 15586 _useRAF = useRAF !== false && _reqAnimFrame ? "auto" : false, 15587 _lagThreshold = 500, 15588 _adjustedLag = 33, 15589 _tickWord = "tick", 15590 //helps reduce gc burden 15591 _fps, 15592 _req, 15593 _id, 15594 _gap, 15595 _nextTime, 15596 _tick2 = function _tick(manual) {
15597 var elapsed = _getTime() - _lastUpdate, 15598 overlap, 15599 dispatch; 15600 if (elapsed > _lagThreshold) { 15601 _startTime += elapsed - _adjustedLag; 15602 } 15603 _lastUpdate += elapsed; 15604 _self.time = (_lastUpdate - _startTime) / 1000; 15605 overlap = _self.time - _nextTime; 15606 if (!_fps || overlap > 0 || manual === true) { 15607 _self.frame++; 15608 _nextTime += overlap + (overlap >= _gap ? 0.004 : _gap - overlap); 15609 dispatch = true; 15610 } 15611 if (manual !== true) { 15612 //make sure the request is made before we dispatch the "tick" event so that timing is maintained. Otherwise, if processing the "tick" requires a bunch of time (like 15ms) and we're using a setTimeout() that's based on 16.7ms, it'd technically take 31.7ms between frames otherwise. 15613 _id = _req(_tick2); 15614 } 15615 if (dispatch) { 15616 _self.dispatchEvent(_tickWord); 15617 } 15618 }; 15619 EventDispatcher.call(_self); 15620 _self.time = _self.frame = 0; 15621 _self.tick = function () { 15622 _tick2(true); 15623 }; 15624 _self.lagSmoothing = function (threshold, adjustedLag) { 15625 if (!arguments.length) { 15626 //if lagSmoothing() is called with no arguments, treat it like a getter that returns a boolean indicating if it's enabled or not. This is purposely undocumented and is for internal use. 15627 return _lagThreshold < 1 / _tinyNum; 15628 } 15629 _lagThreshold = threshold || 1 / _tinyNum; //zero should be interpreted as basically unlimited 15630 _adjustedLag = Math.min(adjustedLag, _lagThreshold, 0); 15631 }; 15632 _self.sleep = function () { 15633 if (_id == null) { 15634 return; 15635 } 15636 if (!_useRAF || !_cancelAnimFrame) { 15637 clearTimeout(_id); 15638 } else { 15639 _cancelAnimFrame(_id); 15640 } 15641 _req = _emptyFunc; 15642 _id = null; 15643 if (_self === _ticker) { 15644 _tickerActive = false; 15645 } 15646 }; 15647 _self.wake = function (seamless) { 15648 if (_id !== null) { 15649 _self.sleep(); 15650 } else if (seamless) { 15651 _startTime += -_lastUpdate + (_lastUpdate = _getTime()); 15652 } else if (_self.frame > 10) { 15653 //don't trigger lagSmoothing if we're just waking up, and make sure that at least 10 frames have elapsed because of the iOS bug that we work around below with the 1.5-second setTimout(). 15654 _lastUpdate = _getTime() - _lagThreshold + 5; 15655 } 15656 _req = _fps === 0 ? _emptyFunc : !_useRAF || !_reqAnimFrame ? function (f) { 15657 return setTimeout(f, (_nextTime - _self.time) * 1000 + 1 | 0); 15658 } : _reqAnimFrame; 15659 if (_self === _ticker) { 15660 _tickerActive = true; 15661 } 15662 _tick2(2); 15663 }; 15664 _self.fps = function (value) { 15665 if (!arguments.length) { 15666 return _fps; 15667 } 15668 _fps = value; 15669 _gap = 1 / (_fps || 60); 15670 _nextTime = this.time + _gap; 15671 _self.wake(); 15672 }; 15673 _self.useRAF = function (value) { 15674 if (!arguments.length) { 15675 return _useRAF; 15676 } 15677 _self.sleep(); 15678 _useRAF = value; 15679 _self.fps(_fps); 15680 }; 15681 _self.fps(fps); 15682 15683 //a bug in iOS 6 Safari occasionally prevents the requestAnimationFrame from working initially, so we use a 1.5-second timeout that automatically falls back to setTimeout() if it senses this condition. 15684 setTimeout(function () { 15685 if (_useRAF === "auto" && _self.frame < 5 && (_doc || {}).visibilityState !== "hidden") { 15686 _self.useRAF(false); 15687 } 15688 }, 1500); 15689 }); 15690 p = gs.Ticker.prototype = new gs.events.EventDispatcher(); 15691 p.constructor = gs.Ticker; 15692 15693 /* 15694 * ---------------------------------------------------------------- 15695 * Animation 15696 * ---------------------------------------------------------------- 15697 */ 15698 var Animation = _class("core.Animation", function (duration, vars) { 15699 this.vars = vars = vars || {}; 15700 this._duration = this._totalDuration = duration || 0; 15701 this._delay = Number(vars.delay) || 0; 15702 this._timeScale = 1; 15703 this._active = vars.immediateRender === true; 15704 this.data = vars.data; 15705 this._reversed = vars.reversed === true; 15706 if (!_rootTimeline) { 15707 return; 15708 } 15709 if (!_tickerActive) { 15710 //some browsers (like iOS 6 Safari) shut down JavaScript execution when the tab is disabled and they [occasionally] neglect to start up requestAnimationFrame again when returning - this code ensures that the engine starts up again properly. 15711 _ticker.wake(); 15712 } 15713 var tl = this.vars.useFrames ? _rootFramesTimeline : _rootTimeline; 15714 tl.add(this, tl._time); 15715 if (this.vars.paused) { 15716 this.paused(true); 15717 } 15718 }); 15719 _ticker = Animation.ticker = new gs.Ticker(); 15720 p = Animation.prototype; 15721 p._dirty = p._gc = p._initted = p._paused = false;
15722 p._totalTime = p._time = 0; 15723 p._rawPrevTime = -1; 15724 p._next = p._last = p._onUpdate = p._timeline = p.timeline = null; 15725 p._paused = false; 15726 15727 //some browsers (like iOS) occasionally drop the requestAnimationFrame event when the user switches to a different tab and then comes back again, so we use a 2-second setTimeout() to sense if/when that condition occurs and then wake() the ticker. 15728 var _checkTimeout2 = function _checkTimeout() { 15729 if (_tickerActive && _getTime() - _lastUpdate > 2000 && ((_doc || {}).visibilityState !== "hidden" || !_ticker.lagSmoothing())) { 15730 //note: if the tab is hidden, we should still wake if lagSmoothing has been disabled. 15731 _ticker.wake(); 15732 } 15733 var t = setTimeout(_checkTimeout2, 2000); 15734 if (t.unref) { 15735 // allows a node process to exit even if the timeout’s callback hasn't been invoked. Without it, the node process could hang as this function is called every two seconds. 15736 t.unref(); 15737 } 15738 }; 15739 _checkTimeout2(); 15740 p.play = function (from, suppressEvents) { 15741 if (from != null) { 15742 this.seek(from, suppressEvents); 15743 } 15744 return this.reversed(false).paused(false); 15745 }; 15746 p.pause = function (atTime, suppressEvents) { 15747 if (atTime != null) { 15748 this.seek(atTime, suppressEvents); 15749 } 15750 return this.paused(true); 15751 }; 15752 p.resume = function (from, suppressEvents) { 15753 if (from != null) { 15754 this.seek(from, suppressEvents); 15755 } 15756 return this.paused(false); 15757 }; 15758 p.seek = function (time, suppressEvents) { 15759 return this.totalTime(Number(time), suppressEvents !== false); 15760 }; 15761 p.restart = function (includeDelay, suppressEvents) { 15762 return this.reversed(false).paused(false).totalTime(includeDelay ? -this._delay : 0, suppressEvents !== false, true); 15763 }; 15764 p.reverse = function (from, suppressEvents) { 15765 if (from != null) { 15766 this.seek(from || this.totalDuration(), suppressEvents); 15767 } 15768 return this.reversed(true).paused(false); 15769 }; 15770 p.render = function (time, suppressEvents, force) { 15771 //stub - we override this method in subclasses. 15772 }; 15773 p.invalidate = function () { 15774 this._time = this._totalTime = 0; 15775 this._initted = this._gc = false; 15776 this._rawPrevTime = -1; 15777 if (this._gc || !this.timeline) { 15778 this._enabled(true); 15779 } 15780 return this; 15781 }; 15782 p.isActive = function () { 15783 var tl = this._timeline, 15784 //the 2 root timelines won't have a _timeline; they're always active. 15785 startTime = this._startTime, 15786 rawTime; 15787 return !tl || !this._gc && !this._paused && tl.isActive() && (rawTime = tl.rawTime(true)) >= startTime && rawTime < startTime + this.totalDuration() / this._timeScale - 0.0000001; 15788 }; 15789 p._enabled = function (enabled, ignoreTimeline) { 15790 if (!_tickerActive) { 15791 _ticker.wake(); 15792 } 15793 this._gc = !enabled; 15794 this._active = this.isActive(); 15795 if (ignoreTimeline !== true) { 15796 if (enabled && !this.timeline) { 15797 this._timeline.add(this, this._startTime - this._delay); 15798 } else if (!enabled && this.timeline) { 15799 this._timeline._remove(this, true); 15800 } 15801 } 15802 return false; 15803 }; 15804 p._kill = function (vars, target) { 15805 return this._enabled(false, false); 15806 }; 15807 p.kill = function (vars, target) { 15808 this._kill(vars, target); 15809 return this; 15810 }; 15811 p._uncache = function (includeSelf) { 15812 var tween = includeSelf ? this : this.timeline; 15813 while (tween) { 15814 tween._dirty = true; 15815 tween = tween.timeline; 15816 } 15817 return this; 15818 }; 15819 p._swapSelfInParams = function (params) { 15820 var i = params.length, 15821 copy = params.concat(); 15822 while (--i > -1) { 15823 if (params[i] === "{self}") { 15824 copy[i] = this; 15825 } 15826 } 15827 return copy; 15828 }; 15829 p._callback = function (type) { 15830 var v = this.vars, 15831 callback = v[type], 15832 params = v[type + "Params"], 15833 scope = v[type + "Scope"] || v.callbackScope || this, 15834 l = params ? params.length : 0; 15835 switch (l) { 15836 //speed optimization; call() is faster than apply() so use it when there are only a few parameters (which is by far most common). Previously we simply did var v = this.vars; v[type].apply(v[type + "Scope"] || v.callbackScope || this, v[type + "Params"] || _blankArray); 15837 case 0: 15838 callback.call(scope); 15839 break; 15840 case 1: 15841 callback.call(scope, params[0]); 15842 break; 15843 case 2: 15844 callback.call(scope, params[0], params[1]); 15845 break; 15846 default: 15847 callback.apply(scope, params); 15848 } 15849 }; 15850 15851 //----Animation getters/setters -------------------------------------------------------- 15852 15853 p.eventCallback = function (type, callback, params, scope) { 15854 if ((type || "").substr(0, 2) === "on") { 15855 var v = this.vars; 15856 if (arguments.length === 1) { 15857 return v[type]; 15858 } 15859 if (callback == null) { 15860 delete v[type]; 15861 } else { 15862 v[type] = callback; 15863 v[type + "Params"] = _isArray(params) && params.join("").indexOf("{self}") !== -1 ? this._swapSelfInParams(params) : params; 15864 v[type + "Scope"] = scope; 15865 } 15866 if (type === "onUpdate") { 15867 this._onUpdate = callback; 15868 } 15869 } 15870 return this; 15871 }; 15872 p.delay = function (value) { 15873 if (!arguments.length) { 15874 return this._delay; 15875 } 15876 if (this._timeline.smoothChildTiming) { 15877 this.startTime(this._startTime + value - this._delay); 15878 }
15879 this._delay = value; 15880 return this; 15881 }; 15882 p.duration = function (value) { 15883 if (!arguments.length) { 15884 this._dirty = false; 15885 return this._duration; 15886 } 15887 this._duration = this._totalDuration = value; 15888 this._uncache(true); //true in case it's a TweenMax or TimelineMax that has a repeat - we'll need to refresh the totalDuration. 15889 if (this._timeline.smoothChildTiming) if (this._time > 0) if (this._time < this._duration) if (value !== 0) { 15890 this.totalTime(this._totalTime * (value / this._duration), true); 15891 } 15892 return this; 15893 }; 15894 p.totalDuration = function (value) { 15895 this._dirty = false; 15896 return !arguments.length ? this._totalDuration : this.duration(value); 15897 }; 15898 p.time = function (value, suppressEvents) { 15899 if (!arguments.length) { 15900 return this._time; 15901 } 15902 if (this._dirty) { 15903 this.totalDuration(); 15904 } 15905 return this.totalTime(value > this._duration ? this._duration : value, suppressEvents); 15906 }; 15907 p.totalTime = function (time, suppressEvents, uncapped) { 15908 if (!_tickerActive) { 15909 _ticker.wake(); 15910 } 15911 if (!arguments.length) { 15912 return this._totalTime; 15913 } 15914 if (this._timeline) { 15915 if (time < 0 && !uncapped) { 15916 time += this.totalDuration(); 15917 } 15918 if (this._timeline.smoothChildTiming) { 15919 if (this._dirty) { 15920 this.totalDuration(); 15921 } 15922 var totalDuration = this._totalDuration, 15923 tl = this._timeline; 15924 if (time > totalDuration && !uncapped) { 15925 time = totalDuration; 15926 } 15927 this._startTime = (this._paused ? this._pauseTime : tl._time) - (!this._reversed ? time : totalDuration - time) / this._timeScale; 15928 if (!tl._dirty) { 15929 //for performance improvement. If the parent's cache is already dirty, it already took care of marking the ancestors as dirty too, so skip the function call here. 15930 this._uncache(false); 15931 } 15932 //in case any of the ancestor timelines had completed but should now be enabled, we should reset their totalTime() which will also ensure that they're lined up properly and enabled. Skip for animations that are on the root (wasteful). Example: a TimelineLite.exportRoot() is performed when there's a paused tween on the root, the export will not complete until that tween is unpaused, but imagine a child gets restarted later, after all [unpaused] tweens have completed. The startTime of that child would get pushed out, but one of the ancestors may have completed. 15933 if (tl._timeline) { 15934 while (tl._timeline) { 15935 if (tl._timeline._time !== (tl._startTime + tl._totalTime) / tl._timeScale) { 15936 tl.totalTime(tl._totalTime, true); 15937 } 15938 tl = tl._timeline; 15939 } 15940 } 15941 } 15942 if (this._gc) { 15943 this._enabled(true, false); 15944 } 15945 if (this._totalTime !== time || this._duration === 0) { 15946 if (_lazyTweens.length) { 15947 _lazyRender(); 15948 } 15949 this.render(time, suppressEvents, false); 15950 if (_lazyTweens.length) { 15951 //in case rendering caused any tweens to lazy-init, we should render them because typically when someone calls seek() or time() or progress(), they expect an immediate render. 15952 _lazyRender(); 15953 } 15954 } 15955 } 15956 return this; 15957 }; 15958 p.progress = p.totalProgress = function (value, suppressEvents) { 15959 var duration = this.duration(); 15960 return !arguments.length ? duration ? this._time / duration : this.ratio : this.totalTime(duration * value, suppressEvents); 15961 }; 15962 p.startTime = function (value) { 15963 if (!arguments.length) { 15964 return this._startTime; 15965 } 15966 if (value !== this._startTime) { 15967 this._startTime = value; 15968 if (this.timeline) if (this.timeline._sortChildren) { 15969 this.timeline.add(this, value - this._delay); //ensures that any necessary re-sequencing of Animations in the timeline occurs to make sure the rendering order is correct. 15970 } 15971 } 15972 return this; 15973 }; 15974 p.endTime = function (includeRepeats) { 15975 return this._startTime + (includeRepeats != false ? this.totalDuration() : this.duration()) / this._timeScale; 15976 }; 15977 p.timeScale = function (value) { 15978 if (!arguments.length) { 15979 return this._timeScale; 15980 } 15981 var pauseTime, t; 15982 value = value || _tinyNum; //can't allow zero because it'll throw the math off 15983 if (this._timeline && this._timeline.smoothChildTiming) { 15984 pauseTime = this._pauseTime; 15985 t = pauseTime || pauseTime === 0 ? pauseTime : this._timeline.totalTime(); 15986 this._startTime = t - (t - this._startTime) * this._timeScale / value; 15987 } 15988 this._timeScale = value; 15989 t = this.timeline; 15990 while (t && t.timeline) { 15991 //must update the duration/totalDuration of all ancestor timelines immediately in case in the middle of a render loop, one tween alters another tween's timeScale which shoves its startTime before 0, forcing the parent timeline to shift around and shiftChildren() which could affect that next tween's render (startTime). Doesn't matter for the root timeline though. 15992 t._dirty = true; 15993 t.totalDuration(); 15994 t = t.timeline; 15995 } 15996 return this; 15997 }; 15998 p.reversed = function (value) { 15999 if (!arguments.length) { 16000 return this._reversed; 16001 } 16002 if (value != this._reversed) { 16003 this._reversed = value; 16004 this.totalTime(this._timeline && !this._timeline.smoothChildTiming ? this.totalDuration() - this._totalTime : this._totalTime, true); 16005 } 16006 return this; 16007 }; 16008 p.paused = function (value) { 16009 if (!arguments.length) { 16010 return this._paused; 16011 } 16012 var tl = this._timeline, 16013 raw, 16014 elapsed; 16015 if (value != this._paused) if (tl) { 16016 if (!_tickerActive && !value) { 16017 _ticker.wake(); 16018 } 16019 raw = tl.rawTime();
16020 elapsed = raw - this._pauseTime; 16021 if (!value && tl.smoothChildTiming) { 16022 this._startTime += elapsed; 16023 this._uncache(false); 16024 } 16025 this._pauseTime = value ? raw : null; 16026 this._paused = value; 16027 this._active = this.isActive(); 16028 if (!value && elapsed !== 0 && this._initted && this.duration()) { 16029 raw = tl.smoothChildTiming ? this._totalTime : (raw - this._startTime) / this._timeScale; 16030 this.render(raw, raw === this._totalTime, true); //in case the target's properties changed via some other tween or manual update by the user, we should force a render. 16031 } 16032 } 16033 if (this._gc && !value) { 16034 this._enabled(true, false); 16035 } 16036 return this; 16037 }; 16038 16039 /* 16040 * ---------------------------------------------------------------- 16041 * SimpleTimeline 16042 * ---------------------------------------------------------------- 16043 */ 16044 var SimpleTimeline = _class("core.SimpleTimeline", function (vars) { 16045 Animation.call(this, 0, vars); 16046 this.autoRemoveChildren = this.smoothChildTiming = true; 16047 }); 16048 p = SimpleTimeline.prototype = new Animation(); 16049 p.constructor = SimpleTimeline; 16050 p.kill()._gc = false; 16051 p._first = p._last = p._recent = null; 16052 p._sortChildren = false; 16053 p.add = p.insert = function (child, position, align, stagger) { 16054 var prevTween, st; 16055 child._startTime = Number(position || 0) + child._delay; 16056 if (child._paused) if (this !== child._timeline) { 16057 //we only adjust the _pauseTime if it wasn't in this timeline already. Remember, sometimes a tween will be inserted again into the same timeline when its startTime is changed so that the tweens in the TimelineLite/Max are re-ordered properly in the linked list (so everything renders in the proper order). 16058 child._pauseTime = child._startTime + (this.rawTime() - child._startTime) / child._timeScale; 16059 } 16060 if (child.timeline) { 16061 child.timeline._remove(child, true); //removes from existing timeline so that it can be properly added to this one. 16062 } 16063 child.timeline = child._timeline = this; 16064 if (child._gc) { 16065 child._enabled(true, true); 16066 } 16067 prevTween = this._last; 16068 if (this._sortChildren) { 16069 st = child._startTime; 16070 while (prevTween && prevTween._startTime > st) { 16071 prevTween = prevTween._prev; 16072 } 16073 } 16074 if (prevTween) { 16075 child._next = prevTween._next; 16076 prevTween._next = child; 16077 } else { 16078 child._next = this._first; 16079 this._first = child; 16080 } 16081 if (child._next) { 16082 child._next._prev = child; 16083 } else { 16084 this._last = child; 16085 } 16086 child._prev = prevTween; 16087 this._recent = child; 16088 if (this._timeline) { 16089 this._uncache(true); 16090 } 16091 return this; 16092 }; 16093 p._remove = function (tween, skipDisable) { 16094 if (tween.timeline === this) { 16095 if (!skipDisable) { 16096 tween._enabled(false, true); 16097 } 16098 if (tween._prev) { 16099 tween._prev._next = tween._next; 16100 } else if (this._first === tween) { 16101 this._first = tween._next; 16102 } 16103 if (tween._next) { 16104 tween._next._prev = tween._prev; 16105 } else if (this._last === tween) { 16106 this._last = tween._prev; 16107 } 16108 tween._next = tween._prev = tween.timeline = null; 16109 if (tween === this._recent) { 16110 this._recent = this._last; 16111 } 16112 if (this._timeline) { 16113 this._uncache(true); 16114 } 16115 } 16116 return this; 16117 }; 16118 p.render = function (time, suppressEvents, force) { 16119 var tween = this._first, 16120 next; 16121 this._totalTime = this._time = this._rawPrevTime = time; 16122 while (tween) { 16123 next = tween._next; //record it here because the value could change after rendering... 16124 if (tween._active || time >= tween._startTime && !tween._paused && !tween._gc) { 16125 if (!tween._reversed) { 16126 tween.render((time - tween._startTime) * tween._timeScale, suppressEvents, force); 16127 } else { 16128 tween.render((!tween._dirty ? tween._totalDuration : tween.totalDuration()) - (time - tween._startTime) * tween._timeScale, suppressEvents, force); 16129 } 16130 } 16131 tween = next; 16132 } 16133 }; 16134 p.rawTime = function () { 16135 if (!_tickerActive) { 16136 _ticker.wake(); 16137 } 16138 return this._totalTime; 16139 }; 16140 16141 /* 16142 * ---------------------------------------------------------------- 16143 * TweenLite 16144 * ---------------------------------------------------------------- 16145 */ 16146 var TweenLite = _class("TweenLite", function (target, duration, vars) { 16147 Animation.call(this, duration, vars); 16148 this.render = TweenLite.prototype.render; //speed optimization (avoid prototype lookup on this "hot" method) 16149 16150 if (target == null) { 16151 throw "Cannot tween a null target."; 16152 } 16153 this.target = target = typeof target !== "string" ? target : TweenLite.selector(target) || target; 16154 var isSelector = target.jquery || target.length && target !== window && target[0] && (target[0] === window || target[0].nodeType && target[0].style && !target.nodeType),
16155 overwrite = this.vars.overwrite, 16156 i, 16157 targ, 16158 targets; 16159 this._overwrite = overwrite = overwrite == null ? _overwriteLookup[TweenLite.defaultOverwrite] : typeof overwrite === "number" ? overwrite >> 0 : _overwriteLookup[overwrite]; 16160 if ((isSelector || target instanceof Array || target.push && _isArray(target)) && typeof target[0] !== "number") { 16161 this._targets = targets = _slice(target); //don't use Array.prototype.slice.call(target, 0) because that doesn't work in IE8 with a NodeList that's returned by querySelectorAll() 16162 this._propLookup = []; 16163 this._siblings = []; 16164 for (i = 0; i < targets.length; i++) { 16165 targ = targets[i]; 16166 if (!targ) { 16167 targets.splice(i--, 1); 16168 continue; 16169 } else if (typeof targ === "string") { 16170 targ = targets[i--] = TweenLite.selector(targ); //in case it's an array of strings 16171 if (typeof targ === "string") { 16172 targets.splice(i + 1, 1); //to avoid an endless loop (can't imagine why the selector would return a string, but just in case) 16173 } 16174 continue; 16175 } else if (targ.length && targ !== window && targ[0] && (targ[0] === window || targ[0].nodeType && targ[0].style && !targ.nodeType)) { 16176 //in case the user is passing in an array of selector objects (like jQuery objects), we need to check one more level and pull things out if necessary. Also note that <select> elements pass all the criteria regarding length and the first child having style, so we must also check to ensure the target isn't an HTML node itself. 16177 targets.splice(i--, 1); 16178 this._targets = targets = targets.concat(_slice(targ)); 16179 continue; 16180 } 16181 this._siblings[i] = _register(targ, this, false); 16182 if (overwrite === 1) if (this._siblings[i].length > 1) { 16183 _applyOverwrite(targ, this, null, 1, this._siblings[i]); 16184 } 16185 } 16186 } else { 16187 this._propLookup = {}; 16188 this._siblings = _register(target, this, false); 16189 if (overwrite === 1) if (this._siblings.length > 1) { 16190 _applyOverwrite(target, this, null, 1, this._siblings); 16191 } 16192 } 16193 if (this.vars.immediateRender || duration === 0 && this._delay === 0 && this.vars.immediateRender !== false) { 16194 this._time = -_tinyNum; //forces a render without having to set the render() "force" parameter to true because we want to allow lazying by default (using the "force" parameter always forces an immediate full render) 16195 this.render(Math.min(0, -this._delay)); //in case delay is negative 16196 } 16197 }, true), 16198 _isSelector = function _isSelector(v) { 16199 return v && v.length && v !== window && v[0] && (v[0] === window || v[0].nodeType && v[0].style && !v.nodeType); //we cannot check "nodeType" if the target is window from within an iframe, otherwise it will trigger a security error in some browsers like Firefox. 16200 }, 16201 _autoCSS = function _autoCSS(vars, target) { 16202 var css = {}, 16203 p; 16204 for (p in vars) { 16205 if (!_reservedProps[p] && (!(p in target) || p === "transform" || p === "x" || p === "y" || p === "width" || p === "height" || p === "className" || p === "border") && (!_plugins[p] || _plugins[p] && _plugins[p]._autoCSS)) { 16206 //note: <img> elements contain read-only "x" and "y" properties. We should also prioritize editing css width/height rather than the element's properties. 16207 css[p] = vars[p]; 16208 delete vars[p]; 16209 } 16210 } 16211 vars.css = css; 16212 }; 16213 p = TweenLite.prototype = new Animation(); 16214 p.constructor = TweenLite; 16215 p.kill()._gc = false; 16216 16217 //----TweenLite defaults, overwrite management, and root updates ---------------------------------------------------- 16218 16219 p.ratio = 0; 16220 p._firstPT = p._targets = p._overwrittenProps = p._startAt = null; 16221 p._notifyPluginsOfEnabled = p._lazy = false; 16222 TweenLite.version = "1.20.4"; 16223 TweenLite.defaultEase = p._ease = new Ease(null, null, 1, 1); 16224 TweenLite.defaultOverwrite = "auto"; 16225 TweenLite.ticker = _ticker; 16226 TweenLite.autoSleep = 120;
16227 TweenLite.lagSmoothing = function (threshold, adjustedLag) { 16228 _ticker.lagSmoothing(threshold, adjustedLag); 16229 }; 16230 TweenLite.selector = window.$ || window.jQuery || function (e) { 16231 var selector = window.$ || window.jQuery; 16232 if (selector) { 16233 TweenLite.selector = selector; 16234 return selector(e); 16235 } 16236 return typeof _doc === "undefined" ? e : _doc.querySelectorAll ? _doc.querySelectorAll(e) : _doc.getElementById(e.charAt(0) === "#" ? e.substr(1) : e); 16237 }; 16238 var _lazyTweens = [], 16239 _lazyLookup = {}, 16240 _numbersExp = /(?:(-|-=|\+=)?\d*\.?\d*(?:e[\-+]?\d+)?)[0-9]/ig, 16241 _relExp = /[\+-]=-?[\.\d]/, 16242 //_nonNumbersExp = /(?:([\-+](?!(\d|=)))|[^\d\-+=e]|(e(?![\-+][\d])))+/ig, 16243 _setRatio = function _setRatio(v) { 16244 var pt = this._firstPT, 16245 min = 0.000001, 16246 val; 16247 while (pt) { 16248 val = !pt.blob ? pt.c * v + pt.s : v === 1 && this.end != null ? this.end : v ? this.join("") : this.start; 16249 if (pt.m) { 16250 val = pt.m(val, this._target || pt.t); 16251 } else if (val < min) if (val > -min && !pt.blob) { 16252 //prevents issues with converting very small numbers to strings in the browser 16253 val = 0; 16254 } 16255 if (!pt.f) { 16256 pt.t[pt.p] = val; 16257 } else if (pt.fp) { 16258 pt.t[pt.p](pt.fp, val); 16259 } else { 16260 pt.t[pt.p](val); 16261 } 16262 pt = pt._next; 16263 } 16264 }, 16265 //compares two strings (start/end), finds the numbers that are different and spits back an array representing the whole value but with the changing values isolated as elements. For example, "rgb(0,0,0)" and "rgb(100,50,0)" would become ["rgb(", 0, ",", 50, ",0)"]. Notice it merges the parts that are identical (performance optimization). The array also has a linked list of PropTweens attached starting with _firstPT that contain the tweening data (t, p, s, c, f, etc.). It also stores the starting value as a "start" property so that we can revert to it if/when necessary, like when a tween rewinds fully. If the quantity of numbers differs between the start and end, it will always prioritize the end value(s). The pt parameter is optional - it's for a PropTween that will be appended to the end of the linked list and is typically for actually setting the value after all of the elements have been updated (with array.join("")). 16266 _blobDif = function _blobDif(start, end, filter, pt) { 16267 var a = [], 16268 charIndex = 0, 16269 s = "", 16270 color = 0, 16271 startNums, 16272 endNums, 16273 num, 16274 i, 16275 l, 16276 nonNumbers, 16277 currentNum; 16278 a.start = start; 16279 a.end = end; 16280 start = a[0] = start + ""; //ensure values are strings 16281 end = a[1] = end + ""; 16282 if (filter) { 16283 filter(a); //pass an array with the starting and ending values and let the filter do whatever it needs to the values. 16284 start = a[0]; 16285 end = a[1]; 16286 } 16287 a.length = 0; 16288 startNums = start.match(_numbersExp) || []; 16289 endNums = end.match(_numbersExp) || []; 16290 if (pt) { 16291 pt._next = null; 16292 pt.blob = 1; 16293 a._firstPT = a._applyPT = pt; //apply last in the linked list (which means inserting it first) 16294 } 16295 l = endNums.length; 16296 for (i = 0; i < l; i++) { 16297 currentNum = endNums[i]; 16298 nonNumbers = end.substr(charIndex, end.indexOf(currentNum, charIndex) - charIndex); 16299 s += nonNumbers || !i ? nonNumbers : ","; //note: SVG spec allows omission of comma/space when a negative sign is wedged between two numbers, like 2.5-5.3 instead of 2.5,-5.3 but when tweening, the negative value may switch to positive, so we insert the comma just in case. 16300 charIndex += nonNumbers.length; 16301 if (color) { 16302 //sense rgba() values and round them. 16303 color = (color + 1) % 5; 16304 } else if (nonNumbers.substr(-5) === "rgba(") { 16305 color = 1; 16306 } 16307 if (currentNum === startNums[i] || startNums.length <= i) { 16308 s += currentNum; 16309 } else { 16310 if (s) { 16311 a.push(s); 16312 s = ""; 16313 } 16314 num = parseFloat(startNums[i]); 16315 a.push(num); 16316 a._firstPT = { 16317 _next: a._firstPT, 16318 t: a, 16319 p: a.length - 1, 16320 s: num, 16321 c: (currentNum.charAt(1) === "=" ? parseInt(currentNum.charAt(0) + "1", 10) * parseFloat(currentNum.substr(2)) : parseFloat(currentNum) - num) || 0, 16322 f: 0, 16323 m: color && color < 4 ? Math.round : 0 16324 }; 16325 //note: we don't set _prev because we'll never need to remove individual PropTweens from this list. 16326 } 16327 charIndex += currentNum.length; 16328 } 16329 s += end.substr(charIndex); 16330 if (s) { 16331 a.push(s); 16332 } 16333 a.setRatio = _setRatio; 16334 if (_relExp.test(end)) { 16335 //if the end string contains relative values, delete it so that on the final render (in _setRatio()), we don't actually set it to the string with += or -= characters (forces it to use the calculated value). 16336 a.end = null; 16337 } 16338 return a; 16339 }, 16340 //note: "funcParam" is only necessary for function-based getters/setters that require an extra parameter like getAttribute("width") and setAttribute("width", value). In this example, funcParam would be "width". Used by AttrPlugin for example. 16341 _addPropTween = function _addPropTween(target, prop, start, end, overwriteProp, mod, funcParam, stringFilter, index) { 16342 if (typeof end === "function") { 16343 end = end(index || 0, target); 16344 } 16345 var type = _typeof(target[prop]), 16346 getterName = type !== "function" ? "" : prop.indexOf("set") || typeof target["get" + prop.substr(3)] !== "function" ? prop : "get" + prop.substr(3), 16347 s = start !== "get" ? start : !getterName ? target[prop] : funcParam ? target[getterName](funcParam) : target[getterName](), 16348 isRelative = typeof end === "string" && end.charAt(1) === "=", 16349 pt = { 16350 t: target, 16351 p: prop, 16352 s: s, 16353 f: type === "function", 16354 pg: 0, 16355 n: overwriteProp || prop, 16356 m: !mod ? 0 : typeof mod === "function" ? mod : Math.round, 16357 pr: 0, 16358 c: isRelative ? parseInt(end.charAt(0) + "1", 10) * parseFloat(end.substr(2)) : parseFloat(end) - s || 0 16359 }, 16360 blob; 16361 if (typeof s !== "number" || typeof end !== "number" && !isRelative) { 16362 if (funcParam || isNaN(s) || !isRelative && isNaN(end) || typeof s === "boolean" || typeof end === "boolean") { 16363 //a blob (string that has multiple numbers in it) 16364 pt.fp = funcParam; 16365 blob = _blobDif(s, isRelative ? parseFloat(pt.s) + pt.c + (pt.s + "").replace(/[0-9\-\.]/g, "") : end, stringFilter || TweenLite.defaultStringFilter, pt); 16366 pt = { 16367 t: blob, 16368 p: "setRatio", 16369 s: 0, 16370 c: 1, 16371 f: 2, 16372 pg: 0, 16373 n: overwriteProp || prop, 16374 pr: 0, 16375 m: 0 16376 }; //"2" indicates it's a Blob property tween. Needed for RoundPropsPlugin for example. 16377 } else { 16378 pt.s = parseFloat(s); 16379 if (!isRelative) { 16380 pt.c = parseFloat(end) - pt.s || 0; 16381 } 16382 } 16383 } 16384 if (pt.c) { 16385 //only add it to the linked list if there's a change. 16386 if (pt._next = this._firstPT) { 16387 pt._next._prev = pt; 16388 } 16389 this._firstPT = pt; 16390 return pt; 16391 } 16392 }, 16393 _internals = TweenLite._internals = { 16394 isArray: _isArray, 16395 isSelector: _isSelector, 16396 lazyTweens: _lazyTweens, 16397 blobDif: _blobDif 16398 }, 16399 //gives us a way to expose certain private values to other GreenSock classes without contaminating tha main TweenLite object. 16400 _plugins = TweenLite._plugins = {}, 16401 _tweenLookup = _internals.tweenLookup = {}, 16402 _tweenLookupNum = 0, 16403 _reservedProps = _internals.reservedProps = { 16404 ease: 1, 16405 delay: 1, 16406 overwrite: 1, 16407 onComplete: 1, 16408 onCompleteParams: 1, 16409 onCompleteScope: 1, 16410 useFrames: 1, 16411 runBackwards: 1, 16412 startAt: 1, 16413 onUpdate: 1, 16414 onUpdateParams: 1, 16415 onUpdateScope: 1, 16416 onStart: 1, 16417 onStartParams: 1, 16418 onStartScope: 1, 16419 onReverseComplete: 1, 16420 onReverseCompleteParams: 1, 16421 onReverseCompleteScope: 1, 16422 onRepeat: 1, 16423 onRepeatParams: 1, 16424 onRepeatScope: 1, 16425 easeParams: 1, 16426 yoyo: 1, 16427 immediateRender: 1, 16428 repeat: 1, 16429 repeatDelay: 1, 16430 data: 1, 16431 paused: 1, 16432 reversed: 1, 16433 autoCSS: 1, 16434 lazy: 1, 16435 onOverwrite: 1, 16436 callbackScope: 1,
16437 stringFilter: 1, 16438 id: 1, 16439 yoyoEase: 1 16440 }, 16441 _overwriteLookup = { 16442 none: 0, 16443 all: 1, 16444 auto: 2, 16445 concurrent: 3, 16446 allOnStart: 4, 16447 preexisting: 5, 16448 "true": 1, 16449 "false": 0 16450 }, 16451 _rootFramesTimeline = Animation._rootFramesTimeline = new SimpleTimeline(), 16452 _rootTimeline = Animation._rootTimeline = new SimpleTimeline(), 16453 _nextGCFrame = 30, 16454 _lazyRender = _internals.lazyRender = function () { 16455 var i = _lazyTweens.length, 16456 tween; 16457 _lazyLookup = {}; 16458 while (--i > -1) { 16459 tween = _lazyTweens[i]; 16460 if (tween && tween._lazy !== false) { 16461 tween.render(tween._lazy[0], tween._lazy[1], true); 16462 tween._lazy = false; 16463 } 16464 } 16465 _lazyTweens.length = 0; 16466 }; 16467 _rootTimeline._startTime = _ticker.time; 16468 _rootFramesTimeline._startTime = _ticker.frame; 16469 _rootTimeline._active = _rootFramesTimeline._active = true; 16470 setTimeout(_lazyRender, 1); //on some mobile devices, there isn't a "tick" before code runs which means any lazy renders wouldn't run before the next official "tick". 16471 16472 Animation._updateRoot = TweenLite.render = function () { 16473 var i, a, p; 16474 if (_lazyTweens.length) { 16475 //if code is run outside of the requestAnimationFrame loop, there may be tweens queued AFTER the engine refreshed, so we need to ensure any pending renders occur before we refresh again. 16476 _lazyRender(); 16477 } 16478 _rootTimeline.render((_ticker.time - _rootTimeline._startTime) * _rootTimeline._timeScale, false, false); 16479 _rootFramesTimeline.render((_ticker.frame - _rootFramesTimeline._startTime) * _rootFramesTimeline._timeScale, false, false); 16480 if (_lazyTweens.length) { 16481 _lazyRender(); 16482 } 16483 if (_ticker.frame >= _nextGCFrame) { 16484 //dump garbage every 120 frames or whatever the user sets TweenLite.autoSleep to 16485 _nextGCFrame = _ticker.frame + (parseInt(TweenLite.autoSleep, 10) || 120); 16486 for (p in _tweenLookup) { 16487 a = _tweenLookup[p].tweens; 16488 i = a.length; 16489 while (--i > -1) { 16490 if (a[i]._gc) { 16491 a.splice(i, 1); 16492 } 16493 } 16494 if (a.length === 0) { 16495 delete _tweenLookup[p]; 16496 } 16497 } 16498 //if there are no more tweens in the root timelines, or if they're all paused, make the _timer sleep to reduce load on the CPU slightly 16499 p = _rootTimeline._first; 16500 if (!p || p._paused) if (TweenLite.autoSleep && !_rootFramesTimeline._first && _ticker._listeners.tick.length === 1) { 16501 while (p && p._paused) { 16502 p = p._next; 16503 } 16504 if (!p) { 16505 _ticker.sleep(); 16506 } 16507 } 16508 } 16509 }; 16510 _ticker.addEventListener("tick", Animation._updateRoot); 16511 var _register = function _register(target, tween, scrub) { 16512 var id = target._gsTweenID, 16513 a, 16514 i; 16515 if (!_tweenLookup[id || (target._gsTweenID = id = "t" + _tweenLookupNum++)]) { 16516 _tweenLookup[id] = { 16517 target: target, 16518 tweens: [] 16519 }; 16520 } 16521 if (tween) { 16522 a = _tweenLookup[id].tweens; 16523 a[i = a.length] = tween; 16524 if (scrub) { 16525 while (--i > -1) { 16526 if (a[i] === tween) { 16527 a.splice(i, 1); 16528 } 16529 } 16530 } 16531 } 16532 return _tweenLookup[id].tweens; 16533 }, 16534 _onOverwrite = function _onOverwrite(overwrittenTween, overwritingTween, target, killedProps) { 16535 var func = overwrittenTween.vars.onOverwrite, 16536 r1, 16537 r2; 16538 if (func) { 16539 r1 = func(overwrittenTween, overwritingTween, target, killedProps); 16540 } 16541 func = TweenLite.onOverwrite; 16542 if (func) { 16543 r2 = func(overwrittenTween, overwritingTween, target, killedProps); 16544 } 16545 return r1 !== false && r2 !== false; 16546 }, 16547 _applyOverwrite = function _applyOverwrite(target, tween, props, mode, siblings) { 16548 var i, changed, curTween, l; 16549 if (mode === 1 || mode >= 4) { 16550 l = siblings.length; 16551 for (i = 0; i < l; i++) { 16552 if ((curTween = siblings[i]) !== tween) { 16553 if (!curTween._gc) { 16554 if (curTween._kill(null, target, tween)) { 16555 changed = true; 16556 } 16557 } 16558 } else if (mode === 5) { 16559 break; 16560 } 16561 } 16562 return changed; 16563 } 16564 //NOTE: Add 0.0000000001 to overcome floating point errors that can cause the startTime to be VERY slightly off (when a tween's time() is set for example) 16565 var startTime = tween._startTime + _tinyNum, 16566 overlaps = [], 16567 oCount = 0, 16568 zeroDur = tween._duration === 0, 16569 globalStart; 16570 i = siblings.length; 16571 while (--i > -1) { 16572 if ((curTween = siblings[i]) === tween || curTween._gc || curTween._paused) { 16573 //ignore 16574 } else if (curTween._timeline !== tween._timeline) { 16575 globalStart = globalStart || _checkOverlap(tween, 0, zeroDur); 16576 if (_checkOverlap(curTween, globalStart, zeroDur) === 0) { 16577 overlaps[oCount++] = curTween; 16578 } 16579 } else if (curTween._startTime <= startTime) if (curTween._startTime + curTween.totalDuration() / curTween._timeScale > startTime) if (!((zeroDur || !curTween._initted) && startTime - curTween._startTime <= 0.0000000002)) { 16580 overlaps[oCount++] = curTween; 16581 } 16582 } 16583 i = oCount; 16584 while (--i > -1) { 16585 curTween = overlaps[i]; 16586 if (mode === 2) if (curTween._kill(props, target, tween)) { 16587 changed = true; 16588 } 16589 if (mode !== 2 || !curTween._firstPT && curTween._initted) { 16590 if (mode !== 2 && !_onOverwrite(curTween, tween)) { 16591 continue; 16592 } 16593 if (curTween._enabled(false, false)) { 16594 //if all property tweens have been overwritten, kill the tween. 16595 changed = true; 16596 } 16597 } 16598 } 16599 return changed; 16600 }, 16601 _checkOverlap = function _checkOverlap(tween, reference, zeroDur) { 16602 var tl = tween._timeline, 16603 ts = tl._timeScale, 16604 t = tween._startTime; 16605 while (tl._timeline) { 16606 t += tl._startTime; 16607 ts *= tl._timeScale; 16608 if (tl._paused) { 16609 return -100; 16610 } 16611 tl = tl._timeline; 16612 } 16613 t /= ts; 16614 return t > reference ? t - reference : zeroDur && t === reference || !tween._initted && t - reference < 2 * _tinyNum ? _tinyNum : (t += tween.totalDuration() / tween._timeScale / ts) > reference + _tinyNum ? 0 : t - reference - _tinyNum; 16615 }; 16616 16617 //---- TweenLite instance methods ----------------------------------------------------------------------------- 16618 16619 p._init = function () { 16620 var v = this.vars, 16621 op = this._overwrittenProps, 16622 dur = this._duration, 16623 immediate = !!v.immediateRender, 16624 ease = v.ease, 16625 i, 16626 initPlugins, 16627 pt, 16628 p, 16629 startVars, 16630 l; 16631 if (v.startAt) { 16632 if (this._startAt) { 16633 this._startAt.render(-1, true); //if we've run a startAt previously (when the tween instantiated), we should revert it so that the values re-instantiate correctly particularly for relative tweens. Without this, a TweenLite.fromTo(obj, 1, {x:"+=100"}, {x:"-=100"}), for example, would actually jump to +=200 because the startAt would run twice, doubling the relative change. 16634 this._startAt.kill(); 16635 } 16636 startVars = {}; 16637 for (p in v.startAt) { 16638 //copy the properties/values into a new object to avoid collisions, like var to = {x:0}, from = {x:500}; timeline.fromTo(e, 1, from, to).fromTo(e, 1, to, from); 16639 startVars[p] = v.startAt[p]; 16640 } 16641 startVars.data = "isStart"; 16642 startVars.overwrite = false;
16643 startVars.immediateRender = true; 16644 startVars.lazy = immediate && v.lazy !== false; 16645 startVars.startAt = startVars.delay = null; //no nesting of startAt objects allowed (otherwise it could cause an infinite loop). 16646 startVars.onUpdate = v.onUpdate; 16647 startVars.onUpdateParams = v.onUpdateParams; 16648 startVars.onUpdateScope = v.onUpdateScope || v.callbackScope || this; 16649 this._startAt = TweenLite.to(this.target, 0, startVars); 16650 if (immediate) { 16651 if (this._time > 0) { 16652 this._startAt = null; //tweens that render immediately (like most from() and fromTo() tweens) shouldn't revert when their parent timeline's playhead goes backward past the startTime because the initial render could have happened anytime and it shouldn't be directly correlated to this tween's startTime. Imagine setting up a complex animation where the beginning states of various objects are rendered immediately but the tween doesn't happen for quite some time - if we revert to the starting values as soon as the playhead goes backward past the tween's startTime, it will throw things off visually. Reversion should only happen in TimelineLite/Max instances where immediateRender was false (which is the default in the convenience methods like from()). 16653 } else if (dur !== 0) { 16654 return; //we skip initialization here so that overwriting doesn't occur until the tween actually begins. Otherwise, if you create several immediateRender:true tweens of the same target/properties to drop into a TimelineLite or TimelineMax, the last one created would overwrite the first ones because they didn't get placed into the timeline yet before the first render occurs and kicks in overwriting. 16655 } 16656 } 16657 } else if (v.runBackwards && dur !== 0) { 16658 //from() tweens must be handled uniquely: their beginning values must be rendered but we don't want overwriting to occur yet (when time is still 0). Wait until the tween actually begins before doing all the routines like overwriting. At that time, we should render at the END of the tween to ensure that things initialize correctly (remember, from() tweens go backwards) 16659 if (this._startAt) { 16660 this._startAt.render(-1, true); 16661 this._startAt.kill(); 16662 this._startAt = null; 16663 } else { 16664 if (this._time !== 0) { 16665 //in rare cases (like if a from() tween runs and then is invalidate()-ed), immediateRender could be true but the initial forced-render gets skipped, so there's no need to force the render in this context when the _time is greater than 0 16666 immediate = false; 16667 } 16668 pt = {}; 16669 for (p in v) { 16670 //copy props into a new object and skip any reserved props, otherwise onComplete or onUpdate or onStart could fire. We should, however, permit autoCSS to go through. 16671 if (!_reservedProps[p] || p === "autoCSS") { 16672 pt[p] = v[p]; 16673 } 16674 } 16675 pt.overwrite = 0; 16676 pt.data = "isFromStart"; //we tag the tween with as "isFromStart" so that if [inside a plugin] we need to only do something at the very END of a tween, we have a way of identifying this tween as merely the one that's setting the beginning values for a "from()" tween. For example, clearProps in CSSPlugin should only get applied at the very END of a tween and without this tag, from(...{height:100, clearProps:"height", delay:1}) would wipe the height at the beginning of the tween and after 1 second, it'd kick back in. 16677 pt.lazy = immediate && v.lazy !== false; 16678 pt.immediateRender = immediate; //zero-duration tweens render immediately by default, but if we're not specifically instructed to render this tween immediately, we should skip this and merely _init() to record the starting values (rendering them immediately would push them to completion which is wasteful in that case - we'd have to render(-1) immediately after) 16679 this._startAt = TweenLite.to(this.target, 0, pt); 16680 if (!immediate) { 16681 this._startAt._init(); //ensures that the initial values are recorded 16682 this._startAt._enabled(false); //no need to have the tween render on the next cycle. Disable it because we'll always manually control the renders of the _startAt tween. 16683 if (this.vars.immediateRender) { 16684 this._startAt = null; 16685 } 16686 } else if (this._time === 0) { 16687 return; 16688 } 16689 } 16690 } 16691 this._ease = ease = !ease ? TweenLite.defaultEase : ease instanceof Ease ? ease : typeof ease === "function" ? new Ease(ease, v.easeParams) : _easeMap[ease] || TweenLite.defaultEase; 16692 if (v.easeParams instanceof Array && ease.config) { 16693 this._ease = ease.config.apply(ease, v.easeParams); 16694 } 16695 this._easeType = this._ease._type; 16696 this._easePower = this._ease._power; 16697 this._firstPT = null; 16698 if (this._targets) { 16699 l = this._targets.length; 16700 for (i = 0; i < l; i++) { 16701 if (this._initProps(this._targets[i], this._propLookup[i] = {}, this._siblings[i], op ? op[i] : null, i)) { 16702 initPlugins = true; 16703 } 16704 } 16705 } else { 16706 initPlugins = this._initProps(this.target, this._propLookup, this._siblings, op, 0); 16707 } 16708 if (initPlugins) { 16709 TweenLite._onPluginEvent("_onInitAllProps", this); //reorders the array in order of priority. Uses a static TweenPlugin method in order to minimize file size in TweenLite 16710 } 16711 if (op) if (!this._firstPT) if (typeof this.target !== "function") { 16712 //if all tweening properties have been overwritten, kill the tween. If the target is a function, it's probably a delayedCall so let it live. 16713 this._enabled(false, false); 16714 } 16715 if (v.runBackwards) { 16716 pt = this._firstPT; 16717 while (pt) { 16718 pt.s += pt.c; 16719 pt.c = -pt.c; 16720 pt = pt._next; 16721 } 16722 } 16723 this._onUpdate = v.onUpdate; 16724 this._initted = true; 16725 }; 16726 p._initProps = function (target, propLookup, siblings, overwrittenProps, index) { 16727 var p, i, initPlugins, plugin, pt, v; 16728 if (target == null) { 16729 return false;
16730 } 16731 if (_lazyLookup[target._gsTweenID]) { 16732 _lazyRender(); //if other tweens of the same target have recently initted but haven't rendered yet, we've got to force the render so that the starting values are correct (imagine populating a timeline with a bunch of sequential tweens and then jumping to the end) 16733 } 16734 if (!this.vars.css) if (target.style) if (target !== window && target.nodeType) if (_plugins.css) if (this.vars.autoCSS !== false) { 16735 //it's so common to use TweenLite/Max to animate the css of DOM elements, we assume that if the target is a DOM element, that's what is intended (a convenience so that users don't have to wrap things in css:{}, although we still recommend it for a slight performance boost and better specificity). Note: we cannot check "nodeType" on the window inside an iframe. 16736 _autoCSS(this.vars, target); 16737 } 16738 for (p in this.vars) { 16739 v = this.vars[p]; 16740 if (_reservedProps[p]) { 16741 if (v) if (v instanceof Array || v.push && _isArray(v)) if (v.join("").indexOf("{self}") !== -1) { 16742 this.vars[p] = v = this._swapSelfInParams(v, this); 16743 } 16744 } else if (_plugins[p] && (plugin = new _plugins[p]())._onInitTween(target, this.vars[p], this, index)) { 16745 //t - target [object] 16746 //p - property [string] 16747 //s - start [number] 16748 //c - change [number] 16749 //f - isFunction [boolean] 16750 //n - name [string] 16751 //pg - isPlugin [boolean] 16752 //pr - priority [number] 16753 //m - mod [function | 0] 16754 this._firstPT = pt = { 16755 _next: this._firstPT, 16756 t: plugin, 16757 p: "setRatio", 16758 s: 0, 16759 c: 1, 16760 f: 1, 16761 n: p, 16762 pg: 1, 16763 pr: plugin._priority, 16764 m: 0 16765 }; 16766 i = plugin._overwriteProps.length; 16767 while (--i > -1) { 16768 propLookup[plugin._overwriteProps[i]] = this._firstPT; 16769 } 16770 if (plugin._priority || plugin._onInitAllProps) { 16771 initPlugins = true; 16772 } 16773 if (plugin._onDisable || plugin._onEnable) { 16774 this._notifyPluginsOfEnabled = true; 16775 } 16776 if (pt._next) { 16777 pt._next._prev = pt; 16778 } 16779 } else { 16780 propLookup[p] = _addPropTween.call(this, target, p, "get", v, p, 0, null, this.vars.stringFilter, index); 16781 } 16782 } 16783 if (overwrittenProps) if (this._kill(overwrittenProps, target)) { 16784 //another tween may have tried to overwrite properties of this tween before init() was called (like if two tweens start at the same time, the one created second will run first) 16785 return this._initProps(target, propLookup, siblings, overwrittenProps, index); 16786 } 16787 if (this._overwrite > 1) if (this._firstPT) if (siblings.length > 1) if (_applyOverwrite(target, this, propLookup, this._overwrite, siblings)) { 16788 this._kill(propLookup, target); 16789 return this._initProps(target, propLookup, siblings, overwrittenProps, index); 16790 } 16791 if (this._firstPT) if (this.vars.lazy !== false && this._duration || this.vars.lazy && !this._duration) { 16792 //zero duration tweens don't lazy render by default; everything else does. 16793 _lazyLookup[target._gsTweenID] = true; 16794 } 16795 return initPlugins; 16796 }; 16797 p.render = function (time, suppressEvents, force) { 16798 var prevTime = this._time, 16799 duration = this._duration, 16800 prevRawPrevTime = this._rawPrevTime, 16801 isComplete, 16802 callback, 16803 pt, 16804 rawPrevTime; 16805 if (time >= duration - 0.0000001 && time >= 0) { 16806 //to work around occasional floating point math artifacts. 16807 this._totalTime = this._time = duration; 16808 this.ratio = this._ease._calcEnd ? this._ease.getRatio(1) : 1; 16809 if (!this._reversed) { 16810 isComplete = true; 16811 callback = "onComplete"; 16812 force = force || this._timeline.autoRemoveChildren; //otherwise, if the animation is unpaused/activated after it's already finished, it doesn't get removed from the parent timeline. 16813 } 16814 if (duration === 0) if (this._initted || !this.vars.lazy || force) { 16815 //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered. 16816 if (this._startTime === this._timeline._duration) { 16817 //if a zero-duration tween is at the VERY end of a timeline and that timeline renders at its end, it will typically add a tiny bit of cushion to the render time to prevent roun
16817ding errors from getting in the way of tweens rendering their VERY end. If we then reverse() that timeline, the zero-duration tween will trigger its onReverseComplete even though technically the playhead didn't pass over it again. It's a very specific edge case we must accommodate. 16818 time = 0; 16819 } 16820 if (prevRawPrevTime < 0 || time <= 0 && time >= -0.0000001 || prevRawPrevTime === _tinyNum && this.data !== "isPause") if (prevRawPrevTime !== time) { 16821 //note: when this.data is "isPause", it's a callback added by addPause() on a timeline that we should not be triggered when LEAVING its exact start time. In other words, tl.addPause(1).play(1) shouldn't pause. 16822 force = true; 16823 if (prevRawPrevTime > _tinyNum) { 16824 callback = "onReverseComplete"; 16825 } 16826 } 16827 this._rawPrevTime = rawPrevTime = !suppressEvents || time || prevRawPrevTime === time ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient. 16828 } 16829 } else if (time < 0.0000001) { 16830 //to work around occasional floating point math artifacts, round super small values to 0. 16831 this._totalTime = this._time = 0; 16832 this.ratio = this._ease._calcEnd ? this._ease.getRatio(0) : 0; 16833 if (prevTime !== 0 || duration === 0 && prevRawPrevTime > 0) { 16834 callback = "onReverseComplete"; 16835 isComplete = this._reversed; 16836 } 16837 if (time < 0) { 16838 this._active = false; 16839 if (duration === 0) if (this._initted || !this.vars.lazy || force) { 16840 //zero-duration tweens are tricky because we must discern the momentum/direction of time in order to determine whether the starting values should be rendered or the ending values. If the "playhead" of its timeline goes past the zero-duration tween in the forward direction or lands directly on it, the end values should be rendered, but if the timeline's "playhead" moves past it in the backward direction (from a postitive time to a negative time), the starting values must be rendered. 16841 if (prevRawPrevTime >= 0 && !(prevRawPrevTime === _tinyNum && this.data === "isPause")) { 16842 force = true; 16843 } 16844 this._rawPrevTime = rawPrevTime = !suppressEvents || time || prevRawPrevTime === time ? time : _tinyNum; //when the playhead arrives at EXACTLY time 0 (right on top) of a zero-duration tween, we need to discern if events are suppressed so that when the playhead moves again (next time), it'll trigger the callback. If events are NOT suppressed, obviously the callback would be triggered in this render. Basically, the callback should fire either when the playhead ARRIVES or LEAVES this exact spot, not both. Imagine doing a timeline.seek(0) and there's a callback that sits at 0. Since events are suppressed on that seek() by default, nothing will fire, but when the playhead moves off of that position, the callback should fire. This behavior is what people intuitively expect. We set the _rawPrevTime to be a precise tiny number to indicate this scenario rather than using another property/variable which would increase memory usage. This technique is less readable, but more efficient. 16845 } 16846 } 16847 if (!this._initted || this._startAt && this._startAt.progress()) { 16848 //if we render the very beginning (time == 0) of a fromTo(), we must force the render (normal tweens wouldn't need to render at a time of 0 when the prevTime was also 0). This is also mandatory to make sure overwriting kicks in immediately. Also, we check progress() because if startAt has already rendered at its end, we should force a render at its beginning. Otherwise, if you put the playhead directly on top of where a fromTo({immediateRender:false}) starts, and then move it backwards, the from() won't revert its values. 16849 force = true; 16850 } 16851 } else { 16852 this._totalTime = this._time = time; 16853 if (this._easeType) { 16854 var r = time / duration, 16855 type = this._easeType, 16856 pow = this._easePower; 16857 if (type === 1 || type === 3 && r >= 0.5) { 16858 r = 1 - r; 16859 } 16860 if (type === 3) { 16861 r *= 2; 16862 } 16863 if (pow === 1) { 16864 r *= r; 16865 } else if (pow === 2) { 16866 r *= r * r; 16867 } else if (pow === 3) { 16868 r *= r * r * r; 16869 } else if (pow === 4) { 16870 r *= r * r * r * r; 16871 } 16872 if (type === 1) { 16873 this.ratio = 1 - r; 16874 } else if (type === 2) { 16875 this.ratio = r; 16876 } else if (time / duration < 0.5) { 16877 this.ratio = r / 2; 16878 } else { 16879 this.ratio = 1 - r / 2; 16880 } 16881 } else { 16882 this.ratio = this._ease.getRatio(time / duration); 16883 } 16884 } 16885 if (this._time === prevTime && !force) { 16886 return; 16887 } else if (!this._initted) { 16888 this._init(); 16889 if (!this._initted || this._gc) { 16890 //immediateRender tweens typically won't initialize until the playhead advances (_time is greater than 0) in order to ensure that over
16890writing occurs properly. Also, if all of the tweening properties have been overwritten (which would cause _gc to be true, as set in _init()), we shouldn't continue otherwise an onStart callback could be called for example. 16891 return; 16892 } else if (!force && this._firstPT && (this.vars.lazy !== false && this._duration || this.vars.lazy && !this._duration)) { 16893 this._time = this._totalTime = prevTime; 16894 this._rawPrevTime = prevRawPrevTime; 16895 _lazyTweens.push(this); 16896 this._lazy = [time, suppressEvents]; 16897 return; 16898 } 16899 //_ease is initially set to defaultEase, so now that init() has run, _ease is set properly and we need to recalculate the ratio. Overall this is faster than using conditional logic earlier in the method to avoid having to set ratio twice because we only init() once but renderTime() gets called VERY frequently. 16900 if (this._time && !isComplete) { 16901 this.ratio = this._ease.getRatio(this._time / duration); 16902 } else if (isComplete && this._ease._calcEnd) { 16903 this.ratio = this._ease.getRatio(this._time === 0 ? 0 : 1); 16904 } 16905 } 16906 if (this._lazy !== false) { 16907 //in case a lazy render is pending, we should flush it because the new render is occurring now (imagine a lazy tween instantiating and then immediately the user calls tween.seek(tween.duration()), skipping to the end - the end render would be forced, and then if we didn't flush the lazy render, it'd fire AFTER the seek(), rendering it at the wrong time. 16908 this._lazy = false; 16909 } 16910 if (!this._active) if (!this._paused && this._time !== prevTime && time >= 0) { 16911 this._active = true; //so that if the user renders a tween (as opposed to the timeline rendering it), the timeline is forced to re-render and align it with the proper time/frame on the next rendering cycle. Maybe the tween already finished but the user manually re-renders it as halfway done. 16912 } 16913 if (prevTime === 0) { 16914 if (this._startAt) { 16915 if (time >= 0) { 16916 this._startAt.render(time, true, force); 16917 } else if (!callback) { 16918 callback = "_dummyGS"; //if no callback is defined, use a dummy value just so that the condition at the end evaluates as true because _startAt should render AFTER the normal render loop when the time is negative. We could handle this in a more intuitive way, of course, but the render loop is the MOST important thing to optimize, so this technique allows us to avoid adding extra conditional logic in a high-frequency area. 16919 } 16920 } 16921 if (this.vars.onStart) if (this._time !== 0 || duration === 0) if (!suppressEvents) { 16922 this._callback("onStart"); 16923 } 16924 } 16925 pt = this._firstPT; 16926 while (pt) { 16927 if (pt.f) { 16928 pt.t[pt.p](pt.c * this.ratio + pt.s); 16929 } else { 16930 pt.t[pt.p] = pt.c * this.ratio + pt.s; 16931 } 16932 pt = pt._next; 16933 } 16934 if (this._onUpdate) { 16935 if (time < 0) if (this._startAt && time !== -0.0001) { 16936 //if the tween is positioned at the VERY beginning (_startTime 0) of its parent timeline, it's illegal for the playhead to go back further, so we should not render the recorded startAt values. 16937 this._startAt.render(time, true, force); //note: for performance reasons, we tuck this conditional logic inside less traveled areas (most tweens don't have an onUpdate). We'd just have it at the end before the onComplete, but the values should be updated before any onUpdate is called, so we ALSO put it here and then if it's not called, we do so later near the onComplete. 16938 } 16939 if (!suppressEvents) if (this._time !== prevTime || isComplete || force) { 16940 this._callback("onUpdate"); 16941 } 16942 } 16943 if (callback) if (!this._gc || force) { 16944 //check _gc because there's a chance that kill() could be called in an onUpdate 16945 if (time < 0 && this._startAt && !this._onUpdate && time !== -0.0001) { 16946 //-0.0001 is a special value that we use when looping back to the beginning of a repeated TimelineMax, in which case we shouldn't render the _startAt values. 16947 this._startAt.render(time, true, force); 16948 } 16949 if (isComplete) { 16950 if (this._timeline.autoRemoveChildren) { 16951 this._enabled(false, false); 16952 } 16953 this._active = false;
16954 } 16955 if (!suppressEvents && this.vars[callback]) { 16956 this._callback(callback); 16957 } 16958 if (duration === 0 && this._rawPrevTime === _tinyNum && rawPrevTime !== _tinyNum) { 16959 //the onComplete or onReverseComplete could trigger movement of the playhead and for zero-duration tweens (which must discern direction) that land directly back on their start time, we don't want to fire again on the next render. Think of several addPause()'s in a timeline that forces the playhead to a certain spot, but what if it's already paused and another tween is tweening the "time" of the timeline? Each time it moves [forward] past that spot, it would move back, and since suppressEvents is true, it'd reset _rawPrevTime to _tinyNum so that when it begins again, the callback would fire (so ultimately it could bounce back and forth during that tween). Again, this is a very uncommon scenario, but possible nonetheless. 16960 this._rawPrevTime = 0; 16961 } 16962 } 16963 }; 16964 p._kill = function (vars, target, overwritingTween) { 16965 if (vars === "all") { 16966 vars = null; 16967 } 16968 if (vars == null) if (target == null || target === this.target) { 16969 this._lazy = false; 16970 return this._enabled(false, false); 16971 } 16972 target = typeof target !== "string" ? target || this._targets || this.target : TweenLite.selector(target) || target; 16973 var simultaneousOverwrite = overwritingTween && this._time && overwritingTween._startTime === this._startTime && this._timeline === overwritingTween._timeline, 16974 i, 16975 overwrittenProps, 16976 p, 16977 pt, 16978 propLookup, 16979 changed, 16980 killProps, 16981 record, 16982 killed; 16983 if ((_isArray(target) || _isSelector(target)) && typeof target[0] !== "number") { 16984 i = target.length; 16985 while (--i > -1) { 16986 if (this._kill(vars, target[i], overwritingTween)) { 16987 changed = true; 16988 } 16989 } 16990 } else { 16991 if (this._targets) { 16992 i = this._targets.length; 16993 while (--i > -1) { 16994 if (target === this._targets[i]) { 16995 propLookup = this._propLookup[i] || {}; 16996 this._overwrittenProps = this._overwrittenProps || []; 16997 overwrittenProps = this._overwrittenProps[i] = vars ? this._overwrittenProps[i] || {} : "all"; 16998 break; 16999 } 17000 } 17001 } else if (target !== this.target) { 17002 return false; 17003 } else { 17004 propLookup = this._propLookup; 17005 overwrittenProps = this._overwrittenProps = vars ? this._overwrittenProps || {} : "all"; 17006 } 17007 if (propLookup) { 17008 killProps = vars || propLookup; 17009 record = vars !== overwrittenProps && overwrittenProps !== "all" && vars !== propLookup && (_typeof(vars) !== "object" || !vars._tempKill); //_tempKill is a super-secret way to delete a particular tweening property but NOT have it remembered as an official overwritten property (like in BezierPlugin) 17010 if (overwritingTween && (TweenLite.onOverwrite || this.vars.onOverwrite)) { 17011 for (p in killProps) { 17012 if (propLookup[p]) { 17013 if (!killed) { 17014 killed = []; 17015 } 17016 killed.push(p); 17017 } 17018 } 17019 if ((killed || !vars) && !_onOverwrite(this, overwritingTween, target, killed)) { 17020 //if the onOverwrite returned false, that means the user wants to override the overwriting (cancel it). 17021 return false; 17022 } 17023 } 17024 for (p in killProps) { 17025 if (pt = propLookup[p]) { 17026 if (simultaneousOverwrite) { 17027 //if another tween overwrites this one and they both start at exactly the same time, yet this tween has already rendered once (for example, at 0.001) because it's first in the queue, we should revert the values to where they were at 0 so that the starting values aren't contaminated on the overwriting tween. 17028 if (pt.f) { 17029 pt.t[pt.p](pt.s); 17030 } else { 17031 pt.t[pt.p] = pt.s; 17032 } 17033 changed = true; 17034 } 17035 if (pt.pg && pt.t._kill(killProps)) { 17036 changed = true; //some plugins need to be notified so they can perform cleanup tasks first 17037 } 17038 if (!pt.pg || pt.t._overwriteProps.length === 0) { 17039 if (pt._prev) { 17040 pt._prev._next = pt._next; 17041 } else if (pt === this._firstPT) { 17042 this._firstPT = pt._next; 17043 } 17044 if (pt._next) { 17045 pt._next._prev = pt._prev; 17046 } 17047 pt._next = pt._prev = null; 17048 } 17049 delete propLookup[p]; 17050 } 17051 if (record) { 17052 overwrittenProps[p] = 1; 17053 } 17054 } 17055 if (!this._firstPT && this._initted) { 17056 //if all tweening properties are killed, kill the tween. Without this line, if there's a tween with multiple targets and then you killTweensOf() each target individually, the tween would technically still remain active and fire its onComplete even though there aren't any more properties tweening. 17057 this._enabled(false, false); 17058 } 17059 } 17060 } 17061 return changed; 17062 }; 17063 p.invalidate = function () { 17064 if (this._notifyPluginsOfEnabled) { 17065 TweenLite._onPluginEvent("_onDisable", this); 17066 } 17067 this._firstPT = this._overwrittenProps = this._startAt = this._onUpdate = null; 17068 this._notifyPluginsOfEnabled = this._active = this._lazy = false;
17069 this._propLookup = this._targets ? {} : []; 17070 Animation.prototype.invalidate.call(this); 17071 if (this.vars.immediateRender) { 17072 this._time = -_tinyNum; //forces a render without having to set the render() "force" parameter to true because we want to allow lazying by default (using the "force" parameter always forces an immediate full render) 17073 this.render(Math.min(0, -this._delay)); //in case delay is negative. 17074 } 17075 return this; 17076 }; 17077 p._enabled = function (enabled, ignoreTimeline) { 17078 if (!_tickerActive) { 17079 _ticker.wake(); 17080 } 17081 if (enabled && this._gc) { 17082 var targets = this._targets, 17083 i; 17084 if (targets) { 17085 i = targets.length; 17086 while (--i > -1) { 17087 this._siblings[i] = _register(targets[i], this, true); 17088 } 17089 } else { 17090 this._siblings = _register(this.target, this, true); 17091 } 17092 } 17093 Animation.prototype._enabled.call(this, enabled, ignoreTimeline); 17094 if (this._notifyPluginsOfEnabled) if (this._firstPT) { 17095 return TweenLite._onPluginEvent(enabled ? "_onEnable" : "_onDisable", this); 17096 } 17097 return false; 17098 }; 17099 17100 //----TweenLite static methods ----------------------------------------------------- 17101 17102 TweenLite.to = function (target, duration, vars) { 17103 return new TweenLite(target, duration, vars); 17104 }; 17105 TweenLite.from = function (target, duration, vars) { 17106 vars.runBackwards = true; 17107 vars.immediateRender = vars.immediateRender != false; 17108 return new TweenLite(target, duration, vars); 17109 }; 17110 TweenLite.fromTo = function (target, duration, fromVars, toVars) { 17111 toVars.startAt = fromVars; 17112 toVars.immediateRender = toVars.immediateRender != false && fromVars.immediateRender != false; 17113 return new TweenLite(target, duration, toVars); 17114 }; 17115 TweenLite.delayedCall = function (delay, callback, params, scope, useFrames) { 17116 return new TweenLite(callback, 0, { 17117 delay: delay, 17118 onComplete: callback, 17119 onCompleteParams: params, 17120 callbackScope: scope, 17121 onReverseComplete: callback, 17122 onReverseCompleteParams: params, 17123 immediateRender: false, 17124 lazy: false, 17125 useFrames: useFrames, 17126 overwrite: 0 17127 }); 17128 }; 17129 TweenLite.set = function (target, vars) { 17130 return new TweenLite(target, 0, vars); 17131 }; 17132 TweenLite.getTweensOf = function (target, onlyActive) { 17133 if (target == null) { 17134 return []; 17135 } 17136 target = typeof target !== "string" ? target : TweenLite.selector(target) || target; 17137 var i, a, j, t; 17138 if ((_isArray(target) || _isSelector(target)) && typeof target[0] !== "number") { 17139 i = target.length; 17140 a = []; 17141 while (--i > -1) { 17142 a = a.concat(TweenLite.getTweensOf(target[i], onlyActive)); 17143 } 17144 i = a.length; 17145 //now get rid of any duplicates (tweens of arrays of objects could cause duplicates) 17146 while (--i > -1) { 17147 t = a[i]; 17148 j = i; 17149 while (--j > -1) { 17150 if (t === a[j]) { 17151 a.splice(i, 1); 17152 } 17153 } 17154 } 17155 } else if (target._gsTweenID) { 17156 a = _register(target).concat(); 17157 i = a.length; 17158 while (--i > -1) { 17159 if (a[i]._gc || onlyActive && !a[i].isActive()) { 17160 a.splice(i, 1); 17161 } 17162 } 17163 } 17164 return a || []; 17165 }; 17166 TweenLite.killTweensOf = TweenLite.killDelayedCallsTo = function (target, onlyActive, vars) { 17167 if (_typeof(onlyActive) === "object") { 17168 vars = onlyActive; //for backwards compatibility (before "onlyActive" parameter was inserted) 17169 onlyActive = false; 17170 } 17171 var a = TweenLite.getTweensOf(target, onlyActive), 17172 i = a.length; 17173 while (--i > -1) { 17174 a[i]._kill(vars, target); 17175 } 17176 }; 17177 17178 /* 17179 * ---------------------------------------------------------------- 17180 * TweenPlugin (could easily be split out as a separate file/class, but included for ease of use (so that people don't need to include another script call before loading plugins which is easy to forget) 17181 * ---------------------------------------------------------------- 17182 */ 17183 var TweenPlugin = _class("plugins.TweenPlugin", function (props, priority) { 17184 this._overwriteProps = (props || "").split(","); 17185 this._propName = this._overwriteProps[0]; 17186 this._priority = priority || 0; 17187 this._super = TweenPlugin.prototype; 17188 }, true); 17189 p = TweenPlugin.prototype; 17190 TweenPlugin.version = "1.19.0"; 17191 TweenPlugin.API = 2; 17192 p._firstPT = null; 17193 p._addTween = _addPropTween; 17194 p.setRatio = _setRatio; 17195 p._kill = function (lookup) { 17196 var a = this._overwriteProps, 17197 pt = this._firstPT, 17198 i; 17199 if (lookup[this._propName] != null) { 17200 this._overwriteProps = []; 17201 } else { 17202 i = a.length; 17203 while (--i > -1) { 17204 if (lookup[a[i]] != null) { 17205 a.splice(i, 1); 17206 } 17207 } 17208 } 17209 while (pt) { 17210 if (lookup[pt.n] != null) { 17211 if (pt._next) { 17212 pt._next._prev = pt._prev; 17213 } 17214 if (pt._prev) { 17215 pt._prev._next = pt._next; 17216 pt._prev = null; 17217 } else if (this._firstPT === pt) { 17218 this._firstPT = pt._next; 17219 } 17220 } 17221 pt = pt._next; 17222 } 17223 return false;
17224 }; 17225 p._mod = p._roundProps = function (lookup) { 17226 var pt = this._firstPT, 17227 val; 17228 while (pt) { 17229 val = lookup[this._propName] || pt.n != null && lookup[pt.n.split(this._propName + "_").join("")]; 17230 if (val && typeof val === "function") { 17231 //some properties that are very plugin-specific add a prefix named after the _propName plus an underscore, so we need to ignore that extra stuff here. 17232 if (pt.f === 2) { 17233 pt.t._applyPT.m = val; 17234 } else { 17235 pt.m = val; 17236 } 17237 } 17238 pt = pt._next; 17239 } 17240 }; 17241 TweenLite._onPluginEvent = function (type, tween) { 17242 var pt = tween._firstPT, 17243 changed, 17244 pt2, 17245 first, 17246 last, 17247 next; 17248 if (type === "_onInitAllProps") { 17249 //sorts the PropTween linked list in order of priority because some plugins need to render earlier/later than others, like MotionBlurPlugin applies its effects after all x/y/alpha tweens have rendered on each frame. 17250 while (pt) { 17251 next = pt._next; 17252 pt2 = first; 17253 while (pt2 && pt2.pr > pt.pr) { 17254 pt2 = pt2._next; 17255 } 17256 if (pt._prev = pt2 ? pt2._prev : last) { 17257 pt._prev._next = pt; 17258 } else { 17259 first = pt; 17260 } 17261 if (pt._next = pt2) { 17262 pt2._prev = pt; 17263 } else { 17264 last = pt; 17265 } 17266 pt = next; 17267 } 17268 pt = tween._firstPT = first; 17269 } 17270 while (pt) { 17271 if (pt.pg) if (typeof pt.t[type] === "function") if (pt.t[type]()) { 17272 changed = true; 17273 } 17274 pt = pt._next; 17275 } 17276 return changed; 17277 }; 17278 TweenPlugin.activate = function (plugins) { 17279 var i = plugins.length; 17280 while (--i > -1) { 17281 if (plugins[i].API === TweenPlugin.API) { 17282 _plugins[new plugins[i]()._propName] = plugins[i]; 17283 } 17284 } 17285 return true; 17286 }; 17287 17288 //provides a more concise way to define plugins that have no dependencies besides TweenPlugin and TweenLite, wrapping common boilerplate stuff into one function (added in 1.9.0). You don't NEED to use this to define a plugin - the old way still works and can be useful in certain (rare) situations. 17289 _gsDefine.plugin = function (config) { 17290 if (!config || !config.propName || !config.init || !config.API) { 17291 throw "illegal plugin definition."; 17292 } 17293 var propName = config.propName, 17294 priority = config.priority || 0, 17295 overwriteProps = config.overwriteProps, 17296 map = { 17297 init: "_onInitTween", 17298 set: "setRatio", 17299 kill: "_kill", 17300 round: "_mod", 17301 mod: "_mod", 17302 initAll: "_onInitAllProps" 17303 }, 17304 Plugin = _class("plugins." + propName.charAt(0).toUpperCase() + propName.substr(1) + "Plugin", function () { 17305 TweenPlugin.call(this, propName, priority); 17306 this._overwriteProps = overwriteProps || []; 17307 }, config.global === true), 17308 p = Plugin.prototype = new TweenPlugin(propName), 17309 prop; 17310 p.constructor = Plugin; 17311 Plugin.API = config.API; 17312 for (prop in map) { 17313 if (typeof config[prop] === "function") { 17314 p[map[prop]] = config[prop]; 17315 } 17316 } 17317 Plugin.version = config.version; 17318 TweenPlugin.activate([Plugin]); 17319 return Plugin; 17320 }; 17321 17322 //now run through all the dependencies discovered and if any are missing, log that to the console as a warning. This is why it's best to have TweenLite load last - it can check all the dependencies for you. 17323 a = window._gsQueue; 17324 if (a) { 17325 for (i = 0; i < a.length; i++) { 17326 a[i](); 17327 } 17328 for (p in _defLookup) { 17329 if (!_defLookup[p].func) { 17330 window.console.log("GSAP encountered missing dependency: " + p); 17331 } 17332 } 17333 } 17334 _tickerActive = false; //ensures that the first official animation forces a ticker.tick() to update the time when it is instantiated 17335})(typeof module !== "undefined" && module.exports && typeof global !== "undefined" ? global : void 0 || window, "TweenMax"); 17336 17337}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 17338},{}],6:[function(require,module,exports){ 17339"use strict"; 17340 17341/*! 17342 Zoom 1.7.21 17343 license: MIT 17344 http://www.jacklmoore.com/zoom 17345*/ 17346(function ($) { 17347 var defaults = { 17348 url: false, 17349 callback: false, 17350 target: false, 17351 duration: 120, 17352 on: 'mouseover', 17353 // other options: grab, click, toggle 17354 touch: true, 17355 // enables a touch fallback
17356 onZoomIn: false, 17357 onZoomOut: false, 17358 magnify: 1 17359 }; 17360 17361 // Core Zoom Logic, independent of event listeners. 17362 $.zoom = function (target, source, img, magnify) { 17363 var targetHeight, 17364 targetWidth, 17365 sourceHeight, 17366 sourceWidth, 17367 xRatio, 17368 yRatio, 17369 offset, 17370 $target = $(target), 17371 position = $target.css('position'), 17372 $source = $(source); 17373 17374 // The parent element needs positioning so that the zoomed element can be correctly positioned within. 17375 target.style.position = /(absolute|fixed)/.test(position) ? position : 'relative'; 17376 target.style.overflow = 'hidden'; 17377 img.style.width = img.style.height = ''; 17378 $(img).addClass('zoomImg').css({ 17379 position: 'absolute', 17380 top: 0, 17381 left: 0, 17382 opacity: 0, 17383 width: img.width * magnify, 17384 height: img.height * magnify, 17385 border: 'none', 17386 maxWidth: 'none', 17387 maxHeight: 'none' 17388 }).appendTo(target); 17389 return { 17390 init: function init() { 17391 targetWidth = $target.outerWidth(); 17392 targetHeight = $target.outerHeight(); 17393 if (source === target) { 17394 sourceWidth = targetWidth; 17395 sourceHeight = targetHeight; 17396 } else { 17397 sourceWidth = $source.outerWidth(); 17398 sourceHeight = $source.outerHeight(); 17399 } 17400 xRatio = (img.width - targetWidth) / sourceWidth; 17401 yRatio = (img.height - targetHeight) / sourceHeight; 17402 offset = $source.offset(); 17403 }, 17404 move: function move(e) { 17405 var left = e.pageX - offset.left, 17406 top = e.pageY - offset.top; 17407 top = Math.max(Math.min(top, sourceHeight), 0); 17408 left = Math.max(Math.min(left, sourceWidth), 0); 17409 img.style.left = left * -xRatio + 'px'; 17410 img.style.top = top * -yRatio + 'px'; 17411 } 17412 }; 17413 }; 17414 $.fn.zoom = function (options) { 17415 return this.each(function () { 17416 var settings = $.extend({}, defaults, options || {}), 17417 //target will display the zoomed image 17418 target = settings.target && $(settings.target)[0] || this, 17419 //source will provide zoom location info (thumbnail) 17420 source = this, 17421 $source = $(source), 17422 img = document.createElement('img'), 17423 $img = $(img), 17424 mousemove = 'mousemove.zoom', 17425 clicked = false, 17426 touched = false; 17427 17428 // If a url wasn't specified, look for an image element. 17429 if (!settings.url) { 17430 var srcElement = source.querySelector('img'); 17431 if (srcElement) { 17432 settings.url = srcElement.getAttribute('data-src') || srcElement.currentSrc || srcElement.src; 17433 } 17434 if (!settings.url) { 17435 return; 17436 } 17437 } 17438 $source.one('zoom.destroy', function (position, overflow) { 17439 $source.off(".zoom"); 17440 target.style.position = position; 17441 target.style.overflow = overflow; 17442 img.onload = null; 17443 $img.remove(); 17444 }.bind(this, target.style.position, target.style.overflow)); 17445 img.onload = function () { 17446 var zoom = $.zoom(target, source, img, settings.magnify); 17447 function start(e) { 17448 zoom.init(); 17449 zoom.move(e); 17450 17451 // Skip the fade-in for IE8 and lower since it chokes on fading-in 17452 // and changing position based on mousemovement at the same time. 17453 $img.stop().fadeTo($.support.opacity ? settings.duration : 0, 1, $.isFunction(settings.onZoomIn) ? settings.onZoomIn.call(img) : false); 17454 } 17455 function stop() { 17456 $img.stop().fadeTo(settings.duration, 0, $.isFunction(settings.onZoomOut) ? settings.onZoomOut.call(img) : false); 17457 } 17458 17459 // Mouse events 17460 if (settings.on === 'grab') { 17461 $source.on('mousedown.zoom', function (e) { 17462 if (e.which === 1) { 17463 $(document).one('mouseup.zoom', function () { 17464 stop(); 17465 $(document).off(mousemove, zoom.move); 17466 }); 17467 start(e); 17468 $(document).on(mousemove, zoom.move); 17469 e.preventDefault(); 17470 } 17471 }); 17472 } else if (settings.on === 'click') { 17473 $source.on('click.zoom', function (e) { 17474 if (clicked) { 17475 // bubble the event up to the document to trigger the unbind. 17476 return; 17477 } else { 17478 clicked = true; 17479 start(e); 17480 $(document).on(mousemove, zoom.move); 17481 $(document).one('click.zoom', function () { 17482 stop(); 17483 clicked = false;
17484 $(document).off(mousemove, zoom.move); 17485 }); 17486 return false; 17487 } 17488 }); 17489 } else if (settings.on === 'toggle') { 17490 $source.on('click.zoom', function (e) { 17491 if (clicked) { 17492 stop(); 17493 } else { 17494 start(e); 17495 } 17496 clicked = !clicked; 17497 }); 17498 } else if (settings.on === 'mouseover') { 17499 zoom.init(); // Preemptively call init because IE7 will fire the mousemove handler before the hover handler. 17500 17501 $source.on('mouseenter.zoom', start).on('mouseleave.zoom', stop).on(mousemove, zoom.move); 17502 } 17503 17504 // Touch fallback 17505 if (settings.touch) { 17506 $source.on('touchstart.zoom', function (e) { 17507 e.preventDefault(); 17508 if (touched) { 17509 touched = false; 17510 stop(); 17511 } else { 17512 touched = true; 17513 start(e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]); 17514 } 17515 }).on('touchmove.zoom', function (e) { 17516 e.preventDefault(); 17517 zoom.move(e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]); 17518 }).on('touchend.zoom', function (e) { 17519 e.preventDefault(); 17520 if (touched) { 17521 touched = false; 17522 stop(); 17523 } 17524 }); 17525 } 17526 if ($.isFunction(settings.callback)) { 17527 settings.callback.call(img); 17528 } 17529 }; 17530 img.setAttribute('role', 'presentation'); 17531 img.alt = ''; 17532 img.src = settings.url; 17533 }); 17534 }; 17535 $.fn.zoom.defaults = defaults; 17536})(window.jQuery); 17537 17538},{}],7:[function(require,module,exports){ 17539(function (global){(function (){ 17540"use strict"; 17541 17542function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 17543/* 17544 _ _ _ _ 17545 ___| (_) ___| | __ (_)___ 17546/ __| | |/ __| |/ / | / __| 17547\__ \ | | (__| < _ | \__ \ 17548|___/_|_|\___|_|\_(_)/ |___/ 17549 |__/ 17550 17551 Version: 1.6.0 17552 Author: Ken Wheeler 17553 Website: http://kenwheeler.github.io 17554 Docs: http://kenwheeler.github.io/slick 17555 Repo: http://github.com/kenwheeler/slick 17556 Issues: http://github.com/kenwheeler/slick/issues 17557 17558 */ 17559/* global window, document, define, jQuery, setInterval, clearInterval */ 17560(function (factory) { 17561 'use strict'; 17562 17563 if (typeof define === 'function' && define.amd) { 17564 define(['jquery'], factory); 17565 } else if (typeof exports !== 'undefined') { 17566 module.exports = factory((typeof window !== "undefined" ? window['jQuery'] : typeof global !== "undefined" ? global['jQuery'] : null)); 17567 } else { 17568 factory(jQuery); 17569 } 17570})(function ($) { 17571 'use strict'; 17572 17573 var Slick = window.Slick || {}; 17574 Slick = function () { 17575 var instanceUid = 0; 17576 function Slick(element, settings) { 17577 var _ = this, 17578 dataSettings; 17579 _.defaults = { 17580 accessibility: true, 17581 adaptiveHeight: false, 17582 appendArrows: $(element), 17583 appendDots: $(element), 17584 arrows: true, 17585 asNavFor: null, 17586 prevArrow: '<button type="button" data-role="none" class="slick-prev" aria-label="Previous" tabindex="0" role="button">Previous</button>', 17587 nextArrow: '<button type="button" data-role="none" class="slick-next" aria-label="Next" tabindex="0" role="button">Next</button>', 17588 autoplay: false, 17589 autoplaySpeed: 3000, 17590 centerMode: false, 17591 centerPadding: '50px', 17592 cssEase: 'ease', 17593 customPaging: function customPaging(slider, i) { 17594 return $('<button type="button" data-role="none" role="button" tabindex="0" />').text(i + 1); 17595 }, 17596 dots: false, 17597 dotsClass: 'slick-dots', 17598 draggable: true, 17599 easing: 'linear', 17600 edgeFriction: 0.35, 17601 fade: false, 17602 focusOnSelect: false, 17603 infinite: true, 17604 initialSlide: 0, 17605 lazyLoad: 'ondemand', 17606 mobileFirst: false, 17607 pauseOnHover: true, 17608 pauseOnFocus: true, 17609 pauseOnDotsHover: false, 17610 respondTo: 'window', 17611 responsive: null, 17612 rows: 1, 17613 rtl: false, 17614 slide: '', 17615 slidesPerRow: 1, 17616 slidesToShow: 1, 17617 slidesToScroll: 1, 17618 speed: 500, 17619 swipe: true, 17620 swipeToSlide: false, 17621 touchMove: true, 17622 touchThreshold: 5, 17623 useCSS: true, 17624 useTransform: true, 17625 variableWidth: false, 17626 vertical: false, 17627 verticalSwiping: false, 17628 waitForAnimate: true, 17629 zIndex: 1000 17630 }; 17631 _.initials = { 17632 animating: false, 17633 dragging: false, 17634 autoPlayTimer: null, 17635 currentDirection: 0, 17636 currentLeft: null, 17637 currentSlide: 0, 17638 direction: 1, 17639 $dots: null, 17640 listWidth: null, 17641 listHeight: null, 17642 loadIndex: 0, 17643 $nextArrow: null, 17644 $prevArrow: null, 17645 slideCount: null, 17646 slideWidth: null, 17647 $slideTrack: null, 17648 $slides: null, 17649 sliding: false, 17650 slideOffset: 0, 17651 swipeLeft: null, 17652 $list: null, 17653 touchObject: {}, 17654 transformsEnabled: false,
17655 unslicked: false 17656 }; 17657 $.extend(_, _.initials); 17658 _.activeBreakpoint = null; 17659 _.animType = null; 17660 _.animProp = null; 17661 _.breakpoints = []; 17662 _.breakpointSettings = []; 17663 _.cssTransitions = false; 17664 _.focussed = false; 17665 _.interrupted = false; 17666 _.hidden = 'hidden'; 17667 _.paused = true; 17668 _.positionProp = null; 17669 _.respondTo = null; 17670 _.rowCount = 1; 17671 _.shouldClick = true; 17672 _.$slider = $(element); 17673 _.$slidesCache = null; 17674 _.transformType = null; 17675 _.transitionType = null; 17676 _.visibilityChange = 'visibilitychange'; 17677 _.windowWidth = 0; 17678 _.windowTimer = null; 17679 dataSettings = $(element).data('slick') || {}; 17680 _.options = $.extend({}, _.defaults, settings, dataSettings); 17681 _.currentSlide = _.options.initialSlide; 17682 _.originalSettings = _.options; 17683 if (typeof document.mozHidden !== 'undefined') { 17684 _.hidden = 'mozHidden'; 17685 _.visibilityChange = 'mozvisibilitychange'; 17686 } else if (typeof document.webkitHidden !== 'undefined') { 17687 _.hidden = 'webkitHidden'; 17688 _.visibilityChange = 'webkitvisibilitychange'; 17689 } 17690 _.autoPlay = $.proxy(_.autoPlay, _); 17691 _.autoPlayClear = $.proxy(_.autoPlayClear, _); 17692 _.autoPlayIterator = $.proxy(_.autoPlayIterator, _); 17693 _.changeSlide = $.proxy(_.changeSlide, _); 17694 _.clickHandler = $.proxy(_.clickHandler, _); 17695 _.selectHandler = $.proxy(_.selectHandler, _); 17696 _.setPosition = $.proxy(_.setPosition, _); 17697 _.swipeHandler = $.proxy(_.swipeHandler, _); 17698 _.dragHandler = $.proxy(_.dragHandler, _); 17699 _.keyHandler = $.proxy(_.keyHandler, _); 17700 _.instanceUid = instanceUid++; 17701 17702 // A simple way to check for HTML strings 17703 // Strict HTML recognition (must start with <) 17704 // Extracted from jQuery v1.11 source 17705 _.htmlExpr = /^(?:\s*(<[\w\W]+>)[^>]*)$/; 17706 _.registerBreakpoints(); 17707 _.init(true); 17708 } 17709 return Slick; 17710 }(); 17711 Slick.prototype.activateADA = function () { 17712 var _ = this; 17713 _.$slideTrack.find('.slick-active').attr({ 17714 'aria-hidden': 'false' 17715 }).find('a, input, button, select').attr({ 17716 'tabindex': '0' 17717 }); 17718 }; 17719 Slick.prototype.addSlide = Slick.prototype.slickAdd = function (markup, index, addBefore) { 17720 var _ = this; 17721 if (typeof index === 'boolean') { 17722 addBefore = index; 17723 index = null; 17724 } else if (index < 0 || index >= _.slideCount) { 17725 return false; 17726 } 17727 _.unload(); 17728 if (typeof index === 'number') { 17729 if (index === 0 && _.$slides.length === 0) { 17730 $(markup).appendTo(_.$slideTrack); 17731 } else if (addBefore) { 17732 $(markup).insertBefore(_.$slides.eq(index)); 17733 } else { 17734 $(markup).insertAfter(_.$slides.eq(index)); 17735 } 17736 } else { 17737 if (addBefore === true) { 17738 $(markup).prependTo(_.$slideTrack); 17739 } else { 17740 $(markup).appendTo(_.$slideTrack); 17741 } 17742 } 17743 _.$slides = _.$slideTrack.children(this.options.slide); 17744 _.$slideTrack.children(this.options.slide).detach(); 17745 _.$slideTrack.append(_.$slides); 17746 _.$slides.each(function (index, element) { 17747 $(element).attr('data-slick-index', index); 17748 }); 17749 _.$slidesCache = _.$slides; 17750 _.reinit(); 17751 }; 17752 Slick.prototype.animateHeight = function () { 17753 var _ = this; 17754 if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) { 17755 var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true); 17756 _.$list.animate({ 17757 height: targetHeight 17758 }, _.options.speed); 17759 } 17760 }; 17761 Slick.prototype.animateSlide = function (targetLeft, callback) { 17762 var animProps = {}, 17763 _ = this; 17764 _.animateHeight(); 17765 if (_.options.rtl === true && _.options.vertical === false) { 17766 targetLeft = -targetLeft; 17767 } 17768 if (_.transformsEnabled === false) { 17769 if (_.options.vertical === false) { 17770 _.$slideTrack.animate({ 17771 left: targetLeft 17772 }, _.options.speed, _.options.easing, callback); 17773 } else { 17774 _.$slideTrack.animate({ 17775 top: targetLeft 17776 }, _.options.speed, _.options.easing, callback); 17777 } 17778 } else { 17779 if (_.cssTransitions === false) { 17780 if (_.options.rtl === true) { 17781 _.currentLeft = -_.currentLeft; 17782 } 17783 $({ 17784 animStart: _.currentLeft 17785 }).animate({ 17786 animStart: targetLeft 17787 }, { 17788 duration: _.options.speed, 17789 easing: _.options.easing, 17790 step: function step(now) { 17791 now = Math.ceil(now); 17792 if (_.options.vertical === false) { 17793 animProps[_.animType] = 'translate(' + now + 'px, 0px)'; 17794 _.$slideTrack.css(animProps); 17795 } else { 17796 animProps[_.animType] = 'translate(0px,' + now + 'px)'; 17797 _.$slideTrack.css(animProps); 17798 } 17799 }, 17800 complete: function complete() { 17801 if (callback) { 17802 callback.call(); 17803 } 17804 } 17805 }); 17806 } else { 17807 _.applyTransition();
17808 targetLeft = Math.ceil(targetLeft); 17809 if (_.options.vertical === false) { 17810 animProps[_.animType] = 'translate3d(' + targetLeft + 'px, 0px, 0px)'; 17811 } else { 17812 animProps[_.animType] = 'translate3d(0px,' + targetLeft + 'px, 0px)'; 17813 } 17814 _.$slideTrack.css(animProps); 17815 if (callback) { 17816 setTimeout(function () { 17817 _.disableTransition(); 17818 callback.call(); 17819 }, _.options.speed); 17820 } 17821 } 17822 } 17823 }; 17824 Slick.prototype.getNavTarget = function () { 17825 var _ = this, 17826 asNavFor = _.options.asNavFor; 17827 if (asNavFor && asNavFor !== null) { 17828 asNavFor = $(asNavFor).not(_.$slider); 17829 } 17830 return asNavFor; 17831 }; 17832 Slick.prototype.asNavFor = function (index) { 17833 var _ = this, 17834 asNavFor = _.getNavTarget(); 17835 if (asNavFor !== null && _typeof(asNavFor) === 'object') { 17836 asNavFor.each(function () { 17837 var target = $(this).slick('getSlick'); 17838 if (!target.unslicked) { 17839 target.slideHandler(index, true); 17840 } 17841 }); 17842 } 17843 }; 17844 Slick.prototype.applyTransition = function (slide) { 17845 var _ = this, 17846 transition = {}; 17847 if (_.options.fade === false) { 17848 transition[_.transitionType] = _.transformType + ' ' + _.options.speed + 'ms ' + _.options.cssEase; 17849 } else { 17850 transition[_.transitionType] = 'opacity ' + _.options.speed + 'ms ' + _.options.cssEase; 17851 } 17852 if (_.options.fade === false) { 17853 _.$slideTrack.css(transition); 17854 } else { 17855 _.$slides.eq(slide).css(transition); 17856 } 17857 }; 17858 Slick.prototype.autoPlay = function () { 17859 var _ = this; 17860 _.autoPlayClear(); 17861 if (_.slideCount > _.options.slidesToShow) { 17862 _.autoPlayTimer = setInterval(_.autoPlayIterator, _.options.autoplaySpeed); 17863 } 17864 }; 17865 Slick.prototype.autoPlayClear = function () { 17866 var _ = this; 17867 if (_.autoPlayTimer) { 17868 clearInterval(_.autoPlayTimer); 17869 } 17870 }; 17871 Slick.prototype.autoPlayIterator = function () { 17872 var _ = this, 17873 slideTo = _.currentSlide + _.options.slidesToScroll; 17874 if (!_.paused && !_.interrupted && !_.focussed) { 17875 if (_.options.infinite === false) { 17876 if (_.direction === 1 && _.currentSlide + 1 === _.slideCount - 1) { 17877 _.direction = 0; 17878 } else if (_.direction === 0) { 17879 slideTo = _.currentSlide - _.options.slidesToScroll; 17880 if (_.currentSlide - 1 === 0) { 17881 _.direction = 1; 17882 } 17883 } 17884 } 17885 _.slideHandler(slideTo); 17886 } 17887 }; 17888 Slick.prototype.buildArrows = function () { 17889 var _ = this; 17890 if (_.options.arrows === true) { 17891 _.$prevArrow = $(_.options.prevArrow).addClass('slick-arrow'); 17892 _.$nextArrow = $(_.options.nextArrow).addClass('slick-arrow'); 17893 if (_.slideCount > _.options.slidesToShow) { 17894 _.$prevArrow.removeClass('slick-hidden').removeAttr('aria-hidden tabindex'); 17895 _.$nextArrow.removeClass('slick-hidden').removeAttr('aria-hidden tabindex'); 17896 if (_.htmlExpr.test(_.options.prevArrow)) { 17897 _.$prevArrow.prependTo(_.options.appendArrows); 17898 } 17899 if (_.htmlExpr.test(_.options.nextArrow)) { 17900 _.$nextArrow.appendTo(_.options.appendArrows); 17901 } 17902 if (_.options.infinite !== true) { 17903 _.$prevArrow.addClass('slick-disabled').attr('aria-disabled', 'true'); 17904 } 17905 } else { 17906 _.$prevArrow.add(_.$nextArrow).addClass('slick-hidden').attr({ 17907 'aria-disabled': 'true', 17908 'tabindex': '-1' 17909 }); 17910 } 17911 } 17912 }; 17913 Slick.prototype.buildDots = function () { 17914 var _ = this, 17915 i, 17916 dot; 17917 if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { 17918 _.$slider.addClass('slick-dotted'); 17919 dot = $('<ul />').addClass(_.options.dotsClass); 17920 for (i = 0; i <= _.getDotCount(); i += 1) { 17921 dot.append($('<li />').append(_.options.customPaging.call(this, _, i))); 17922 } 17923 _.$dots = dot.appendTo(_.options.appendDots); 17924 _.$dots.find('li').first().addClass('slick-active').attr('aria-hidden', 'false'); 17925 } 17926 }; 17927 Slick.prototype.buildOut = function () { 17928 var _ = this; 17929 _.$slides = _.$slider.children(_.options.slide + ':not(.slick-cloned)').addClass('slick-slide'); 17930 _.slideCount = _.$slides.length; 17931 _.$slides.each(function (index, element) { 17932 $(element).attr('data-slick-index', index).data('originalStyling', $(element).attr('style') || ''); 17933 }); 17934 _.$slider.addClass('slick-slider'); 17935 _.$slideTrack = _.slideCount === 0 ? $('<div class="slick-track"/>').appendTo(_.$slider) : _.$slides.wrapAll('<div class="slick-track"/>').parent(); 17936 _.$list = _.$slideTrack.wrap('<div aria-live="polite" class="slick-list"/>').parent(); 17937 _.$slideTrack.css('opacity', 0); 17938 if (_.options.centerMode === true || _.options.swipeToSlide === true) {
17939 _.options.slidesToScroll = 1; 17940 } 17941 $('img[data-lazy]', _.$slider).not('[src]').addClass('slick-loading'); 17942 _.setupInfinite(); 17943 _.buildArrows(); 17944 _.buildDots(); 17945 _.updateDots(); 17946 _.setSlideClasses(typeof _.currentSlide === 'number' ? _.currentSlide : 0); 17947 if (_.options.draggable === true) { 17948 _.$list.addClass('draggable'); 17949 } 17950 }; 17951 Slick.prototype.buildRows = function () { 17952 var _ = this, 17953 a, 17954 b, 17955 c, 17956 newSlides, 17957 numOfSlides, 17958 originalSlides, 17959 slidesPerSection; 17960 newSlides = document.createDocumentFragment(); 17961 originalSlides = _.$slider.children(); 17962 if (_.options.rows > 1) { 17963 slidesPerSection = _.options.slidesPerRow * _.options.rows; 17964 numOfSlides = Math.ceil(originalSlides.length / slidesPerSection); 17965 for (a = 0; a < numOfSlides; a++) { 17966 var slide = document.createElement('div'); 17967 for (b = 0; b < _.options.rows; b++) { 17968 var row = document.createElement('div'); 17969 for (c = 0; c < _.options.slidesPerRow; c++) { 17970 var target = a * slidesPerSection + (b * _.options.slidesPerRow + c); 17971 if (originalSlides.get(target)) { 17972 row.appendChild(originalSlides.get(target)); 17973 } 17974 } 17975 slide.appendChild(row); 17976 } 17977 newSlides.appendChild(slide); 17978 } 17979 _.$slider.empty().append(newSlides); 17980 _.$slider.children().children().children().css({ 17981 'width': 100 / _.options.slidesPerRow + '%', 17982 'display': 'inline-block' 17983 }); 17984 } 17985 }; 17986 Slick.prototype.checkResponsive = function (initial, forceUpdate) { 17987 var _ = this, 17988 breakpoint, 17989 targetBreakpoint, 17990 respondToWidth, 17991 triggerBreakpoint = false; 17992 var sliderWidth = _.$slider.width(); 17993 var windowWidth = window.innerWidth || $(window).width(); 17994 if (_.respondTo === 'window') { 17995 respondToWidth = windowWidth; 17996 } else if (_.respondTo === 'slider') { 17997 respondToWidth = sliderWidth; 17998 } else if (_.respondTo === 'min') { 17999 respondToWidth = Math.min(windowWidth, sliderWidth); 18000 } 18001 if (_.options.responsive && _.options.responsive.length && _.options.responsive !== null) { 18002 targetBreakpoint = null; 18003 for (breakpoint in _.breakpoints) { 18004 if (_.breakpoints.hasOwnProperty(breakpoint)) { 18005 if (_.originalSettings.mobileFirst === false) { 18006 if (respondToWidth < _.breakpoints[breakpoint]) { 18007 targetBreakpoint = _.breakpoints[breakpoint]; 18008 } 18009 } else { 18010 if (respondToWidth > _.breakpoints[breakpoint]) { 18011 targetBreakpoint = _.breakpoints[breakpoint]; 18012 } 18013 } 18014 } 18015 } 18016 if (targetBreakpoint !== null) { 18017 if (_.activeBreakpoint !== null) { 18018 if (targetBreakpoint !== _.activeBreakpoint || forceUpdate) { 18019 _.activeBreakpoint = targetBreakpoint; 18020 if (_.breakpointSettings[targetBreakpoint] === 'unslick') { 18021 _.unslick(targetBreakpoint); 18022 } else { 18023 _.options = $.extend({}, _.originalSettings, _.breakpointSettings[targetBreakpoint]); 18024 if (initial === true) { 18025 _.currentSlide = _.options.initialSlide; 18026 } 18027 _.refresh(initial); 18028 } 18029 triggerBreakpoint = targetBreakpoint; 18030 } 18031 } else { 18032 _.activeBreakpoint = targetBreakpoint; 18033 if (_.breakpointSettings[targetBreakpoint] === 'unslick') { 18034 _.unslick(targetBreakpoint); 18035 } else { 18036 _.options = $.extend({}, _.originalSettings, _.breakpointSettings[targetBreakpoint]); 18037 if (initial === true) { 18038 _.currentSlide = _.options.initialSlide; 18039 } 18040 _.refresh(initial); 18041 } 18042 triggerBreakpoint = targetBreakpoint; 18043 } 18044 } else { 18045 if (_.activeBreakpoint !== null) { 18046 _.activeBreakpoint = null; 18047 _.options = _.originalSettings; 18048 if (initial === true) { 18049 _.currentSlide = _.options.initialSlide; 18050 } 18051 _.refresh(initial);
18052 triggerBreakpoint = targetBreakpoint; 18053 } 18054 } 18055 18056 // only trigger breakpoints during an actual break. not on initialize. 18057 if (!initial && triggerBreakpoint !== false) { 18058 _.$slider.trigger('breakpoint', [_, triggerBreakpoint]); 18059 } 18060 } 18061 }; 18062 Slick.prototype.changeSlide = function (event, dontAnimate) { 18063 var _ = this, 18064 $target = $(event.currentTarget), 18065 indexOffset, 18066 slideOffset, 18067 unevenOffset; 18068 18069 // If target is a link, prevent default action. 18070 if ($target.is('a')) { 18071 event.preventDefault(); 18072 } 18073 18074 // If target is not the <li> element (ie: a child), find the <li>. 18075 if (!$target.is('li')) { 18076 $target = $target.closest('li'); 18077 } 18078 unevenOffset = _.slideCount % _.options.slidesToScroll !== 0; 18079 indexOffset = unevenOffset ? 0 : (_.slideCount - _.currentSlide) % _.options.slidesToScroll; 18080 switch (event.data.message) { 18081 case 'previous': 18082 slideOffset = indexOffset === 0 ? _.options.slidesToScroll : _.options.slidesToShow - indexOffset; 18083 if (_.slideCount > _.options.slidesToShow) { 18084 _.slideHandler(_.currentSlide - slideOffset, false, dontAnimate); 18085 } 18086 break; 18087 case 'next': 18088 slideOffset = indexOffset === 0 ? _.options.slidesToScroll : indexOffset; 18089 if (_.slideCount > _.options.slidesToShow) { 18090 _.slideHandler(_.currentSlide + slideOffset, false, dontAnimate); 18091 } 18092 break; 18093 case 'index': 18094 var index = event.data.index === 0 ? 0 : event.data.index || $target.index() * _.options.slidesToScroll; 18095 _.slideHandler(_.checkNavigable(index), false, dontAnimate); 18096 $target.children().trigger('focus'); 18097 break; 18098 default: 18099 return; 18100 } 18101 }; 18102 Slick.prototype.checkNavigable = function (index) { 18103 var _ = this, 18104 navigables, 18105 prevNavigable; 18106 navigables = _.getNavigableIndexes(); 18107 prevNavigable = 0; 18108 if (index > navigables[navigables.length - 1]) { 18109 index = navigables[navigables.length - 1]; 18110 } else { 18111 for (var n in navigables) { 18112 if (index < navigables[n]) { 18113 index = prevNavigable; 18114 break; 18115 } 18116 prevNavigable = navigables[n]; 18117 } 18118 } 18119 return index; 18120 }; 18121 Slick.prototype.cleanUpEvents = function () { 18122 var _ = this; 18123 if (_.options.dots && _.$dots !== null) { 18124 $('li', _.$dots).off('click.slick', _.changeSlide).off('mouseenter.slick', $.proxy(_.interrupt, _, true)).off('mouseleave.slick', $.proxy(_.interrupt, _, false)); 18125 } 18126 _.$slider.off('focus.slick blur.slick'); 18127 if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { 18128 _.$prevArrow && _.$prevArrow.off('click.slick', _.changeSlide); 18129 _.$nextArrow && _.$nextArrow.off('click.slick', _.changeSlide); 18130 } 18131 _.$list.off('touchstart.slick mousedown.slick', _.swipeHandler); 18132 _.$list.off('touchmove.slick mousemove.slick', _.swipeHandler); 18133 _.$list.off('touchend.slick mouseup.slick', _.swipeHandler);
18134 _.$list.off('touchcancel.slick mouseleave.slick', _.swipeHandler); 18135 _.$list.off('click.slick', _.clickHandler); 18136 $(document).off(_.visibilityChange, _.visibility); 18137 _.cleanUpSlideEvents(); 18138 if (_.options.accessibility === true) { 18139 _.$list.off('keydown.slick', _.keyHandler); 18140 } 18141 if (_.options.focusOnSelect === true) { 18142 $(_.$slideTrack).children().off('click.slick', _.selectHandler); 18143 } 18144 $(window).off('orientationchange.slick.slick-' + _.instanceUid, _.orientationChange); 18145 $(window).off('resize.slick.slick-' + _.instanceUid, _.resize); 18146 $('[draggable!=true]', _.$slideTrack).off('dragstart', _.preventDefault); 18147 $(window).off('load.slick.slick-' + _.instanceUid, _.setPosition); 18148 $(document).off('ready.slick.slick-' + _.instanceUid, _.setPosition); 18149 }; 18150 Slick.prototype.cleanUpSlideEvents = function () { 18151 var _ = this; 18152 _.$list.off('mouseenter.slick', $.proxy(_.interrupt, _, true)); 18153 _.$list.off('mouseleave.slick', $.proxy(_.interrupt, _, false)); 18154 }; 18155 Slick.prototype.cleanUpRows = function () { 18156 var _ = this, 18157 originalSlides; 18158 if (_.options.rows > 1) { 18159 originalSlides = _.$slides.children().children(); 18160 originalSlides.removeAttr('style'); 18161 _.$slider.empty().append(originalSlides); 18162 } 18163 }; 18164 Slick.prototype.clickHandler = function (event) { 18165 var _ = this; 18166 if (_.shouldClick === false) { 18167 event.stopImmediatePropagation(); 18168 event.stopPropagation(); 18169 event.preventDefault(); 18170 } 18171 }; 18172 Slick.prototype.destroy = function (refresh) { 18173 var _ = this; 18174 _.autoPlayClear(); 18175 _.touchObject = {}; 18176 _.cleanUpEvents(); 18177 $('.slick-cloned', _.$slider).detach(); 18178 if (_.$dots) { 18179 _.$dots.remove(); 18180 } 18181 if (_.$prevArrow && _.$prevArrow.length) { 18182 _.$prevArrow.removeClass('slick-disabled slick-arrow slick-hidden').removeAttr('aria-hidden aria-disabled tabindex').css('display', ''); 18183 if (_.htmlExpr.test(_.options.prevArrow)) { 18184 _.$prevArrow.remove(); 18185 } 18186 } 18187 if (_.$nextArrow && _.$nextArrow.length) { 18188 _.$nextArrow.removeClass('slick-disabled slick-arrow slick-hidden').removeAttr('aria-hidden aria-disabled tabindex').css('display', ''); 18189 if (_.htmlExpr.test(_.options.nextArrow)) { 18190 _.$nextArrow.remove(); 18191 } 18192 } 18193 if (_.$slides) { 18194 _.$slides.removeClass('slick-slide slick-active slick-center slick-visible slick-current').removeAttr('aria-hidden').removeAttr('data-slick-index').each(function () { 18195 $(this).attr('style', $(this).data('originalStyling')); 18196 }); 18197 _.$slideTrack.children(this.options.slide).detach(); 18198 _.$slideTrack.detach(); 18199 _.$list.detach(); 18200 _.$slider.append(_.$slides); 18201 } 18202 _.cleanUpRows(); 18203 _.$slider.removeClass('slick-slider'); 18204 _.$slider.removeClass('slick-initialized'); 18205 _.$slider.removeClass('slick-dotted'); 18206 _.unslicked = true; 18207 if (!refresh) { 18208 _.$slider.trigger('destroy', [_]); 18209 } 18210 }; 18211 Slick.prototype.disableTransition = function (slide) { 18212 var _ = this, 18213 transition = {}; 18214 transition[_.transitionType] = ''; 18215 if (_.options.fade === false) { 18216 _.$slideTrack.css(transition); 18217 } else { 18218 _.$slides.eq(slide).css(transition); 18219 } 18220 }; 18221 Slick.prototype.fadeSlide = function (slideIndex, callback) { 18222 var _ = this; 18223 if (_.cssTransitions === false) { 18224 _.$slides.eq(slideIndex).css({ 18225 zIndex: _.options.zIndex 18226 }); 18227 _.$slides.eq(slideIndex).animate({ 18228 opacity: 1 18229 }, _.options.speed, _.options.easing, callback); 18230 } else { 18231 _.applyTransition(slideIndex); 18232 _.$slides.eq(slideIndex).css({ 18233 opacity: 1, 18234 zIndex: _.options.zIndex 18235 }); 18236 if (callback) { 18237 setTimeout(function () { 18238 _.disableTransition(slideIndex); 18239 callback.call(); 18240 }, _.options.speed); 18241 } 18242 } 18243 }; 18244 Slick.prototype.fadeSlideOut = function (slideIndex) { 18245 var _ = this; 18246 if (_.cssTransitions === false) { 18247 _.$slides.eq(slideIndex).animate({ 18248 opacity: 0, 18249 zIndex: _.options.zIndex - 2 18250 }, _.options.speed, _.options.easing); 18251 } else { 18252 _.applyTransition(slideIndex); 18253 _.$slides.eq(slideIndex).css({ 18254 opacity: 0, 18255 zIndex: _.options.zIndex - 2 18256 }); 18257 } 18258 };
18259 Slick.prototype.filterSlides = Slick.prototype.slickFilter = function (filter) { 18260 var _ = this; 18261 if (filter !== null) { 18262 _.$slidesCache = _.$slides; 18263 _.unload(); 18264 _.$slideTrack.children(this.options.slide).detach(); 18265 _.$slidesCache.filter(filter).appendTo(_.$slideTrack); 18266 _.reinit(); 18267 } 18268 }; 18269 Slick.prototype.focusHandler = function () { 18270 var _ = this; 18271 _.$slider.off('focus.slick blur.slick').on('focus.slick blur.slick', '*:not(.slick-arrow)', function (event) { 18272 event.stopImmediatePropagation(); 18273 var $sf = $(this); 18274 setTimeout(function () { 18275 if (_.options.pauseOnFocus) { 18276 _.focussed = $sf.is(':focus'); 18277 _.autoPlay(); 18278 } 18279 }, 0); 18280 }); 18281 }; 18282 Slick.prototype.getCurrent = Slick.prototype.slickCurrentSlide = function () { 18283 var _ = this; 18284 return _.currentSlide; 18285 }; 18286 Slick.prototype.getDotCount = function () { 18287 var _ = this; 18288 var breakPoint = 0; 18289 var counter = 0; 18290 var pagerQty = 0; 18291 if (_.options.infinite === true) { 18292 while (breakPoint < _.slideCount) { 18293 ++pagerQty; 18294 breakPoint = counter + _.options.slidesToScroll; 18295 counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow; 18296 } 18297 } else if (_.options.centerMode === true) { 18298 pagerQty = _.slideCount; 18299 } else if (!_.options.asNavFor) { 18300 pagerQty = 1 + Math.ceil((_.slideCount - _.options.slidesToShow) / _.options.slidesToScroll); 18301 } else { 18302 while (breakPoint < _.slideCount) { 18303 ++pagerQty; 18304 breakPoint = counter + _.options.slidesToScroll; 18305 counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow; 18306 } 18307 } 18308 return pagerQty - 1; 18309 }; 18310 Slick.prototype.getLeft = function (slideIndex) { 18311 var _ = this, 18312 targetLeft, 18313 verticalHeight, 18314 verticalOffset = 0, 18315 targetSlide; 18316 _.slideOffset = 0; 18317 verticalHeight = _.$slides.first().outerHeight(true); 18318 if (_.options.infinite === true) { 18319 if (_.slideCount > _.options.slidesToShow) { 18320 _.slideOffset = _.slideWidth * _.options.slidesToShow * -1; 18321 verticalOffset = verticalHeight * _.options.slidesToShow * -1; 18322 } 18323 if (_.slideCount % _.options.slidesToScroll !== 0) { 18324 if (slideIndex + _.options.slidesToScroll > _.slideCount && _.slideCount > _.options.slidesToShow) { 18325 if (slideIndex > _.slideCount) {
18326 _.slideOffset = (_.options.slidesToShow - (slideIndex - _.slideCount)) * _.slideWidth * -1; 18327 verticalOffset = (_.options.slidesToShow - (slideIndex - _.slideCount)) * verticalHeight * -1; 18328 } else { 18329 _.slideOffset = _.slideCount % _.options.slidesToScroll * _.slideWidth * -1; 18330 verticalOffset = _.slideCount % _.options.slidesToScroll * verticalHeight * -1; 18331 } 18332 } 18333 } 18334 } else { 18335 if (slideIndex + _.options.slidesToShow > _.slideCount) { 18336 _.slideOffset = (slideIndex + _.options.slidesToShow - _.slideCount) * _.slideWidth; 18337 verticalOffset = (slideIndex + _.options.slidesToShow - _.slideCount) * verticalHeight; 18338 } 18339 } 18340 if (_.slideCount <= _.options.slidesToShow) { 18341 _.slideOffset = 0; 18342 verticalOffset = 0; 18343 } 18344 if (_.options.centerMode === true && _.options.infinite === true) { 18345 _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2) - _.slideWidth; 18346 } else if (_.options.centerMode === true) { 18347 _.slideOffset = 0; 18348 _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2); 18349 } 18350 if (_.options.vertical === false) { 18351 targetLeft = slideIndex * _.slideWidth * -1 + _.slideOffset; 18352 } else { 18353 targetLeft = slideIndex * verticalHeight * -1 + verticalOffset; 18354 } 18355 if (_.options.variableWidth === true) {
18356 if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) { 18357 targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex); 18358 } else { 18359 targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow); 18360 } 18361 if (_.options.rtl === true) { 18362 if (targetSlide[0]) { 18363 targetLeft = (_.$slideTrack.width() - targetSlide[0].offsetLeft - targetSlide.width()) * -1; 18364 } else { 18365 targetLeft = 0; 18366 } 18367 } else { 18368 targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0; 18369 } 18370 if (_.options.centerMode === true) { 18371 if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) { 18372 targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex); 18373 } else { 18374 targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow + 1); 18375 } 18376 if (_.options.rtl === true) { 18377 if (targetSlide[0]) { 18378 targetLeft = (_.$slideTrack.width() - targetSlide[0].offsetLeft - targetSlide.width()) * -1; 18379 } else { 18380 targetLeft = 0; 18381 } 18382 } else { 18383 targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0; 18384 } 18385 targetLeft += (_.$list.width() - targetSlide.outerWidth()) / 2; 18386 } 18387 } 18388 return targetLeft; 18389 }; 18390 Slick.prototype.getOption = Slick.prototype.slickGetOption = function (option) { 18391 var _ = this; 18392 return _.options[option]; 18393 }; 18394 Slick.prototype.getNavigableIndexes = function () { 18395 var _ = this, 18396 breakPoint = 0, 18397 counter = 0, 18398 indexes = [], 18399 max; 18400 if (_.options.infinite === false) { 18401 max = _.slideCount; 18402 } else { 18403 breakPoint = _.options.slidesToScroll * -1; 18404 counter = _.options.slidesToScroll * -1; 18405 max = _.slideCount * 2; 18406 } 18407 while (breakPoint < max) { 18408 indexes.push(breakPoint); 18409 breakPoint = counter + _.options.slidesToScroll; 18410 counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow; 18411 } 18412 return indexes; 18413 }; 18414 Slick.prototype.getSlick = function () { 18415 return this; 18416 }; 18417 Slick.prototype.getSlideCount = function () { 18418 var _ = this, 18419 slidesTraversed, 18420 swipedSlide, 18421 centerOffset; 18422 centerOffset = _.options.centerMode === true ? _.slideWidth * Math.floor(_.options.slidesToShow / 2) : 0; 18423 if (_.options.swipeToSlide === true) { 18424 _.$slideTrack.find('.slick-slide').each(function (index, slide) { 18425 if (slide.offsetLeft - centerOffset + $(slide).outerWidth() / 2 > _.swipeLeft * -1) { 18426 swipedSlide = slide; 18427 return false; 18428 } 18429 }); 18430 slidesTraversed = Math.abs($(swipedSlide).attr('data-slick-index') - _.currentSlide) || 1; 18431 return slidesTraversed; 18432 } else { 18433 return _.options.slidesToScroll; 18434 } 18435 }; 18436 Slick.prototype.goTo = Slick.prototype.slickGoTo = function (slide, dontAnimate) { 18437 var _ = this; 18438 _.changeSlide({ 18439 data: { 18440 message: 'index', 18441 index: parseInt(slide) 18442 } 18443 }, dontAnimate); 18444 }; 18445 Slick.prototype.init = function (creation) { 18446 var _ = this; 18447 if (!$(_.$slider).hasClass('slick-initialized')) { 18448 $(_.$slider).addClass('slick-initialized'); 18449 _.buildRows(); 18450 _.buildOut(); 18451 _.setProps(); 18452 _.startLoad(); 18453 _.loadSlider(); 18454 _.initializeEvents(); 18455 _.updateArrows(); 18456 _.updateDots(); 18457 _.checkResponsive(true); 18458 _.focusHandler(); 18459 } 18460 if (creation) { 18461 _.$slider.trigger('init', [_]); 18462 } 18463 if (_.options.accessibility === true) { 18464 _.initADA(); 18465 } 18466 if (_.options.autoplay) { 18467 _.paused = false; 18468 _.autoPlay(); 18469 } 18470 }; 18471 Slick.prototype.initADA = function () { 18472 var _ = this; 18473 _.$slides.add(_.$slideTrack.find('.slick-cloned')).attr({ 18474 'aria-hidden': 'true', 18475 'tabindex': '-1' 18476 }).find('a, input, button, select').attr({ 18477 'tabindex': '-1' 18478 }); 18479 _.$slideTrack.attr('role', 'listbox'); 18480 _.$slides.not(_.$slideTrack.find('.slick-cloned')).each(function (i) { 18481 $(this).attr({ 18482 'role': 'option', 18483 'aria-describedby': 'slick-slide' + _.instanceUid + i + '' 18484 }); 18485 }); 18486 if (_.$dots !== null) { 18487 _.$dots.attr('role', 'tablist').find('li').each(function (i) { 18488 $(this).attr({ 18489 'role': 'presentation', 18490 'aria-selected': 'false', 18491 'aria-controls': 'navigation' + _.instanceUid + i + '', 18492 'id': 'slick-slide' + _.instanceUid + i + '' 18493 }); 18494 }).first().attr('aria-selected', 'true').end().find('button').attr('role', 'button').end().closest('div').attr('role', 'toolbar'); 18495 } 18496 _.activateADA(); 18497 }; 18498 Slick.prototype.initArrowEvents = function () { 18499 var _ = this; 18500 if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { 18501 _.$prevArrow.off('click.slick').on('click.slick', { 18502 message: 'previous' 18503 }, _.changeSlide); 18504 _.$nextArrow.off('click.slick').on('click.slick', { 18505 message: 'next' 18506 }, _.changeSlide); 18507 } 18508 }; 18509 Slick.prototype.initDotEvents = function () { 18510 var _ = this; 18511 if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { 18512 $('li', _.$dots).on('click.slick', { 18513 message: 'index' 18514 }, _.changeSlide); 18515 } 18516 if (_.options.dots === true && _.options.pauseOnDotsHover === true) { 18517 $('li', _.$dots).on('mouseenter.slick', $.proxy(_.interrupt, _, true)).on('mouseleave.
18517slick', $.proxy(_.interrupt, _, false)); 18518 } 18519 }; 18520 Slick.prototype.initSlideEvents = function () { 18521 var _ = this; 18522 if (_.options.pauseOnHover) { 18523 _.$list.on('mouseenter.slick', $.proxy(_.interrupt, _, true)); 18524 _.$list.on('mouseleave.slick', $.proxy(_.interrupt, _, false)); 18525 } 18526 }; 18527 Slick.prototype.initializeEvents = function () { 18528 var _ = this; 18529 _.initArrowEvents(); 18530 _.initDotEvents(); 18531 _.initSlideEvents(); 18532 _.$list.on('touchstart.slick mousedown.slick', { 18533 action: 'start' 18534 }, _.swipeHandler); 18535 _.$list.on('touchmove.slick mousemove.slick', { 18536 action: 'move' 18537 }, _.swipeHandler); 18538 _.$list.on('touchend.slick mouseup.slick', { 18539 action: 'end' 18540 }, _.swipeHandler); 18541 _.$list.on('touchcancel.slick mouseleave.slick', { 18542 action: 'end' 18543 }, _.swipeHandler); 18544 _.$list.on('click.slick', _.clickHandler); 18545 $(document).on(_.visibilityChange, $.proxy(_.visibility, _)); 18546 if (_.options.accessibility === true) { 18547 _.$list.on('keydown.slick', _.keyHandler); 18548 } 18549 if (_.options.focusOnSelect === true) { 18550 $(_.$slideTrack).children().on('click.slick', _.selectHandler); 18551 } 18552 $(window).on('orientationchange.slick.slick-' + _.instanceUid, $.proxy(_.orientationChange, _)); 18553 $(window).on('resize.slick.slick-' + _.instanceUid, $.proxy(_.resize, _)); 18554 $('[draggable!=true]', _.$slideTrack).on('dragstart', _.preventDefault); 18555 $(window).on('load.slick.slick-' + _.instanceUid, _.setPosition); 18556 $(document).on('ready.slick.slick-' + _.instanceUid, _.setPosition); 18557 }; 18558 Slick.prototype.initUI = function () { 18559 var _ = this; 18560 if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { 18561 _.$prevArrow.show(); 18562 _.$nextArrow.show(); 18563 } 18564 if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { 18565 _.$dots.show(); 18566 } 18567 }; 18568 Slick.prototype.keyHandler = function (event) { 18569 var _ = this; 18570 //Dont slide if the cursor is inside the form fields and arrow keys are pressed 18571 if (!event.target.tagName.match('TEXTAREA|INPUT|SELECT')) { 18572 if (event.keyCode === 37 && _.options.accessibility === true) { 18573 _.changeSlide({ 18574 data: { 18575 message: _.options.rtl === true ? 'next' : 'previous' 18576 } 18577 }); 18578 } else if (event.keyCode === 39 && _.options.accessibility === true) { 18579 _.changeSlide({ 18580 data: { 18581 message: _.options.rtl === true ? 'previous' : 'next' 18582 } 18583 }); 18584 } 18585 } 18586 }; 18587 Slick.prototype.lazyLoad = function () { 18588 var _ = this, 18589 loadRange, 18590 cloneRange, 18591 rangeStart, 18592 rangeEnd; 18593 function loadImages(imagesScope) { 18594 $('img[data-lazy]', imagesScope).each(function () { 18595 var image = $(this), 18596 imageSource = $(this).attr('data-lazy'), 18597 imageToLoad = document.createElement('img'); 18598 imageToLoad.onload = function () { 18599 image.animate({ 18600 opacity: 0 18601 }, 100, function () { 18602 image.attr('src', imageSource).animate({ 18603 opacity: 1 18604 }, 200, function () { 18605 image.removeAttr('data-lazy').removeClass('slick-loading'); 18606 }); 18607 _.$slider.trigger('lazyLoaded', [_, image, imageSource]); 18608 }); 18609 }; 18610 imageToLoad.onerror = function () { 18611 image.removeAttr('data-lazy').removeClass('slick-loading').addClass('slick-lazyload-error'); 18612 _.$slider.trigger('lazyLoadError', [_, image, imageSource]); 18613 }; 18614 imageToLoad.src = imageSource; 18615 }); 18616 } 18617 if (_.options.centerMode === true) { 18618 if (_.options.infinite === true) { 18619 rangeStart = _.currentSlide + (_.options.slidesToShow / 2 + 1); 18620 rangeEnd = rangeStart + _.options.slidesToShow + 2; 18621 } else { 18622 rangeStart = Math.max(0, _.currentSlide - (_.options.slidesToShow / 2 + 1)); 18623 rangeEnd = 2 + (_.options.slidesToShow / 2 + 1) + _.currentSlide; 18624 } 18625 } else { 18626 rangeStart = _.options.infinite ? _.options.slidesToShow + _.currentSlide : _.currentSlide; 18627 rangeEnd = Math.ceil(rangeStart + _.options.slidesToShow); 18628 if (_.options.fade === true) { 18629 if (rangeStart > 0) rangeStart--; 18630 if (rangeEnd <= _.slideCount) rangeEnd++; 18631 } 18632 } 18633 loadRange = _.$slider.find('.slick-slide').slice(rangeStart, rangeEnd); 18634 loadImages(loadRange); 18635 if (_.slideCount <= _.options.slidesToShow) { 18636 cloneRange = _.$slider.find('.slick-slide'); 18637 loadImages(cloneRange); 18638 } else if (_.currentSlide >= _.slideCount - _.options.slidesToShow) { 18639 cloneRange = _.$slider.find('.slick-cloned').slice(0, _.options.slidesToShow); 18640 loadImages(cloneRange); 18641 } else if (_.currentSlide === 0) { 18642 cloneRange = _.$slider.find('.slick-cloned').slice(_.options.slidesToShow * -1); 18643 loadImages(cloneRange); 18644 } 18645 }; 18646 Slick.prototype.loadSlider = function () { 18647 var _ = this; 18648 _.setPosition(); 18649 _.$slideTrack.css({ 18650 opacity: 1 18651 }); 18652 _.$slider.removeClass('slick-loading'); 18653 _.initUI(); 18654 if (_.options.lazyLoad === 'progressive') { 18655 _.progressiveLazyLoad(); 18656 } 18657 }; 18658 Slick.prototype.next = Slick.prototype.slickNext = function () { 18659 var _ = this; 18660 _.changeSlide({ 18661 data: { 18662 message: 'next' 18663 } 18664 }); 18665 }; 18666 Slick.prototype.orientationChange = function () { 18667 var _ = this; 18668 _.checkResponsive(); 18669 _.setPosition(); 18670 }; 18671 Slick.prototype.pause = Slick.prototype.slickPause = function () { 18672 var _ = this; 18673 _.autoPlayClear(); 18674 _.paused = true; 18675 }; 18676 Slick.prototype.play = Slick.prototype.slickPlay = function () { 18677 var _ = this; 18678 _.autoPlay(); 18679 _.options.autoplay = true; 18680 _.paused = false;
18681 _.focussed = false; 18682 _.interrupted = false; 18683 }; 18684 Slick.prototype.postSlide = function (index) { 18685 var _ = this; 18686 if (!_.unslicked) { 18687 _.$slider.trigger('afterChange', [_, index]); 18688 _.animating = false; 18689 _.setPosition(); 18690 _.swipeLeft = null; 18691 if (_.options.autoplay) { 18692 _.autoPlay(); 18693 } 18694 if (_.options.accessibility === true) { 18695 _.initADA(); 18696 } 18697 } 18698 }; 18699 Slick.prototype.prev = Slick.prototype.slickPrev = function () { 18700 var _ = this; 18701 _.changeSlide({ 18702 data: { 18703 message: 'previous' 18704 } 18705 }); 18706 }; 18707 Slick.prototype.preventDefault = function (event) { 18708 event.preventDefault(); 18709 }; 18710 Slick.prototype.progressiveLazyLoad = function (tryCount) { 18711 tryCount = tryCount || 1; 18712 var _ = this, 18713 $imgsToLoad = $('img[data-lazy]', _.$slider), 18714 image, 18715 imageSource, 18716 imageToLoad; 18717 if ($imgsToLoad.length) { 18718 image = $imgsToLoad.first(); 18719 imageSource = image.attr('data-lazy'); 18720 imageToLoad = document.createElement('img'); 18721 imageToLoad.onload = function () { 18722 image.attr('src', imageSource).removeAttr('data-lazy').removeClass('slick-loading'); 18723 if (_.options.adaptiveHeight === true) { 18724 _.setPosition(); 18725 } 18726 _.$slider.trigger('lazyLoaded', [_, image, imageSource]); 18727 _.progressiveLazyLoad(); 18728 }; 18729 imageToLoad.onerror = function () { 18730 if (tryCount < 3) { 18731 /** 18732 * try to load the image 3 times, 18733 * leave a slight delay so we don't get 18734 * servers blocking the request. 18735 */ 18736 setTimeout(function () { 18737 _.progressiveLazyLoad(tryCount + 1); 18738 }, 500); 18739 } else { 18740 image.removeAttr('data-lazy').removeClass('slick-loading').addClass('slick-lazyload-error'); 18741 _.$slider.trigger('lazyLoadError', [_, image, imageSource]); 18742 _.progressiveLazyLoad(); 18743 } 18744 }; 18745 imageToLoad.src = imageSource; 18746 } else { 18747 _.$slider.trigger('allImagesLoaded', [_]); 18748 } 18749 }; 18750 Slick.prototype.refresh = function (initializing) { 18751 var _ = this, 18752 currentSlide, 18753 lastVisibleIndex; 18754 lastVisibleIndex = _.slideCount - _.options.slidesToShow; 18755 18756 // in non-infinite sliders, we don't want to go past the 18757 // last visible index. 18758 if (!_.options.infinite && _.currentSlide > lastVisibleIndex) { 18759 _.currentSlide = lastVisibleIndex; 18760 } 18761 18762 // if less slides than to show, go to start. 18763 if (_.slideCount <= _.options.slidesToShow) { 18764 _.currentSlide = 0; 18765 } 18766 currentSlide = _.currentSlide; 18767 _.destroy(true); 18768 $.extend(_, _.initials, { 18769 currentSlide: currentSlide 18770 }); 18771 _.init(); 18772 if (!initializing) { 18773 _.changeSlide({ 18774 data: { 18775 message: 'index', 18776 index: currentSlide 18777 } 18778 }, false); 18779 } 18780 }; 18781 Slick.prototype.registerBreakpoints = function () { 18782 var _ = this, 18783 breakpoint, 18784 currentBreakpoint, 18785 l, 18786 responsiveSettings = _.options.responsive || null; 18787 if ($.type(responsiveSettings) === 'array' && responsiveSettings.length) { 18788 _.respondTo = _.options.respondTo || 'window'; 18789 for (breakpoint in responsiveSettings) { 18790 l = _.breakpoints.length - 1; 18791 currentBreakpoint = responsiveSettings[breakpoint].breakpoint; 18792 if (responsiveSettings.hasOwnProperty(breakpoint)) { 18793 // loop through the breakpoints and cut out any existing 18794 // ones with the same breakpoint number, we don't want dupes. 18795 while (l >= 0) { 18796 if (_.breakpoints[l] && _.breakpoints[l] === currentBreakpoint) { 18797 _.breakpoints.splice(l, 1); 18798 } 18799 l--; 18800 } 18801 _.breakpoints.push(currentBreakpoint); 18802 _.breakpointSettings[currentBreakpoint] = responsiveSettings[breakpoint].settings; 18803 } 18804 } 18805 _.breakpoints.sort(function (a, b) { 18806 return _.options.mobileFirst ? a - b : b - a; 18807 }); 18808 } 18809 }; 18810 Slick.prototype.reinit = function () { 18811 var _ = this; 18812 _.$slides = _.$slideTrack.children(_.options.slide).addClass('slick-slide'); 18813 _.slideCount = _.$slides.length; 18814 if (_.currentSlide >= _.slideCount && _.currentSlide !== 0) { 18815 _.currentSlide = _.currentSlide - _.options.slidesToScroll; 18816 } 18817 if (_.slideCount <= _.options.slidesToShow) { 18818 _.currentSlide = 0; 18819 } 18820 _.registerBreakpoints(); 18821 _.setProps(); 18822 _.setupInfinite(); 18823 _.buildArrows(); 18824 _.updateArrows(); 18825 _.initArrowEvents(); 18826 _.buildDots(); 18827 _.updateDots(); 18828 _.initDotEvents(); 18829 _.cleanUpSlideEvents(); 18830 _.initSlideEvents(); 18831 _.checkResponsive(false, true); 18832 if (_.options.focusOnSelect === true) { 18833 $(_.$slideTrack).children().on('click.slick', _.selectHandler); 18834 } 18835 _.setSlideClasses(typeof _.currentSlide === 'number' ? _.currentSlide : 0); 18836 _.setPosition(); 18837 _.focusHandler(); 18838 _.paused = !_.options.autoplay; 18839 _.autoPlay(); 18840 _.$slider.trigger('reInit', [_]); 18841 }; 18842 Slick.prototype.resize = function () { 18843 var _ = this; 18844 if ($(window).width() !== _.windowWidth) { 18845 clearTimeout(_.windowDelay); 18846 _.windowDelay = window.setTimeout(function () { 18847 _.windowWidth = $(window).width(); 18848 _.checkResponsive(); 18849 if (!_.unslicked) { 18850 _.setPosition(); 18851 } 18852 }, 50); 18853 } 18854 }; 18855 Slick.prototype.removeSlide = Slick.prototype.slickRemove = function (index, removeBefore, removeAll) { 18856 var _ = this; 18857 if (typeof index === 'boolean') { 18858 removeBefore = index; 18859 index = removeBefore === true ? 0 : _.slideCount - 1; 18860 } else { 18861 index = removeBefore === true ? --index : index; 18862 } 18863 if (_.slideCount < 1 || index < 0 || index > _.slideCount - 1) { 18864 return false;
18865 } 18866 _.unload(); 18867 if (removeAll === true) { 18868 _.$slideTrack.children().remove(); 18869 } else { 18870 _.$slideTrack.children(this.options.slide).eq(index).remove(); 18871 } 18872 _.$slides = _.$slideTrack.children(this.options.slide); 18873 _.$slideTrack.children(this.options.slide).detach(); 18874 _.$slideTrack.append(_.$slides); 18875 _.$slidesCache = _.$slides; 18876 _.reinit(); 18877 }; 18878 Slick.prototype.setCSS = function (position) { 18879 var _ = this, 18880 positionProps = {}, 18881 x, 18882 y; 18883 if (_.options.rtl === true) { 18884 position = -position; 18885 } 18886 x = _.positionProp == 'left' ? Math.ceil(position) + 'px' : '0px'; 18887 y = _.positionProp == 'top' ? Math.ceil(position) + 'px' : '0px'; 18888 positionProps[_.positionProp] = position; 18889 if (_.transformsEnabled === false) { 18890 _.$slideTrack.css(positionProps); 18891 } else { 18892 positionProps = {}; 18893 if (_.cssTransitions === false) { 18894 positionProps[_.animType] = 'translate(' + x + ', ' + y + ')'; 18895 _.$slideTrack.css(positionProps); 18896 } else { 18897 positionProps[_.animType] = 'translate3d(' + x + ', ' + y + ', 0px)'; 18898 _.$slideTrack.css(positionProps); 18899 } 18900 } 18901 }; 18902 Slick.prototype.setDimensions = function () { 18903 var _ = this; 18904 if (_.options.vertical === false) { 18905 if (_.options.centerMode === true) { 18906 _.$list.css({ 18907 padding: '0px ' + _.options.centerPadding 18908 }); 18909 } 18910 } else { 18911 _.$list.height(_.$slides.first().outerHeight(true) * _.options.slidesToShow); 18912 if (_.options.centerMode === true) { 18913 _.$list.css({ 18914 padding: _.options.centerPadding + ' 0px' 18915 }); 18916 } 18917 } 18918 _.listWidth = _.$list.width(); 18919 _.listHeight = _.$list.height(); 18920 if (_.options.vertical === false && _.options.variableWidth === false) { 18921 _.slideWidth = Math.ceil(_.listWidth / _.options.slidesToShow); 18922 _.$slideTrack.width(Math.ceil(_.slideWidth * _.$slideTrack.children('.slick-slide').length)); 18923 } else if (_.options.variableWidth === true) { 18924 _.$slideTrack.width(5000 * _.slideCount); 18925 } else { 18926 _.slideWidth = Math.ceil(_.listWidth); 18927 _.$slideTrack.height(Math.ceil(_.$slides.first().outerHeight(true) * _.$slideTrack.children('.slick-slide').length)); 18928 } 18929 var offset = _.$slides.first().outerWidth(true) - _.$slides.first().width(); 18930 if (_.options.variableWidth === false) _.$slideTrack.children('.slick-slide').width(_.slideWidth - offset); 18931 }; 18932 Slick.prototype.setFade = function () { 18933 var _ = this, 18934 targetLeft; 18935 _.$slides.each(function (index, element) { 18936 targetLeft = _.slideWidth * index * -1; 18937 if (_.options.rtl === true) { 18938 $(element).css({ 18939 position: 'relative', 18940 right: targetLeft, 18941 top: 0, 18942 zIndex: _.options.zIndex - 2, 18943 opacity: 0 18944 }); 18945 } else { 18946 $(element).css({ 18947 position: 'relative', 18948 left: targetLeft, 18949 top: 0, 18950 zIndex: _.options.zIndex - 2, 18951 opacity: 0 18952 }); 18953 } 18954 }); 18955 _.$slides.eq(_.currentSlide).css({ 18956 zIndex: _.options.zIndex - 1, 18957 opacity: 1 18958 }); 18959 }; 18960 Slick.prototype.setHeight = function () { 18961 var _ = this; 18962 if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) { 18963 var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true); 18964 _.$list.css('height', targetHeight); 18965 } 18966 }; 18967 Slick.prototype.setOption = Slick.prototype.slickSetOption = function () { 18968 /** 18969 * accepts arguments in format of: 18970 * 18971 * - for changing a single option's value: 18972 * .slick("setOption", option, value, refresh ) 18973 * 18974 * - for changing a set of responsive options: 18975 * .slick("setOption", 'responsive', [{}, ...], refresh ) 18976 * 18977 * - for updating multiple values at once (not responsive) 18978 * .slick("setOption", { 'option': value, ... }, refresh ) 18979 */ 18980 18981 var _ = this, 18982 l, 18983 item, 18984 option, 18985 value, 18986 refresh = false, 18987 type; 18988 if ($.type(arguments[0]) === 'object') { 18989 option = arguments[0]; 18990 refresh = arguments[1]; 18991 type = 'multiple'; 18992 } else if ($.type(arguments[0]) === 'string') { 18993 option = arguments[0]; 18994 value = arguments[1]; 18995 refresh = arguments[2]; 18996 if (arguments[0] === 'responsive' && $.type(arguments[1]) === 'array') { 18997 type = 'responsive'; 18998 } else if (typeof arguments[1] !== 'undefined') { 18999 type = 'single'; 19000 } 19001 } 19002 if (type === 'single') {
19003 _.options[option] = value; 19004 } else if (type === 'multiple') { 19005 $.each(option, function (opt, val) { 19006 _.options[opt] = val; 19007 }); 19008 } else if (type === 'responsive') { 19009 for (item in value) { 19010 if ($.type(_.options.responsive) !== 'array') { 19011 _.options.responsive = [value[item]]; 19012 } else { 19013 l = _.options.responsive.length - 1; 19014 19015 // loop through the responsive object and splice out duplicates. 19016 while (l >= 0) { 19017 if (_.options.responsive[l].breakpoint === value[item].breakpoint) { 19018 _.options.responsive.splice(l, 1); 19019 } 19020 l--; 19021 } 19022 _.options.responsive.push(value[item]); 19023 } 19024 } 19025 } 19026 if (refresh) { 19027 _.unload(); 19028 _.reinit(); 19029 } 19030 }; 19031 Slick.prototype.setPosition = function () { 19032 var _ = this; 19033 _.setDimensions(); 19034 _.setHeight(); 19035 if (_.options.fade === false) { 19036 _.setCSS(_.getLeft(_.currentSlide)); 19037 } else { 19038 _.setFade(); 19039 } 19040 _.$slider.trigger('setPosition', [_]); 19041 }; 19042 Slick.prototype.setProps = function () { 19043 var _ = this, 19044 bodyStyle = document.body.style; 19045 _.positionProp = _.options.vertical === true ? 'top' : 'left'; 19046 if (_.positionProp === 'top') { 19047 _.$slider.addClass('slick-vertical'); 19048 } else { 19049 _.$slider.removeClass('slick-vertical'); 19050 } 19051 if (bodyStyle.WebkitTransition !== undefined || bodyStyle.MozTransition !== undefined || bodyStyle.msTransition !== undefined) { 19052 if (_.options.useCSS === true) { 19053 _.cssTransitions = true; 19054 } 19055 } 19056 if (_.options.fade) { 19057 if (typeof _.options.zIndex === 'number') { 19058 if (_.options.zIndex < 3) { 19059 _.options.zIndex = 3; 19060 } 19061 } else { 19062 _.options.zIndex = _.defaults.zIndex; 19063 } 19064 } 19065 if (bodyStyle.OTransform !== undefined) { 19066 _.animType = 'OTransform'; 19067 _.transformType = '-o-transform'; 19068 _.transitionType = 'OTransition'; 19069 if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false;
19070 } 19071 if (bodyStyle.MozTransform !== undefined) { 19072 _.animType = 'MozTransform'; 19073 _.transformType = '-moz-transform'; 19074 _.transitionType = 'MozTransition'; 19075 if (bodyStyle.perspectiveProperty === undefined && bodyStyle.MozPerspective === undefined) _.animType = false; 19076 } 19077 if (bodyStyle.webkitTransform !== undefined) { 19078 _.animType = 'webkitTransform'; 19079 _.transformType = '-webkit-transform'; 19080 _.transitionType = 'webkitTransition'; 19081 if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false; 19082 } 19083 if (bodyStyle.msTransform !== undefined) { 19084 _.animType = 'msTransform'; 19085 _.transformType = '-ms-transform'; 19086 _.transitionType = 'msTransition'; 19087 if (bodyStyle.msTransform === undefined) _.animType = false; 19088 } 19089 if (bodyStyle.transform !== undefined && _.animType !== false) { 19090 _.animType = 'transform'; 19091 _.transformType = 'transform'; 19092 _.transitionType = 'transition'; 19093 } 19094 _.transformsEnabled = _.options.useTransform && _.animType !== null && _.animType !== false; 19095 }; 19096 Slick.prototype.setSlideClasses = function (index) { 19097 var _ = this, 19098 centerOffset, 19099 allSlides, 19100 indexOffset, 19101 remainder; 19102 allSlides = _.$slider.find('.slick-slide').removeClass('slick-active slick-center slick-current').attr('aria-hidden', 'true'); 19103 _.$slides.eq(index).addClass('slick-current'); 19104 if (_.options.centerMode === true) { 19105 centerOffset = Math.floor(_.options.slidesToShow / 2); 19106 if (_.options.infinite === true) { 19107 if (index >= centerOffset && index <= _.slideCount - 1 - centerOffset) { 19108 _.$slides.slice(index - centerOffset, index + centerOffset + 1).addClass('slick-active').attr('aria-hidden', 'false'); 19109 } else { 19110 indexOffset = _.options.slidesToShow + index; 19111 allSlides.slice(indexOffset - centerOffset + 1, indexOffset + centerOffset + 2).addClass('slick-active').attr('aria-hidden', 'false'); 19112 } 19113 if (index === 0) { 19114 allSlides.eq(allSlides.length - 1 - _.options.slidesToShow).addClass('slick-center'); 19115 } else if (index === _.slideCount - 1) { 19116 allSlides.eq(_.options.slidesToShow).addClass('slick-center'); 19117 } 19118 } 19119 _.$slides.eq(index).addClass('slick-center'); 19120 } else { 19121 if (index >= 0 && index <= _.slideCount - _.options.slidesToShow) { 19122 _.$slides.slice(index, index + _.options.slidesToShow).addClass('slick-active').attr('aria-hidden', 'false'); 19123 } else if (allSlides.length <= _.options.slidesToShow) { 19124 allSlides.addClass('slick-active').attr('aria-hidden', 'false'); 19125 } else { 19126 remainder = _.slideCount % _.options.slidesToShow; 19127 indexOffset = _.options.infinite === true ? _.options.slidesToShow + index : index; 19128 if (_.options.slidesToShow == _.options.slidesToScroll && _.slideCount - index < _.options.slidesToShow) { 19129 allSlides.slice(indexOffset - (_.options.slidesToShow - remainder), indexOffset + remainder).addClass('slick-active').attr('aria-hidden', 'false'); 19130 } else { 19131 allSlides.slice(indexOffset, indexOffset + _.options.slidesToShow).addClass('slick-active').attr('aria-hidden', 'false'); 19132 } 19133 } 19134 } 19135 if (_.options.lazyLoad === 'ondemand') { 19136 _.lazyLoad(); 19137 } 19138 }; 19139 Slick.prototype.setupInfinite = function () { 19140 var _ = this, 19141 i, 19142 slideIndex, 19143 infiniteCount; 19144 if (_.options.fade === true) { 19145 _.options.centerMode = false; 19146 } 19147 if (_.options.infinite === true && _.options.fade === false) { 19148 slideIndex = null; 19149 if (_.slideCount > _.options.slidesToShow) { 19150 if (_.options.centerMode === true) { 19151 infiniteCount = _.options.slidesToShow + 1; 19152 } else { 19153 infiniteCount = _.options.slidesToShow; 19154 } 19155 for (i = _.slideCount; i > _.slideCount - infiniteCount; i -= 1) { 19156 slideIndex = i - 1; 19157 $(_.$slides[slideIndex]).clone(true).attr('id', '').attr('data-slick-index', slideIndex - _.slideCount).prependTo(_.$slideTrack).addClass('slick-cloned'); 19158 } 19159 for (i = 0; i < infiniteCount; i += 1) { 19160 slideIndex = i; 19161 $(_.$slides[slideIndex]).clone(true).attr('id', '').attr('data-slick-index', slideIndex + _.slideCount).appendTo(_.$slideTrack).addClass('slick-cloned'); 19162 } 19163 _.$slideTrack.find('.slick-cloned').find('[id]').each(function () { 19164 $(this).attr('id', ''); 19165 }); 19166 } 19167 } 19168 }; 19169 Slick.prototype.interrupt = function (toggle) { 19170 var _ = this; 19171 if (!toggle) { 19172 _.autoPlay(); 19173 } 19174 _.interrupted = toggle; 19175 }; 19176 Slick.prototype.selectHandler = function (event) { 19177 var _ = this; 19178 var targetElement = $(event.target).is('.slick-slide') ? $(event.target) : $(event.target).parents('.slick-slide'); 19179 var index = parseInt(targetElement.attr('data-slick-index')); 19180 if (!index) index = 0; 19181 if (_.slideCount <= _.options.slidesToShow) { 19182 _.setSlideClasses(index); 19183 _.asNavFor(index); 19184 return; 19185 } 19186 _.slideHandler(index); 19187 }; 19188 Slick.prototype.slideHandler = function (index, sync, dontAnimate) { 19189 var targetSlide, 19190 animSlide, 19191 oldSlide, 19192 slideLeft, 19193 targetLeft = null, 19194 _ = this, 19195 navTarget; 19196 sync = sync || false; 19197 if (_.animating === true && _.options.waitForAnimate === true) { 19198 return; 19199 } 19200 if (_.options.fade === true && _.currentSlide === index) { 19201 return; 19202 } 19203 if (_.slideCount <= _.options.slidesToShow) { 19204 return; 19205 } 19206 if (sync === false) { 19207 _.asNavFor(index); 19208 } 19209 targetSlide = index; 19210 targetLeft = _.getLeft(targetSlide); 19211 slideLeft = _.getLeft(_.currentSlide); 19212 _.currentLeft = _.swipeLeft === null ? slideLeft : _.swipeLeft; 19213 if (_.options.infinite === false && _.options.centerMode === false && (index < 0 || index > _.getDotCount() * _.options.slidesToScroll)) { 19214 if (_.options.fade === false) { 19215 targetSlide = _.currentSlide; 19216 if (dontAnimate !== true) { 19217 _.animateSlide(slideLeft, function () { 19218 _.postSlide(targetSlide); 19219 }); 19220 } else { 19221 _.postSlide(targetSlide); 19222 } 19223 } 19224 return; 19225 } else if (_.options.infinite === false && _.options.centerMode === true && (index < 0 || index > _.slideCount - _.options.slidesToScroll)) { 19226 if (_.options.fade === false) { 19227 targetSlide = _.currentSlide; 19228 if (dontAnimate !== true) { 19229 _.animateSlide(slideLeft, function () { 19230 _.postSlide(targetSlide); 19231 }); 19232 } else { 19233 _.postSlide(targetSlide); 19234 } 19235 } 19236 return; 19237 } 19238 if (_.options.autoplay) { 19239 clearInterval(_.autoPlayTimer); 19240 }
19241 if (targetSlide < 0) { 19242 if (_.slideCount % _.options.slidesToScroll !== 0) { 19243 animSlide = _.slideCount - _.slideCount % _.options.slidesToScroll; 19244 } else { 19245 animSlide = _.slideCount + targetSlide; 19246 } 19247 } else if (targetSlide >= _.slideCount) { 19248 if (_.slideCount % _.options.slidesToScroll !== 0) { 19249 animSlide = 0; 19250 } else { 19251 animSlide = targetSlide - _.slideCount; 19252 } 19253 } else { 19254 animSlide = targetSlide; 19255 } 19256 _.animating = true; 19257 _.$slider.trigger('beforeChange', [_, _.currentSlide, animSlide]); 19258 oldSlide = _.currentSlide; 19259 _.currentSlide = animSlide; 19260 _.setSlideClasses(_.currentSlide); 19261 if (_.options.asNavFor) { 19262 navTarget = _.getNavTarget(); 19263 navTarget = navTarget.slick('getSlick'); 19264 if (navTarget.slideCount <= navTarget.options.slidesToShow) { 19265 navTarget.setSlideClasses(_.currentSlide); 19266 } 19267 } 19268 _.updateDots(); 19269 _.updateArrows(); 19270 if (_.options.fade === true) { 19271 if (dontAnimate !== true) { 19272 _.fadeSlideOut(oldSlide); 19273 _.fadeSlide(animSlide, function () { 19274 _.postSlide(animSlide); 19275 }); 19276 } else { 19277 _.postSlide(animSlide); 19278 } 19279 _.animateHeight(); 19280 return; 19281 } 19282 if (dontAnimate !== true) { 19283 _.animateSlide(targetLeft, function () { 19284 _.postSlide(animSlide); 19285 }); 19286 } else { 19287 _.postSlide(animSlide); 19288 } 19289 }; 19290 Slick.prototype.startLoad = function () { 19291 var _ = this; 19292 if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) { 19293 _.$prevArrow.hide(); 19294 _.$nextArrow.hide(); 19295 } 19296 if (_.options.dots === true && _.slideCount > _.options.slidesToShow) { 19297 _.$dots.hide(); 19298 } 19299 _.$slider.addClass('slick-loading'); 19300 }; 19301 Slick.prototype.swipeDirection = function () { 19302 var xDist, 19303 yDist, 19304 r, 19305 swipeAngle, 19306 _ = this; 19307 xDist = _.touchObject.startX - _.touchObject.curX; 19308 yDist = _.touchObject.startY - _.touchObject.curY; 19309 r = Math.atan2(yDist, xDist); 19310 swipeAngle = Math.round(r * 180 / Math.PI); 19311 if (swipeAngle < 0) { 19312 swipeAngle = 360 - Math.abs(swipeAngle); 19313 } 19314 if (swipeAngle <= 45 && swipeAngle >= 0) { 19315 return _.options.rtl === false ? 'left' : 'right'; 19316 } 19317 if (swipeAngle <= 360 && swipeAngle >= 315) { 19318 return _.options.rtl === false ? 'left' : 'right'; 19319 } 19320 if (swipeAngle >= 135 && swipeAngle <= 225) { 19321 return _.options.rtl === false ? 'right' : 'left'; 19322 } 19323 if (_.options.verticalSwiping === true) { 19324 if (swipeAngle >= 35 && swipeAngle <= 135) { 19325 return 'down'; 19326 } else { 19327 return 'up'; 19328 } 19329 } 19330 return 'vertical'; 19331 }; 19332 Slick.prototype.swipeEnd = function (event) { 19333 var _ = this, 19334 slideCount, 19335 direction; 19336 _.dragging = false; 19337 _.interrupted = false; 19338 _.shouldClick = _.touchObject.swipeLength > 10 ? false : true; 19339 if (_.touchObject.curX === undefined) { 19340 return false; 19341 } 19342 if (_.touchObject.edgeHit === true) { 19343 _.$slider.trigger('edge', [_, _.swipeDirection()]); 19344 } 19345 if (_.touchObject.swipeLength >= _.touchObject.minSwipe) { 19346 direction = _.swipeDirection(); 19347 switch (direction) { 19348 case 'left': 19349 case 'down': 19350 slideCount = _.options.swipeToSlide ? _.checkNavigable(_.currentSlide + _.getSlideCount()) : _.currentSlide + _.getSlideCount(); 19351 _.currentDirection = 0; 19352 break; 19353 case 'right': 19354 case 'up': 19355 slideCount = _.options.swipeToSlide ? _.checkNavigable(_.currentSlide - _.getSlideCount()) : _.currentSlide - _.getSlideCount(); 19356 _.currentDirection = 1; 19357 break; 19358 default: 19359 } 19360 if (direction != 'vertical') { 19361 _.slideHandler(slideCount); 19362 _.touchObject = {}; 19363 _.$slider.trigger('swipe', [_, direction]); 19364 } 19365 } else { 19366 if (_.touchObject.startX !== _.touchObject.curX) { 19367 _.slideHandler(_.currentSlide); 19368 _.touchObject = {}; 19369 } 19370 } 19371 }; 19372 Slick.prototype.swipeHandler = function (event) { 19373 var _ = this; 19374 if (_.options.swipe === false || 'ontouchend' in document && _.options.swipe === false) { 19375 return; 19376 } else if (_.options.draggable === false && event.type.indexOf('mouse') !== -1) { 19377 return; 19378 } 19379 _.touchObject.fingerCount = event.originalEvent && event.originalEvent.touches !== undefined ? event.originalEvent.touches.length : 1; 19380 _.touchObject.minSwipe = _.listWidth / _.options.touchThreshold; 19381 if (_.options.verticalSwiping === true) { 19382 _.touchObject.minSwipe = _.listHeight / _.options.touchThreshold; 19383 } 19384 switch (event.data.action) { 19385 case 'start': 19386 _.swipeStart(event); 19387 break; 19388 case 'move': 19389 _.swipeMove(event); 19390 break; 19391 case 'end': 19392 _.swipeEnd(event); 19393 break; 19394 } 19395 }; 19396 Slick.prototype.swipeMove = function (event) { 19397 var _ = this, 19398 edgeWasHit = false, 19399 curLeft, 19400 swipeDirection, 19401 swipeLength, 19402 positionOffset, 19403 touches; 19404 touches = event.originalEvent !== undefined ? event.originalEvent.touches : null; 19405 if (!_.dragging || touches && touches.length !== 1) { 19406 return false;
19407 } 19408 curLeft = _.getLeft(_.currentSlide); 19409 _.touchObject.curX = touches !== undefined ? touches[0].pageX : event.clientX; 19410 _.touchObject.curY = touches !== undefined ? touches[0].pageY : event.clientY; 19411 _.touchObject.swipeLength = Math.round(Math.sqrt(Math.pow(_.touchObject.curX - _.touchObject.startX, 2))); 19412 if (_.options.verticalSwiping === true) { 19413 _.touchObject.swipeLength = Math.round(Math.sqrt(Math.pow(_.touchObject.curY - _.touchObject.startY, 2))); 19414 } 19415 swipeDirection = _.swipeDirection(); 19416 if (swipeDirection === 'vertical') { 19417 return; 19418 } 19419 if (event.originalEvent !== undefined && _.touchObject.swipeLength > 4) { 19420 event.preventDefault(); 19421 } 19422 positionOffset = (_.options.rtl === false ? 1 : -1) * (_.touchObject.curX > _.touchObject.startX ? 1 : -1); 19423 if (_.options.verticalSwiping === true) { 19424 positionOffset = _.touchObject.curY > _.touchObject.startY ? 1 : -1; 19425 } 19426 swipeLength = _.touchObject.swipeLength; 19427 _.touchObject.edgeHit = false; 19428 if (_.options.infinite === false) { 19429 if (_.currentSlide === 0 && swipeDirection === 'right' || _.currentSlide >= _.getDotCount() && swipeDirection === 'left') { 19430 swipeLength = _.touchObject.swipeLength * _.options.edgeFriction; 19431 _.touchObject.edgeHit = true; 19432 } 19433 } 19434 if (_.options.vertical === false) { 19435 _.swipeLeft = curLeft + swipeLength * positionOffset; 19436 } else { 19437 _.swipeLeft = curLeft + swipeLength * (_.$list.height() / _.listWidth) * positionOffset; 19438 } 19439 if (_.options.verticalSwiping === true) { 19440 _.swipeLeft = curLeft + swipeLength * positionOffset; 19441 } 19442 if (_.options.fade === true || _.options.touchMove === false) { 19443 return false; 19444 } 19445 if (_.animating === true) { 19446 _.swipeLeft = null; 19447 return false; 19448 } 19449 _.setCSS(_.swipeLeft); 19450 }; 19451 Slick.prototype.swipeStart = function (event) { 19452 var _ = this, 19453 touches; 19454 _.interrupted = true; 19455 if (_.touchObject.fingerCount !== 1 || _.slideCount <= _.options.slidesToShow) { 19456 _.touchObject = {}; 19457 return false; 19458 } 19459 if (event.originalEvent !== undefined && event.originalEvent.touches !== undefined) { 19460 touches = event.originalEvent.touches[0]; 19461 } 19462 _.touchObject.startX = _.touchObject.curX = touches !== undefined ? touches.pageX : event.clientX; 19463 _.touchObject.startY = _.touchObject.curY = touches !== undefined ? touches.pageY : event.clientY; 19464 _.dragging = true; 19465 }; 19466 Slick.prototype.unfilterSlides = Slick.prototype.slickUnfilter = function () { 19467 var _ = this; 19468 if (_.$slidesCache !== null) { 19469 _.unload(); 19470 _.$slideTrack.children(this.options.slide).detach(); 19471 _.$slidesCache.appendTo(_.$slideTrack); 19472 _.reinit(); 19473 } 19474 }; 19475 Slick.prototype.unload = function () { 19476 var _ = this; 19477 $('.slick-cloned', _.$slider).remove(); 19478 if (_.$dots) { 19479 _.$dots.remove(); 19480 } 19481 if (_.$prevArrow && _.htmlExpr.test(_.options.prevArrow)) { 19482 _.$prevArrow.remove(); 19483 } 19484 if (_.$nextArrow && _.htmlExpr.test(_.options.nextArrow)) { 19485 _.$nextArrow.remove(); 19486 } 19487 _.$slides.removeClass('slick-slide slick-active slick-visible slick-current').attr('aria-hidden', 'true').css('width', ''); 19488 }; 19489 Slick.prototype.unslick = function (fromBreakpoint) { 19490 var _ = this; 19491 _.$slider.trigger('unslick', [_, fromBreakpoint]); 19492 _.destroy(); 19493 }; 19494 Slick.prototype.updateArrows = function () { 19495 var _ = this, 19496 centerOffset; 19497 centerOffset = Math.floor(_.options.slidesToShow / 2); 19498 if (_.options.arrows === true && _.slideCount > _.options.slidesToShow && !_.options.infinite) { 19499 _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false'); 19500 _.$nextArrow.removeClass('slick-disabled').attr('aria-disabled', 'false'); 19501 if (_.currentSlide === 0) { 19502 _.$prevArrow.addClass('slick-disabled').attr('aria-disabled', 'true'); 19503 _.$nextArrow.removeClass('slick-disabled').attr('aria-disabled', 'false'); 19504 } else if (_.currentSlide >= _.slideCount - _.options.slidesToShow && _.options.centerMode === false) { 19505 _.$nextArrow.addClass('slick-disabled').attr('aria-disabled', 'true'); 19506 _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false'); 19507 } else if (_.currentSlide >= _.slideCount - 1 && _.options.centerMode === true) { 19508 _.$nextArrow.addClass('slick-disabled').attr('aria-disabled', 'true'); 19509 _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false'); 19510 } 19511 } 19512 }; 19513 Slick.prototype.updateDots = function () { 19514 var _ = this; 19515 if (_.$dots !== null) { 19516 _.$dots.find('li').removeClass('slick-active').attr('aria-hidden', 'true'); 19517 _.$dots.find('li').eq(Math.floor(_.currentSlide / _.options.slidesToScroll)).addClass('slick-active').attr('aria-hidden', 'false'); 19518 } 19519 }; 19520 Slick.prototype.visibility = function () { 19521 var _ = this; 19522 if (_.options.autoplay) { 19523 if (document[_.hidden]) { 19524 _.interrupted = true; 19525 } else { 19526 _.interrupted = false;
19527 } 19528 } 19529 }; 19530 $.fn.slick = function () { 19531 var _ = this, 19532 opt = arguments[0], 19533 args = Array.prototype.slice.call(arguments, 1), 19534 l = _.length, 19535 i, 19536 ret; 19537 for (i = 0; i < l; i++) { 19538 if (_typeof(opt) == 'object' || typeof opt == 'undefined') _[i].slick = new Slick(_[i], opt);else ret = _[i].slick[opt].apply(_[i].slick, args); 19539 if (typeof ret != 'undefined') return ret; 19540 } 19541 return _; 19542 }; 19543}); 19544 19545}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 19546},{}],8:[function(require,module,exports){ 19547(function (global){(function (){ 19548"use strict"; 19549 19550function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 19551(function (global, factory) { 19552 (typeof exports === "undefined" ? "undefined" : _typeof(exports)) === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define('underscore', factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, function () { 19553 var current = global._; 19554 var exports = global._ = factory(); 19555 exports.noConflict = function () { 19556 global._ = current; 19557 return exports; 19558 }; 19559 }()); 19560})(void 0, function () { 19561 // Underscore.js 1.13.7 19562 // https://underscorejs.org 19563 // (c) 2009-2024 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors 19564 // Underscore may be freely distributed under the MIT license. 19565 19566 // Current version. 19567 var VERSION = '1.13.7'; 19568 19569 // Establish the root object, `window` (`self`) in the browser, `global` 19570 // on the server, or `this` in some virtual machines. We use `self` 19571 // instead of `window` for `WebWorker` support. 19572 var root = (typeof self === "undefined" ? "undefined" : _typeof(self)) == 'object' && self.self === self && self || (typeof global === "undefined" ? "undefined" : _typeof(global)) == 'object' && global.global === global && global || Function('return this')() || {}; 19573 19574 // Save bytes in the minified (but not gzipped) version: 19575 var ArrayProto = Array.prototype, 19576 ObjProto = Object.prototype; 19577 var SymbolProto = typeof Symbol !== 'undefined' ? Symbol.prototype : null; 19578 19579 // Create quick reference variables for speed access to core prototypes. 19580 var push = ArrayProto.push, 19581 slice = ArrayProto.slice, 19582 toString = ObjProto.toString, 19583 hasOwnProperty = ObjProto.hasOwnProperty; 19584 19585 // Modern feature detection. 19586 var supportsArrayBuffer = typeof ArrayBuffer !== 'undefined', 19587 supportsDataView = typeof DataView !== 'undefined'; 19588 19589 // All **ECMAScript 5+** native function implementations that we hope to use 19590 // are declared here. 19591 var nativeIsArray = Array.isArray, 19592 nativeKeys = Object.keys, 19593 nativeCreate = Object.create, 19594 nativeIsView = supportsArrayBuffer && ArrayBuffer.isView; 19595 19596 // Create references to these builtin functions because we override them. 19597 var _isNaN = isNaN, 19598 _isFinite = isFinite; 19599 19600 // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. 19601 var hasEnumBug = !{ 19602 toString: null 19603 }.propertyIsEnumerable('toString'); 19604 var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; 19605 19606 // The largest integer that can be represented exactly. 19607 var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; 19608 19609 // Some functions take a variable number of arguments, or a few expected 19610 // arguments at the beginning and then a variable number of values to operate 19611 // on. This helper accumulates all remaining arguments past the function’s 19612 // argument length (or an explicit `startIndex`), into an array that becomes 19613 // the last argument. Similar to ES6’s "rest parameter". 19614 function restArguments(func, startIndex) { 19615 startIndex = startIndex == null ? func.length - 1 : +startIndex; 19616 return function () { 19617 var length = Math.max(arguments.length - startIndex, 0), 19618 rest = Array(length), 19619 index = 0; 19620 for (; index < length; index++) { 19621 rest[index] = arguments[index + startIndex]; 19622 } 19623 switch (startIndex) { 19624 case 0: 19625 return func.call(this, rest); 19626 case 1: 19627 return func.call(this, arguments[0], rest); 19628 case 2: 19629 return func.call(this, arguments[0], arguments[1], rest); 19630 } 19631 var args = Array(startIndex + 1); 19632 for (index = 0; index < startIndex; index++) { 19633 args[index] = arguments[index]; 19634 } 19635 args[startIndex] = rest; 19636 return func.apply(this, args); 19637 }; 19638 } 19639 19640 // Is a given variable an object? 19641 function isObject(obj) { 19642 var type = _typeof(obj); 19643 return type === 'function' || type === 'object' && !!obj; 19644 } 19645 19646 // Is a given value equal to null? 19647 function isNull(obj) { 19648 return obj === null; 19649 } 19650 19651 // Is a given variable undefined? 19652 function isUndefined(obj) { 19653 return obj === void 0; 19654 } 19655 19656 // Is a given value a boolean? 19657 function isBoolean(obj) { 19658 return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; 19659 } 19660 19661 // Is a given value a DOM element? 19662 function isElement(obj) { 19663 return !!(obj && obj.nodeType === 1); 19664 } 19665 19666 // Internal function for creating a `toString`-based type tester. 19667 function tagTester(name) { 19668 var tag = '[object ' + name + ']'; 19669 return function (obj) { 19670 return toString.call(obj) === tag; 19671 }; 19672 } 19673 var isString = tagTester('String'); 19674 var isNumber = tagTester('Number'); 19675 var isDate = tagTester('Date'); 19676 var isRegExp = tagTester('RegExp'); 19677 var isError = tagTester('Error'); 19678 var isSymbol = tagTester('Symbol'); 19679 var isArrayBuffer = tagTester('ArrayBuffer'); 19680 var isFunction = tagTester('Function'); 19681 19682 // Optimize `isFunction` if appropriate. Work around some `typeof` bugs in old 19683 // v8, IE 11 (#1621), Safari 8 (#1929), and PhantomJS (#2236). 19684 var nodelist = root.document && root.document.childNodes; 19685 if (typeof /./ != 'function' && (typeof Int8Array === "undefined" ? "undefined" : _typeof(Int8Array)) != 'object' && typeof nodelist != 'function') { 19686 isFunction = function isFunction(obj) { 19687 return typeof obj == 'function' || false; 19688 }; 19689 } 19690 var isFunction$1 = isFunction; 19691 var hasObjectTag = tagTester('Object'); 19692 19693 // In IE 10 - Edge 13, `DataView` has string tag `'[object Object]'`. 19694 // In IE 11, the most common among them, this problem also applies to 19695 // `Map`, `WeakMap` and `Set`. 19696 // Also, there are cases where an application can override the native 19697 // `DataView` object, in cases like that we can't use the constructor 19698 // safely and should just rely on alternate `DataView` checks
19699 var hasDataViewBug = supportsDataView && (!/\[native code\]/.test(String(DataView)) || hasObjectTag(new DataView(new ArrayBuffer(8)))), 19700 isIE11 = typeof Map !== 'undefined' && hasObjectTag(new Map()); 19701 var isDataView = tagTester('DataView'); 19702 19703 // In IE 10 - Edge 13, we need a different heuristic 19704 // to determine whether an object is a `DataView`. 19705 // Also, in cases where the native `DataView` is 19706 // overridden we can't rely on the tag itself. 19707 function alternateIsDataView(obj) { 19708 return obj != null && isFunction$1(obj.getInt8) && isArrayBuffer(obj.buffer); 19709 } 19710 var isDataView$1 = hasDataViewBug ? alternateIsDataView : isDataView; 19711 19712 // Is a given value an array? 19713 // Delegates to ECMA5's native `Array.isArray`. 19714 var isArray = nativeIsArray || tagTester('Array'); 19715 19716 // Internal function to check whether `key` is an own property name of `obj`. 19717 function has$1(obj, key) { 19718 return obj != null && hasOwnProperty.call(obj, key); 19719 } 19720 var isArguments = tagTester('Arguments'); 19721 19722 // Define a fallback version of the method in browsers (ahem, IE < 9), where 19723 // there isn't any inspectable "Arguments" type. 19724 (function () { 19725 if (!isArguments(arguments)) { 19726 isArguments = function isArguments(obj) { 19727 return has$1(obj, 'callee'); 19728 }; 19729 } 19730 })(); 19731 var isArguments$1 = isArguments; 19732 19733 // Is a given object a finite number? 19734 function isFinite$1(obj) { 19735 return !isSymbol(obj) && _isFinite(obj) && !isNaN(parseFloat(obj)); 19736 } 19737 19738 // Is the given value `NaN`? 19739 function isNaN$1(obj) { 19740 return isNumber(obj) && _isNaN(obj); 19741 } 19742 19743 // Predicate-generating function. Often useful outside of Underscore. 19744 function constant(value) { 19745 return function () { 19746 return value; 19747 }; 19748 } 19749 19750 // Common internal logic for `isArrayLike` and `isBufferLike`. 19751 function createSizePropertyCheck(getSizeProperty) { 19752 return function (collection) { 19753 var sizeProperty = getSizeProperty(collection); 19754 return typeof sizeProperty == 'number' && sizeProperty >= 0 && sizeProperty <= MAX_ARRAY_INDEX; 19755 }; 19756 } 19757 19758 // Internal helper to generate a function to obtain property `key` from `obj`. 19759 function shallowProperty(key) { 19760 return function (obj) { 19761 return obj == null ? void 0 : obj[key]; 19762 }; 19763 } 19764 19765 // Internal helper to obtain the `byteLength` property of an object. 19766 var getByteLength = shallowProperty('byteLength'); 19767 19768 // Internal helper to determine whether we should spend extensive checks against 19769 // `ArrayBuffer` et al. 19770 var isBufferLike = createSizePropertyCheck(getByteLength); 19771 19772 // Is a given value a typed array? 19773 var typedArrayPattern = /\[object ((I|Ui)nt(8|16|32)|Float(32|64)|Uint8Clamped|Big(I|Ui)nt64)Array\]/; 19774 function isTypedArray(obj) { 19775 // `ArrayBuffer.isView` is the most future-proof, so use it when available. 19776 // Otherwise, fall back on the above regular expression. 19777 return nativeIsView ? nativeIsView(obj) && !isDataView$1(obj) : isBufferLike(obj) && typedArrayPattern.test(toString.call(obj)); 19778 } 19779 var isTypedArray$1 = supportsArrayBuffer ? isTypedArray : constant(false); 19780 19781 // Internal helper to obtain the `length` property of an object. 19782 var getLength = shallowProperty('length'); 19783 19784 // Internal helper to create a simple lookup structure. 19785 // `collectNonEnumProps` used to depend on `_.contains`, but this led to 19786 // circular imports. `emulatedSet` is a one-off solution that only works for
19787 // arrays of strings. 19788 function emulatedSet(keys) { 19789 var hash = {}; 19790 for (var l = keys.length, i = 0; i < l; ++i) hash[keys[i]] = true; 19791 return { 19792 contains: function contains(key) { 19793 return hash[key] === true; 19794 }, 19795 push: function push(key) { 19796 hash[key] = true; 19797 return keys.push(key); 19798 } 19799 }; 19800 } 19801 19802 // Internal helper. Checks `keys` for the presence of keys in IE < 9 that won't 19803 // be iterated by `for key in ...` and thus missed. Extends `keys` in place if 19804 // needed. 19805 function collectNonEnumProps(obj, keys) { 19806 keys = emulatedSet(keys); 19807 var nonEnumIdx = nonEnumerableProps.length; 19808 var constructor = obj.constructor; 19809 var proto = isFunction$1(constructor) && constructor.prototype || ObjProto; 19810 19811 // Constructor is a special case. 19812 var prop = 'constructor'; 19813 if (has$1(obj, prop) && !keys.contains(prop)) keys.push(prop); 19814 while (nonEnumIdx--) { 19815 prop = nonEnumerableProps[nonEnumIdx]; 19816 if (prop in obj && obj[prop] !== proto[prop] && !keys.contains(prop)) { 19817 keys.push(prop); 19818 } 19819 } 19820 } 19821 19822 // Retrieve the names of an object's own properties. 19823 // Delegates to **ECMAScript 5**'s native `Object.keys`. 19824 function keys(obj) { 19825 if (!isObject(obj)) return []; 19826 if (nativeKeys) return nativeKeys(obj); 19827 var keys = []; 19828 for (var key in obj) if (has$1(obj, key)) keys.push(key); 19829 // Ahem, IE < 9. 19830 if (hasEnumBug) collectNonEnumProps(obj, keys); 19831 return keys; 19832 } 19833 19834 // Is a given array, string, or object empty? 19835 // An "empty" object has no enumerable own-properties. 19836 function isEmpty(obj) { 19837 if (obj == null) return true; 19838 // Skip the more expensive `toString`-based type checks if `obj` has no 19839 // `.length`. 19840 var length = getLength(obj); 19841 if (typeof length == 'number' && (isArray(obj) || isString(obj) || isArguments$1(obj))) return length === 0; 19842 return getLength(keys(obj)) === 0; 19843 } 19844 19845 // Returns whether an object has a given set of `key:value` pairs. 19846 function isMatch(object, attrs) { 19847 var _keys = keys(attrs), 19848 length = _keys.length; 19849 if (object == null) return !length; 19850 var obj = Object(object); 19851 for (var i = 0; i < length; i++) { 19852 var key = _keys[i]; 19853 if (attrs[key] !== obj[key] || !(key in obj)) return false; 19854 } 19855 return true; 19856 } 19857 19858 // If Underscore is called as a function, it returns a wrapped object that can 19859 // be used OO-style. This wrapper holds altered versions of all functions added 19860 // through `_.mixin`. Wrapped objects may be chained. 19861 function _$1(obj) { 19862 if (obj instanceof _$1) return obj; 19863 if (!(this instanceof _$1)) return new _$1(obj); 19864 this._wrapped = obj; 19865 } 19866 _$1.VERSION = VERSION; 19867 19868 // Extracts the result from a wrapped and chained object. 19869 _$1.prototype.value = function () { 19870 return this._wrapped; 19871 }; 19872 19873 // Provide unwrapping proxies for some methods used in engine operations 19874 // such as arithmetic and JSON stringification. 19875 _$1.prototype.valueOf = _$1.prototype.toJSON = _$1.prototype.value; 19876 _$1.prototype.toString = function () { 19877 return String(this._wrapped); 19878 }; 19879 19880 // Internal function to wrap or shallow-copy an ArrayBuffer, 19881 // typed array or DataView to a new view, reusing the buffer. 19882 function toBufferView(bufferSource) { 19883 return new Uint8Array(bufferSource.buffer || bufferSource, bufferSource.byteOffset || 0, getByteLength(bufferSource)); 19884 } 19885 19886 // We use this string twice, so give it a name for minification. 19887 var tagDataView = '[object DataView]'; 19888 19889 // Internal recursive comparison function for `_.isEqual`. 19890 function eq(a, b, aStack, bStack) { 19891 // Identical objects are equal. `0 === -0`, but they aren't identical. 19892 // See the [Harmony `egal` proposal](https://wiki.ecmascript.org/doku.php?id=harmony:egal). 19893 if (a === b) return a !== 0 || 1 / a === 1 / b; 19894 // `null` or `undefined` only equal to itself (strict comparison). 19895 if (a == null || b == null) return false; 19896 // `NaN`s are equivalent, but non-reflexive. 19897 if (a !== a) return b !== b; 19898 // Exhaust primitive checks 19899 var type = _typeof(a); 19900 if (type !== 'function' && type !== 'object' && _typeof(b) != 'object') return false;
19901 return deepEq(a, b, aStack, bStack); 19902 } 19903 19904 // Internal recursive comparison function for `_.isEqual`. 19905 function deepEq(a, b, aStack, bStack) { 19906 // Unwrap any wrapped objects. 19907 if (a instanceof _$1) a = a._wrapped; 19908 if (b instanceof _$1) b = b._wrapped; 19909 // Compare `[[Class]]` names. 19910 var className = toString.call(a); 19911 if (className !== toString.call(b)) return false; 19912 // Work around a bug in IE 10 - Edge 13. 19913 if (hasDataViewBug && className == '[object Object]' && isDataView$1(a)) { 19914 if (!isDataView$1(b)) return false; 19915 className = tagDataView; 19916 } 19917 switch (className) { 19918 // These types are compared by value. 19919 case '[object RegExp]': 19920 // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i') 19921 case '[object String]': 19922 // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is 19923 // equivalent to `new String("5")`. 19924 return '' + a === '' + b; 19925 case '[object Number]': 19926 // `NaN`s are equivalent, but non-reflexive. 19927 // Object(NaN) is equivalent to NaN. 19928 if (+a !== +a) return +b !== +b; 19929 // An `egal` comparison is performed for other numeric values. 19930 return +a === 0 ? 1 / +a === 1 / b : +a === +b; 19931 case '[object Date]': 19932 case '[object Boolean]': 19933 // Coerce dates and booleans to numeric primitive values. Dates are compared by their 19934 // millisecond representations. Note that invalid dates with millisecond representations 19935 // of `NaN` are not equivalent. 19936 return +a === +b; 19937 case '[object Symbol]': 19938 return SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b); 19939 case '[object ArrayBuffer]': 19940 case tagDataView: 19941 // Coerce to typed array so we can fall through. 19942 return deepEq(toBufferView(a), toBufferView(b), aStack, bStack); 19943 } 19944 var areArrays = className === '[object Array]'; 19945 if (!areArrays && isTypedArray$1(a)) { 19946 var byteLength = getByteLength(a); 19947 if (byteLength !== getByteLength(b)) return false; 19948 if (a.buffer === b.buffer && a.byteOffset === b.byteOffset) return true; 19949 areArrays = true; 19950 } 19951 if (!areArrays) { 19952 if (_typeof(a) != 'object' || _typeof(b) != 'object') return false; 19953 19954 // Objects with different constructors are not equivalent, but `Object`s or `Array`s 19955 // from different frames are. 19956 var aCtor = a.constructor, 19957 bCtor = b.constructor; 19958 if (aCtor !== bCtor && !(isFunction$1(aCtor) && aCtor instanceof aCtor && isFunction$1(bCtor) && bCtor instanceof bCtor) && 'constructor' in a && 'constructor' in b) { 19959 return false; 19960 } 19961 } 19962 // Assume equality for cyclic structures. The algorithm for detecting cyclic 19963 // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. 19964 19965 // Initializing stack of traversed objects. 19966 // It's done here since we only need them for objects and arrays comparison. 19967 aStack = aStack || []; 19968 bStack = bStack || []; 19969 var length = aStack.length; 19970 while (length--) { 19971 // Linear search. Performance is inversely proportional to the number of 19972 // unique nested structures. 19973 if (aStack[length] === a) return bStack[length] === b; 19974 } 19975 19976 // Add the first object to the stack of traversed objects. 19977 aStack.push(a); 19978 bStack.push(b); 19979 19980 // Recursively compare objects and arrays. 19981 if (areArrays) { 19982 // Compare array lengths to determine if a deep comparison is necessary. 19983 length = a.length; 19984 if (length !== b.length) return false; 19985 // Deep compare the contents, ignoring non-numeric properties. 19986 while (length--) { 19987 if (!eq(a[length], b[length], aStack, bStack)) return false; 19988 } 19989 } else { 19990 // Deep compare objects. 19991 var _keys = keys(a), 19992 key; 19993 length = _keys.length; 19994 // Ensure that both objects contain the same number of properties before comparing deep equality. 19995 if (keys(b).length !== length) return false; 19996 while (length--) { 19997 // Deep compare each member 19998 key = _keys[length]; 19999 if (!(has$1(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
vendor: 5,414 bytes, lines 20000-20164
20000 } 20001 } 20002 // Remove the first object from the stack of traversed objects. 20003 aStack.pop(); 20004 bStack.pop(); 20005 return true; 20006 } 20007 20008 // Perform a deep comparison to check if two objects are equal. 20009 function isEqual(a, b) { 20010 return eq(a, b); 20011 } 20012 20013 // Retrieve all the enumerable property names of an object. 20014 function allKeys(obj) { 20015 if (!isObject(obj)) return []; 20016 var keys = []; 20017 for (var key in obj) keys.push(key); 20018 // Ahem, IE < 9. 20019 if (hasEnumBug) collectNonEnumProps(obj, keys); 20020 return keys; 20021 } 20022 20023 // Since the regular `Object.prototype.toString` type tests don't work for 20024 // some types in IE 11, we use a fingerprinting heuristic instead, based 20025 // on the methods. It's not great, but it's the best we got. 20026 // The fingerprint method lists are defined below. 20027 function ie11fingerprint(methods) { 20028 var length = getLength(methods); 20029 return function (obj) { 20030 if (obj == null) return false; 20031 // `Map`, `WeakMap` and `Set` have no enumerable keys. 20032 var keys = allKeys(obj); 20033 if (getLength(keys)) return false; 20034 for (var i = 0; i < length; i++) { 20035 if (!isFunction$1(obj[methods[i]])) return false; 20036 } 20037 // If we are testing against `WeakMap`, we need to ensure that 20038 // `obj` doesn't have a `forEach` method in order to distinguish 20039 // it from a regular `Map`. 20040 return methods !== weakMapMethods || !isFunction$1(obj[forEachName]); 20041 }; 20042 } 20043 20044 // In the interest of compact minification, we write 20045 // each string in the fingerprints only once. 20046 var forEachName = 'forEach', 20047 hasName = 'has', 20048 commonInit = ['clear', 'delete'], 20049 mapTail = ['get', hasName, 'set']; 20050 20051 // `Map`, `WeakMap` and `Set` each have slightly different 20052 // combinations of the above sublists. 20053 var mapMethods = commonInit.concat(forEachName, mapTail), 20054 weakMapMethods = commonInit.concat(mapTail), 20055 setMethods = ['add'].concat(commonInit, forEachName, hasName); 20056 var isMap = isIE11 ? ie11fingerprint(mapMethods) : tagTester('Map'); 20057 var isWeakMap = isIE11 ? ie11fingerprint(weakMapMethods) : tagTester('WeakMap'); 20058 var isSet = isIE11 ? ie11fingerprint(setMethods) : tagTester('Set'); 20059 var isWeakSet = tagTester('WeakSet'); 20060 20061 // Retrieve the values of an object's properties. 20062 function values(obj) { 20063 var _keys = keys(obj); 20064 var length = _keys.length; 20065 var values = Array(length); 20066 for (var i = 0; i < length; i++) { 20067 values[i] = obj[_keys[i]]; 20068 } 20069 return values; 20070 } 20071 20072 // Convert an object into a list of `[key, value]` pairs. 20073 // The opposite of `_.object` with one argument. 20074 function pairs(obj) { 20075 var _keys = keys(obj); 20076 var length = _keys.length; 20077 var pairs = Array(length); 20078 for (var i = 0; i < length; i++) { 20079 pairs[i] = [_keys[i], obj[_keys[i]]]; 20080 } 20081 return pairs; 20082 } 20083 20084 // Invert the keys and values of an object. The values must be serializable. 20085 function invert(obj) { 20086 var result = {}; 20087 var _keys = keys(obj); 20088 for (var i = 0, length = _keys.length; i < length; i++) { 20089 result[obj[_keys[i]]] = _keys[i]; 20090 } 20091 return result; 20092 } 20093 20094 // Return a sorted list of the function names available on the object. 20095 function functions(obj) { 20096 var names = []; 20097 for (var key in obj) { 20098 if (isFunction$1(obj[key])) names.push(key); 20099 } 20100 return names.sort(); 20101 } 20102 20103 // An internal function for creating assigner functions. 20104 function createAssigner(keysFunc, defaults) { 20105 return function (obj) { 20106 var length = arguments.length; 20107 if (defaults) obj = Object(obj); 20108 if (length < 2 || obj == null) return obj; 20109 for (var index = 1; index < length; index++) { 20110 var source = arguments[index], 20111 keys = keysFunc(source), 20112 l = keys.length; 20113 for (var i = 0; i < l; i++) { 20114 var key = keys[i]; 20115 if (!defaults || obj[key] === void 0) obj[key] = source[key]; 20116 } 20117 } 20118 return obj; 20119 }; 20120 } 20121 20122 // Extend a given object with all the properties in passed-in object(s). 20123 var extend = createAssigner(allKeys); 20124 20125 // Assigns a given object with all the own properties in the passed-in 20126 // object(s). 20127 // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) 20128 var extendOwn = createAssigner(keys); 20129 20130 // Fill in a given object with default properties. 20131 var defaults = createAssigner(allKeys, true); 20132 20133 // Create a naked function reference for surrogate-prototype-swapping. 20134 function ctor() { 20135 return function () {}; 20136 } 20137 20138 // An internal function for creating a new object that inherits from another. 20139 function baseCreate(prototype) { 20140 if (!isObject(prototype)) return {}; 20141 if (nativeCreate) return nativeCreate(prototype); 20142 var Ctor = ctor(); 20143 Ctor.prototype = prototype; 20144 var result = new Ctor(); 20145 Ctor.prototype = null; 20146 return result; 20147 } 20148 20149 // Creates an object that inherits from the given prototype object. 20150 // If additional properties are provided then they will be added to the 20151 // created object. 20152 function create(prototype, props) { 20153 var result = baseCreate(prototype); 20154 if (props) extendOwn(result, props); 20155 return result; 20156 } 20157 20158 // Create a (shallow-cloned) duplicate of an object. 20159 function clone(obj) { 20160 if (!isObject(obj)) return obj; 20161 return isArray(obj) ? obj.slice() : extend({}, obj); 20162 } 20163 20164 // Invokes `interceptor` with the `obj` and then returns `obj`.
vendor: 10,353 bytes, lines 20165-20458
20165 // The primary purpose of this method is to "tap into" a method chain, in 20166 // order to perform operations on intermediate results within the chain. 20167 function tap(obj, interceptor) { 20168 interceptor(obj); 20169 return obj; 20170 } 20171 20172 // Normalize a (deep) property `path` to array. 20173 // Like `_.iteratee`, this function can be customized. 20174 function toPath$1(path) { 20175 return isArray(path) ? path : [path]; 20176 } 20177 _$1.toPath = toPath$1; 20178 20179 // Internal wrapper for `_.toPath` to enable minification. 20180 // Similar to `cb` for `_.iteratee`. 20181 function toPath(path) { 20182 return _$1.toPath(path); 20183 } 20184 20185 // Internal function to obtain a nested property in `obj` along `path`. 20186 function deepGet(obj, path) { 20187 var length = path.length; 20188 for (var i = 0; i < length; i++) { 20189 if (obj == null) return void 0; 20190 obj = obj[path[i]]; 20191 } 20192 return length ? obj : void 0; 20193 } 20194 20195 // Get the value of the (deep) property on `path` from `object`. 20196 // If any property in `path` does not exist or if the value is 20197 // `undefined`, return `defaultValue` instead. 20198 // The `path` is normalized through `_.toPath`. 20199 function get(object, path, defaultValue) { 20200 var value = deepGet(object, toPath(path)); 20201 return isUndefined(value) ? defaultValue : value; 20202 } 20203 20204 // Shortcut function for checking if an object has a given property directly on 20205 // itself (in other words, not on a prototype). Unlike the internal `has` 20206 // function, this public version can also traverse nested properties. 20207 function has(obj, path) { 20208 path = toPath(path); 20209 var length = path.length; 20210 for (var i = 0; i < length; i++) { 20211 var key = path[i]; 20212 if (!has$1(obj, key)) return false; 20213 obj = obj[key]; 20214 } 20215 return !!length; 20216 } 20217 20218 // Keep the identity function around for default iteratees. 20219 function identity(value) { 20220 return value; 20221 } 20222 20223 // Returns a predicate for checking whether an object has a given set of 20224 // `key:value` pairs. 20225 function matcher(attrs) { 20226 attrs = extendOwn({}, attrs); 20227 return function (obj) { 20228 return isMatch(obj, attrs); 20229 }; 20230 } 20231 20232 // Creates a function that, when passed an object, will traverse that object’s 20233 // properties down the given `path`, specified as an array of keys or indices. 20234 function property(path) { 20235 path = toPath(path); 20236 return function (obj) { 20237 return deepGet(obj, path); 20238 }; 20239 } 20240 20241 // Internal function that returns an efficient (for current engines) version 20242 // of the passed-in callback, to be repeatedly applied in other Underscore 20243 // functions. 20244 function optimizeCb(func, context, argCount) { 20245 if (context === void 0) return func; 20246 switch (argCount == null ? 3 : argCount) { 20247 case 1: 20248 return function (value) { 20249 return func.call(context, value); 20250 }; 20251 // The 2-argument case is omitted because we’re not using it. 20252 case 3: 20253 return function (value, index, collection) { 20254 return func.call(context, value, index, collection); 20255 }; 20256 case 4: 20257 return function (accumulator, value, index, collection) { 20258 return func.call(context, accumulator, value, index, collection); 20259 }; 20260 } 20261 return function () { 20262 return func.apply(context, arguments); 20263 }; 20264 } 20265 20266 // An internal function to generate callbacks that can be applied to each 20267 // element in a collection, returning the desired result — either `_.identity`, 20268 // an arbitrary callback, a property matcher, or a property accessor. 20269 function baseIteratee(value, context, argCount) { 20270 if (value == null) return identity; 20271 if (isFunction$1(value)) return optimizeCb(value, context, argCount); 20272 if (isObject(value) && !isArray(value)) return matcher(value); 20273 return property(value); 20274 } 20275 20276 // External wrapper for our callback generator. Users may customize 20277 // `_.iteratee` if they want additional predicate/iteratee shorthand styles. 20278 // This abstraction hides the internal-only `argCount` argument. 20279 function iteratee(value, context) { 20280 return baseIteratee(value, context, Infinity); 20281 } 20282 _$1.iteratee = iteratee; 20283 20284 // The function we call internally to generate a callback. It invokes 20285 // `_.iteratee` if overridden, otherwise `baseIteratee`. 20286 function cb(value, context, argCount) { 20287 if (_$1.iteratee !== iteratee) return _$1.iteratee(value, context); 20288 return baseIteratee(value, context, argCount); 20289 } 20290 20291 // Returns the results of applying the `iteratee` to each element of `obj`. 20292 // In contrast to `_.map` it returns an object. 20293 function mapObject(obj, iteratee, context) { 20294 iteratee = cb(iteratee, context); 20295 var _keys = keys(obj), 20296 length = _keys.length, 20297 results = {}; 20298 for (var index = 0; index < length; index++) { 20299 var currentKey = _keys[index]; 20300 results[currentKey] = iteratee(obj[currentKey], currentKey, obj); 20301 } 20302 return results; 20303 } 20304 20305 // Predicate-generating function. Often useful outside of Underscore. 20306 function noop() {} 20307 20308 // Generates a function for a given object that returns a given property. 20309 function propertyOf(obj) { 20310 if (obj == null) return noop; 20311 return function (path) { 20312 return get(obj, path); 20313 }; 20314 } 20315 20316 // Run a function **n** times. 20317 function times(n, iteratee, context) { 20318 var accum = Array(Math.max(0, n)); 20319 iteratee = optimizeCb(iteratee, context, 1); 20320 for (var i = 0; i < n; i++) accum[i] = iteratee(i); 20321 return accum; 20322 } 20323 20324 // Return a random integer between `min` and `max` (inclusive). 20325 function random(min, max) { 20326 if (max == null) { 20327 max = min; 20328 min = 0; 20329 } 20330 return min + Math.floor(Math.random() * (max - min + 1)); 20331 } 20332 20333 // A (possibly faster) way to get the current timestamp as an integer. 20334 var now = Date.now || function () { 20335 return new Date().getTime(); 20336 }; 20337 20338 // Internal helper to generate functions for escaping and unescaping strings 20339 // to/from HTML interpolation. 20340 function createEscaper(map) { 20341 var escaper = function escaper(match) { 20342 return map[match]; 20343 }; 20344 // Regexes for identifying a key that needs to be escaped. 20345 var source = '(?:' + keys(map).join('|') + ')'; 20346 var testRegexp = RegExp(source); 20347 var replaceRegexp = RegExp(source, 'g'); 20348 return function (string) { 20349 string = string == null ? '' : '' + string; 20350 return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; 20351 }; 20352 } 20353 20354 // Internal list of HTML entities for escaping. 20355 var escapeMap = { 20356 '&': '&', 20357 '<': '<', 20358 '>': '>', 20359 '"': '"', 20360 "'": ''', 20361 '`': '`' 20362 }; 20363 20364 // Function for escaping strings to HTML interpolation. 20365 var _escape = createEscaper(escapeMap); 20366 20367 // Internal list of HTML entities for unescaping. 20368 var unescapeMap = invert(escapeMap); 20369 20370 // Function for unescaping strings from HTML interpolation. 20371 var _unescape = createEscaper(unescapeMap); 20372 20373 // By default, Underscore uses ERB-style template delimiters. Change the 20374 // following template settings to use alternative delimiters. 20375 var templateSettings = _$1.templateSettings = { 20376 evaluate: /<%([\s\S]+?)%>/g, 20377 interpolate: /<%=([\s\S]+?)%>/g, 20378 escape: /<%-([\s\S]+?)%>/g 20379 }; 20380 20381 // When customizing `_.templateSettings`, if you don't want to define an 20382 // interpolation, evaluation or escaping regex, we need one that is 20383 // guaranteed not to match. 20384 var noMatch = /(.)^/; 20385 20386 // Certain characters need to be escaped so that they can be put into a 20387 // string literal. 20388 var escapes = { 20389 "'": "'", 20390 '\\': '\\', 20391 '\r': 'r', 20392 '\n': 'n', 20393 "\u2028": 'u2028', 20394 "\u2029": 'u2029' 20395 }; 20396 var escapeRegExp = /\\|'|\r|\n|\u2028|\u2029/g; 20397 function escapeChar(match) { 20398 return '\\' + escapes[match]; 20399 } 20400 20401 // In order to prevent third-party code injection through 20402 // `_.templateSettings.variable`, we test it against the following regular 20403 // expression. It is intentionally a bit more liberal than just matching valid 20404 // identifiers, but still prevents possible loopholes through defaults or 20405 // destructuring assignment. 20406 var bareIdentifier = /^\s*(\w|\$)+\s*$/; 20407 20408 // JavaScript micro-templating, similar to John Resig's implementation. 20409 // Underscore templating handles arbitrary delimiters, preserves whitespace, 20410 // and correctly escapes quotes within interpolated code. 20411 // NB: `oldSettings` only exists for backwards compatibility. 20412 function template(text, settings, oldSettings) { 20413 if (!settings && oldSettings) settings = oldSettings; 20414 settings = defaults({}, settings, _$1.templateSettings); 20415 20416 // Combine delimiters into one regular expression via alternation. 20417 var matcher = RegExp([(settings.escape || noMatch).source, (settings.interpolate || noMatch).source, (settings.evaluate || noMatch).source].join('|') + '|$', 'g'); 20418 20419 // Compile the template source, escaping string literals appropriately. 20420 var index = 0; 20421 var source = "__p+='"; 20422 text.replace(matcher, function (match, escape, interpolate, evaluate, offset) { 20423 source += text.slice(index, offset).replace(escapeRegExp, escapeChar); 20424 index = offset + match.length; 20425 if (escape) { 20426 source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; 20427 } else if (interpolate) { 20428 source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; 20429 } else if (evaluate) { 20430 source += "';\n" + evaluate + "\n__p+='"; 20431 } 20432 20433 // Adobe VMs need the match returned to produce the correct offset. 20434 return match; 20435 }); 20436 source += "';\n"; 20437 var argument = settings.variable; 20438 if (argument) { 20439 // Insure against third-party code injection. (CVE-2021-23358) 20440 if (!bareIdentifier.test(argument)) throw new Error('variable is not a bare identifier: ' + argument); 20441 } else { 20442 // If a variable is not specified, place data values in local scope. 20443 source = 'with(obj||{}){\n' + source + '}\n'; 20444 argument = 'obj'; 20445 } 20446 source = "var __t,__p='',__j=Array.prototype.join," + "print=function(){__p+=__j.call(arguments,'');};\n" + source + 'return __p;\n'; 20447 var render; 20448 try { 20449 render = new Function(argument, '_', source); 20450 } catch (e) { 20451 e.source = source; 20452 throw e; 20453 } 20454 var template = function template(data) { 20455 return render.call(this, data, _$1); 20456 }; 20457 20458 // Provide the compiled source as a convenience for precompilation.
vendor: 4,259 bytes, lines 20459-20573
20459 template.source = 'function(' + argument + '){\n' + source + '}'; 20460 return template; 20461 } 20462 20463 // Traverses the children of `obj` along `path`. If a child is a function, it 20464 // is invoked with its parent as context. Returns the value of the final 20465 // child, or `fallback` if any child is undefined. 20466 function result(obj, path, fallback) { 20467 path = toPath(path); 20468 var length = path.length; 20469 if (!length) { 20470 return isFunction$1(fallback) ? fallback.call(obj) : fallback; 20471 } 20472 for (var i = 0; i < length; i++) { 20473 var prop = obj == null ? void 0 : obj[path[i]]; 20474 if (prop === void 0) { 20475 prop = fallback; 20476 i = length; // Ensure we don't continue iterating. 20477 } 20478 obj = isFunction$1(prop) ? prop.call(obj) : prop; 20479 } 20480 return obj; 20481 } 20482 20483 // Generate a unique integer id (unique within the entire client session). 20484 // Useful for temporary DOM ids. 20485 var idCounter = 0; 20486 function uniqueId(prefix) { 20487 var id = ++idCounter + ''; 20488 return prefix ? prefix + id : id; 20489 } 20490 20491 // Start chaining a wrapped Underscore object. 20492 function chain(obj) { 20493 var instance = _$1(obj); 20494 instance._chain = true; 20495 return instance; 20496 } 20497 20498 // Internal function to execute `sourceFunc` bound to `context` with optional 20499 // `args`. Determines whether to execute a function as a constructor or as a 20500 // normal function. 20501 function executeBound(sourceFunc, boundFunc, context, callingContext, args) { 20502 if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); 20503 var self = baseCreate(sourceFunc.prototype); 20504 var result = sourceFunc.apply(self, args); 20505 if (isObject(result)) return result; 20506 return self; 20507 } 20508 20509 // Partially apply a function by creating a version that has had some of its 20510 // arguments pre-filled, without changing its dynamic `this` context. `_` acts 20511 // as a placeholder by default, allowing any combination of arguments to be 20512 // pre-filled. Set `_.partial.placeholder` for a custom placeholder argument. 20513 var partial = restArguments(function (func, boundArgs) { 20514 var placeholder = partial.placeholder; 20515 var _bound = function bound() { 20516 var position = 0, 20517 length = boundArgs.length; 20518 var args = Array(length); 20519 for (var i = 0; i < length; i++) { 20520 args[i] = boundArgs[i] === placeholder ? arguments[position++] : boundArgs[i]; 20521 } 20522 while (position < arguments.length) args.push(arguments[position++]); 20523 return executeBound(func, _bound, this, this, args); 20524 }; 20525 return _bound; 20526 }); 20527 partial.placeholder = _$1; 20528 20529 // Create a function bound to a given object (assigning `this`, and arguments, 20530 // optionally). 20531 var bind = restArguments(function (func, context, args) { 20532 if (!isFunction$1(func)) throw new TypeError('Bind must be called on a function'); 20533 var bound = restArguments(function (callArgs) { 20534 return executeBound(func, bound, context, this, args.concat(callArgs)); 20535 }); 20536 return bound; 20537 }); 20538 20539 // Internal helper for collection methods to determine whether a collection 20540 // should be iterated as an array or as an object. 20541 // Related: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength 20542 // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094 20543 var isArrayLike = createSizePropertyCheck(getLength); 20544 20545 // Internal implementation of a recursive `flatten` function. 20546 function flatten$1(input, depth, strict, output) { 20547 output = output || []; 20548 if (!depth && depth !== 0) { 20549 depth = Infinity; 20550 } else if (depth <= 0) { 20551 return output.concat(input); 20552 } 20553 var idx = output.length; 20554 for (var i = 0, length = getLength(input); i < length; i++) { 20555 var value = input[i]; 20556 if (isArrayLike(value) && (isArray(value) || isArguments$1(value))) { 20557 // Flatten current level of array or arguments object. 20558 if (depth > 1) { 20559 flatten$1(value, depth - 1, strict, output); 20560 idx = output.length; 20561 } else { 20562 var j = 0, 20563 len = value.length; 20564 while (j < len) output[idx++] = value[j++]; 20565 } 20566 } else if (!strict) { 20567 output[idx++] = value; 20568 } 20569 } 20570 return output; 20571 } 20572 20573 // Bind a number of an object's methods to that object. Remaining arguments
vendor: 13,218 bytes, lines 20574-20954
20574 // are the method names to be bound. Useful for ensuring that all callbacks 20575 // defined on an object belong to it. 20576 var bindAll = restArguments(function (obj, keys) { 20577 keys = flatten$1(keys, false, false); 20578 var index = keys.length; 20579 if (index < 1) throw new Error('bindAll must be passed function names'); 20580 while (index--) { 20581 var key = keys[index]; 20582 obj[key] = bind(obj[key], obj); 20583 } 20584 return obj; 20585 }); 20586 20587 // Memoize an expensive function by storing its results. 20588 function memoize(func, hasher) { 20589 var _memoize = function memoize(key) { 20590 var cache = _memoize.cache; 20591 var address = '' + (hasher ? hasher.apply(this, arguments) : key); 20592 if (!has$1(cache, address)) cache[address] = func.apply(this, arguments); 20593 return cache[address]; 20594 }; 20595 _memoize.cache = {}; 20596 return _memoize; 20597 } 20598 20599 // Delays a function for the given number of milliseconds, and then calls 20600 // it with the arguments supplied. 20601 var delay = restArguments(function (func, wait, args) { 20602 return setTimeout(function () { 20603 return func.apply(null, args); 20604 }, wait); 20605 }); 20606 20607 // Defers a function, scheduling it to run after the current call stack has 20608 // cleared. 20609 var defer = partial(delay, _$1, 1); 20610 20611 // Returns a function, that, when invoked, will only be triggered at most once 20612 // during a given window of time. Normally, the throttled function will run 20613 // as much as it can, without ever going more than once per `wait` duration; 20614 // but if you'd like to disable the execution on the leading edge, pass 20615 // `{leading: false}`. To disable execution on the trailing edge, ditto. 20616 function throttle(func, wait, options) { 20617 var timeout, context, args, result; 20618 var previous = 0; 20619 if (!options) options = {}; 20620 var later = function later() { 20621 previous = options.leading === false ? 0 : now(); 20622 timeout = null; 20623 result = func.apply(context, args); 20624 if (!timeout) context = args = null; 20625 }; 20626 var throttled = function throttled() { 20627 var _now = now(); 20628 if (!previous && options.leading === false) previous = _now; 20629 var remaining = wait - (_now - previous); 20630 context = this; 20631 args = arguments; 20632 if (remaining <= 0 || remaining > wait) { 20633 if (timeout) { 20634 clearTimeout(timeout); 20635 timeout = null; 20636 } 20637 previous = _now; 20638 result = func.apply(context, args); 20639 if (!timeout) context = args = null; 20640 } else if (!timeout && options.trailing !== false) { 20641 timeout = setTimeout(later, remaining); 20642 } 20643 return result; 20644 }; 20645 throttled.cancel = function () { 20646 clearTimeout(timeout); 20647 previous = 0; 20648 timeout = context = args = null; 20649 }; 20650 return throttled; 20651 } 20652 20653 // When a sequence of calls of the returned function ends, the argument 20654 // function is triggered. The end of a sequence is defined by the `wait` 20655 // parameter. If `immediate` is passed, the argument function will be 20656 // triggered at the beginning of the sequence instead of at the end. 20657 function debounce(func, wait, immediate) { 20658 var timeout, previous, args, result, context; 20659 var _later = function later() { 20660 var passed = now() - previous; 20661 if (wait > passed) { 20662 timeout = setTimeout(_later, wait - passed); 20663 } else { 20664 timeout = null; 20665 if (!immediate) result = func.apply(context, args); 20666 // This check is needed because `func` can recursively invoke `debounced`. 20667 if (!timeout) args = context = null; 20668 } 20669 }; 20670 var debounced = restArguments(function (_args) { 20671 context = this; 20672 args = _args; 20673 previous = now(); 20674 if (!timeout) { 20675 timeout = setTimeout(_later, wait); 20676 if (immediate) result = func.apply(context, args); 20677 } 20678 return result; 20679 }); 20680 debounced.cancel = function () { 20681 clearTimeout(timeout); 20682 timeout = args = context = null; 20683 }; 20684 return debounced; 20685 } 20686 20687 // Returns the first function passed as an argument to the second, 20688 // allowing you to adjust arguments, run code before and after, and 20689 // conditionally execute the original function. 20690 function wrap(func, wrapper) { 20691 return partial(wrapper, func); 20692 } 20693 20694 // Returns a negated version of the passed-in predicate. 20695 function negate(predicate) { 20696 return function () { 20697 return !predicate.apply(this, arguments); 20698 }; 20699 } 20700 20701 // Returns a function that is the composition of a list of functions, each 20702 // consuming the return value of the function that follows. 20703 function compose() { 20704 var args = arguments; 20705 var start = args.length - 1; 20706 return function () { 20707 var i = start; 20708 var result = args[start].apply(this, arguments); 20709 while (i--) result = args[i].call(this, result); 20710 return result; 20711 }; 20712 } 20713 20714 // Returns a function that will only be executed on and after the Nth call. 20715 function after(times, func) { 20716 return function () { 20717 if (--times < 1) { 20718 return func.apply(this, arguments); 20719 } 20720 }; 20721 } 20722 20723 // Returns a function that will only be executed up to (but not including) the 20724 // Nth call. 20725 function before(times, func) { 20726 var memo; 20727 return function () { 20728 if (--times > 0) { 20729 memo = func.apply(this, arguments); 20730 } 20731 if (times <= 1) func = null; 20732 return memo; 20733 }; 20734 } 20735 20736 // Returns a function that will be executed at most one time, no matter how 20737 // often you call it. Useful for lazy initialization. 20738 var once = partial(before, 2); 20739 20740 // Returns the first key on an object that passes a truth test. 20741 function findKey(obj, predicate, context) { 20742 predicate = cb(predicate, context); 20743 var _keys = keys(obj), 20744 key; 20745 for (var i = 0, length = _keys.length; i < length; i++) { 20746 key = _keys[i]; 20747 if (predicate(obj[key], key, obj)) return key; 20748 } 20749 } 20750 20751 // Internal function to generate `_.findIndex` and `_.findLastIndex`. 20752 function createPredicateIndexFinder(dir) { 20753 return function (array, predicate, context) { 20754 predicate = cb(predicate, context); 20755 var length = getLength(array); 20756 var index = dir > 0 ? 0 : length - 1; 20757 for (; index >= 0 && index < length; index += dir) { 20758 if (predicate(array[index], index, array)) return index; 20759 } 20760 return -1; 20761 }; 20762 } 20763 20764 // Returns the first index on an array-like that passes a truth test. 20765 var findIndex = createPredicateIndexFinder(1); 20766 20767 // Returns the last index on an array-like that passes a truth test. 20768 var findLastIndex = createPredicateIndexFinder(-1); 20769 20770 // Use a comparator function to figure out the smallest index at which 20771 // an object should be inserted so as to maintain order. Uses binary search. 20772 function sortedIndex(array, obj, iteratee, context) { 20773 iteratee = cb(iteratee, context, 1); 20774 var value = iteratee(obj); 20775 var low = 0, 20776 high = getLength(array); 20777 while (low < high) { 20778 var mid = Math.floor((low + high) / 2); 20779 if (iteratee(array[mid]) < value) low = mid + 1;else high = mid; 20780 } 20781 return low; 20782 } 20783 20784 // Internal function to generate the `_.indexOf` and `_.lastIndexOf` functions. 20785 function createIndexFinder(dir, predicateFind, sortedIndex) { 20786 return function (array, item, idx) { 20787 var i = 0, 20788 length = getLength(array); 20789 if (typeof idx == 'number') { 20790 if (dir > 0) { 20791 i = idx >= 0 ? idx : Math.max(idx + length, i); 20792 } else { 20793 length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; 20794 } 20795 } else if (sortedIndex && idx && length) { 20796 idx = sortedIndex(array, item); 20797 return array[idx] === item ? idx : -1; 20798 } 20799 if (item !== item) { 20800 idx = predicateFind(slice.call(array, i, length), isNaN$1); 20801 return idx >= 0 ? idx + i : -1; 20802 } 20803 for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) { 20804 if (array[idx] === item) return idx; 20805 } 20806 return -1; 20807 }; 20808 } 20809 20810 // Return the position of the first occurrence of an item in an array, 20811 // or -1 if the item is not included in the array. 20812 // If the array is large and already in sort order, pass `true` 20813 // for **isSorted** to use binary search. 20814 var indexOf = createIndexFinder(1, findIndex, sortedIndex); 20815 20816 // Return the position of the last occurrence of an item in an array, 20817 // or -1 if the item is not included in the array. 20818 var lastIndexOf = createIndexFinder(-1, findLastIndex); 20819 20820 // Return the first value which passes a truth test. 20821 function find(obj, predicate, context) { 20822 var keyFinder = isArrayLike(obj) ? findIndex : findKey; 20823 var key = keyFinder(obj, predicate, context); 20824 if (key !== void 0 && key !== -1) return obj[key]; 20825 } 20826 20827 // Convenience version of a common use case of `_.find`: getting the first 20828 // object containing specific `key:value` pairs. 20829 function findWhere(obj, attrs) { 20830 return find(obj, matcher(attrs)); 20831 } 20832 20833 // The cornerstone for collection functions, an `each` 20834 // implementation, aka `forEach`. 20835 // Handles raw objects in addition to array-likes. Treats all 20836 // sparse array-likes as if they were dense. 20837 function each(obj, iteratee, context) { 20838 iteratee = optimizeCb(iteratee, context); 20839 var i, length; 20840 if (isArrayLike(obj)) { 20841 for (i = 0, length = obj.length; i < length; i++) { 20842 iteratee(obj[i], i, obj); 20843 } 20844 } else { 20845 var _keys = keys(obj); 20846 for (i = 0, length = _keys.length; i < length; i++) { 20847 iteratee(obj[_keys[i]], _keys[i], obj); 20848 } 20849 } 20850 return obj; 20851 } 20852 20853 // Return the results of applying the iteratee to each element. 20854 function map(obj, iteratee, context) { 20855 iteratee = cb(iteratee, context); 20856 var _keys = !isArrayLike(obj) && keys(obj), 20857 length = (_keys || obj).length, 20858 results = Array(length); 20859 for (var index = 0; index < length; index++) { 20860 var currentKey = _keys ? _keys[index] : index; 20861 results[index] = iteratee(obj[currentKey], currentKey, obj); 20862 } 20863 return results; 20864 } 20865 20866 // Internal helper to create a reducing function, iterating left or right. 20867 function createReduce(dir) { 20868 // Wrap code that reassigns argument variables in a separate function than 20869 // the one that accesses `arguments.length` to avoid a perf hit. (#1991) 20870 var reducer = function reducer(obj, iteratee, memo, initial) { 20871 var _keys = !isArrayLike(obj) && keys(obj), 20872 length = (_keys || obj).length, 20873 index = dir > 0 ? 0 : length - 1; 20874 if (!initial) { 20875 memo = obj[_keys ? _keys[index] : index]; 20876 index += dir; 20877 } 20878 for (; index >= 0 && index < length; index += dir) { 20879 var currentKey = _keys ? _keys[index] : index; 20880 memo = iteratee(memo, obj[currentKey], currentKey, obj); 20881 } 20882 return memo; 20883 }; 20884 return function (obj, iteratee, memo, context) { 20885 var initial = arguments.length >= 3; 20886 return reducer(obj, optimizeCb(iteratee, context, 4), memo, initial); 20887 }; 20888 } 20889 20890 // **Reduce** builds up a single result from a list of values, aka `inject`, 20891 // or `foldl`. 20892 var reduce = createReduce(1); 20893 20894 // The right-associative version of reduce, also known as `foldr`. 20895 var reduceRight = createReduce(-1); 20896 20897 // Return all the elements that pass a truth test. 20898 function filter(obj, predicate, context) { 20899 var results = []; 20900 predicate = cb(predicate, context); 20901 each(obj, function (value, index, list) { 20902 if (predicate(value, index, list)) results.push(value); 20903 }); 20904 return results; 20905 } 20906 20907 // Return all the elements for which a truth test fails. 20908 function reject(obj, predicate, context) { 20909 return filter(obj, negate(cb(predicate)), context); 20910 } 20911 20912 // Determine whether all of the elements pass a truth test. 20913 function every(obj, predicate, context) { 20914 predicate = cb(predicate, context); 20915 var _keys = !isArrayLike(obj) && keys(obj), 20916 length = (_keys || obj).length; 20917 for (var index = 0; index < length; index++) { 20918 var currentKey = _keys ? _keys[index] : index; 20919 if (!predicate(obj[currentKey], currentKey, obj)) return false; 20920 } 20921 return true; 20922 } 20923 20924 // Determine if at least one element in the object passes a truth test. 20925 function some(obj, predicate, context) { 20926 predicate = cb(predicate, context); 20927 var _keys = !isArrayLike(obj) && keys(obj), 20928 length = (_keys || obj).length; 20929 for (var index = 0; index < length; index++) { 20930 var currentKey = _keys ? _keys[index] : index; 20931 if (predicate(obj[currentKey], currentKey, obj)) return true; 20932 } 20933 return false; 20934 } 20935 20936 // Determine if the array or object contains a given item (using `===`). 20937 function contains(obj, item, fromIndex, guard) { 20938 if (!isArrayLike(obj)) obj = values(obj); 20939 if (typeof fromIndex != 'number' || guard) fromIndex = 0; 20940 return indexOf(obj, item, fromIndex) >= 0; 20941 } 20942 20943 // Invoke a method (with arguments) on every item in a collection. 20944 var invoke = restArguments(function (obj, path, args) { 20945 var contextPath, func; 20946 if (isFunction$1(path)) { 20947 func = path; 20948 } else { 20949 path = toPath(path); 20950 contextPath = path.slice(0, -1); 20951 path = path[path.length - 1]; 20952 } 20953 return map(obj, function (context) { 20954 var method = func;
vendor: 6,310 bytes, lines 20955-21144
20955 if (!method) { 20956 if (contextPath && contextPath.length) { 20957 context = deepGet(context, contextPath); 20958 } 20959 if (context == null) return void 0; 20960 method = context[path]; 20961 } 20962 return method == null ? method : method.apply(context, args); 20963 }); 20964 }); 20965 20966 // Convenience version of a common use case of `_.map`: fetching a property. 20967 function pluck(obj, key) { 20968 return map(obj, property(key)); 20969 } 20970 20971 // Convenience version of a common use case of `_.filter`: selecting only 20972 // objects containing specific `key:value` pairs. 20973 function where(obj, attrs) { 20974 return filter(obj, matcher(attrs)); 20975 } 20976 20977 // Return the maximum element (or element-based computation). 20978 function max(obj, iteratee, context) { 20979 var result = -Infinity, 20980 lastComputed = -Infinity, 20981 value, 20982 computed; 20983 if (iteratee == null || typeof iteratee == 'number' && _typeof(obj[0]) != 'object' && obj != null) { 20984 obj = isArrayLike(obj) ? obj : values(obj); 20985 for (var i = 0, length = obj.length; i < length; i++) { 20986 value = obj[i]; 20987 if (value != null && value > result) { 20988 result = value; 20989 } 20990 } 20991 } else { 20992 iteratee = cb(iteratee, context); 20993 each(obj, function (v, index, list) { 20994 computed = iteratee(v, index, list); 20995 if (computed > lastComputed || computed === -Infinity && result === -Infinity) { 20996 result = v; 20997 lastComputed = computed; 20998 } 20999 }); 21000 } 21001 return result; 21002 } 21003 21004 // Return the minimum element (or element-based computation). 21005 function min(obj, iteratee, context) { 21006 var result = Infinity, 21007 lastComputed = Infinity, 21008 value, 21009 computed; 21010 if (iteratee == null || typeof iteratee == 'number' && _typeof(obj[0]) != 'object' && obj != null) { 21011 obj = isArrayLike(obj) ? obj : values(obj); 21012 for (var i = 0, length = obj.length; i < length; i++) { 21013 value = obj[i]; 21014 if (value != null && value < result) { 21015 result = value; 21016 } 21017 } 21018 } else { 21019 iteratee = cb(iteratee, context); 21020 each(obj, function (v, index, list) { 21021 computed = iteratee(v, index, list); 21022 if (computed < lastComputed || computed === Infinity && result === Infinity) { 21023 result = v; 21024 lastComputed = computed; 21025 } 21026 }); 21027 } 21028 return result; 21029 } 21030 21031 // Safely create a real, live array from anything iterable. 21032 var reStrSymbol = /[^\ud800-\udfff]|[\ud800-\udbff][\udc00-\udfff]|[\ud800-\udfff]/g; 21033 function toArray(obj) { 21034 if (!obj) return []; 21035 if (isArray(obj)) return slice.call(obj); 21036 if (isString(obj)) { 21037 // Keep surrogate pair characters together. 21038 return obj.match(reStrSymbol); 21039 } 21040 if (isArrayLike(obj)) return map(obj, identity); 21041 return values(obj); 21042 } 21043 21044 // Sample **n** random values from a collection using the modern version of the 21045 // [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher–Yates_shuffle). 21046 // If **n** is not specified, returns a single random element. 21047 // The internal `guard` argument allows it to work with `_.map`. 21048 function sample(obj, n, guard) { 21049 if (n == null || guard) { 21050 if (!isArrayLike(obj)) obj = values(obj); 21051 return obj[random(obj.length - 1)]; 21052 } 21053 var sample = toArray(obj); 21054 var length = getLength(sample); 21055 n = Math.max(Math.min(n, length), 0); 21056 var last = length - 1; 21057 for (var index = 0; index < n; index++) { 21058 var rand = random(index, last); 21059 var temp = sample[index]; 21060 sample[index] = sample[rand]; 21061 sample[rand] = temp; 21062 } 21063 return sample.slice(0, n); 21064 } 21065 21066 // Shuffle a collection. 21067 function shuffle(obj) { 21068 return sample(obj, Infinity); 21069 } 21070 21071 // Sort the object's values by a criterion produced by an iteratee. 21072 function sortBy(obj, iteratee, context) { 21073 var index = 0; 21074 iteratee = cb(iteratee, context); 21075 return pluck(map(obj, function (value, key, list) { 21076 return { 21077 value: value, 21078 index: index++, 21079 criteria: iteratee(value, key, list) 21080 }; 21081 }).sort(function (left, right) { 21082 var a = left.criteria; 21083 var b = right.criteria; 21084 if (a !== b) { 21085 if (a > b || a === void 0) return 1; 21086 if (a < b || b === void 0) return -1; 21087 } 21088 return left.index - right.index; 21089 }), 'value'); 21090 } 21091 21092 // An internal function used for aggregate "group by" operations. 21093 function group(behavior, partition) { 21094 return function (obj, iteratee, context) { 21095 var result = partition ? [[], []] : {}; 21096 iteratee = cb(iteratee, context); 21097 each(obj, function (value, index) { 21098 var key = iteratee(value, index, obj); 21099 behavior(result, value, key); 21100 }); 21101 return result; 21102 }; 21103 } 21104 21105 // Groups the object's values by a criterion. Pass either a string attribute 21106 // to group by, or a function that returns the criterion. 21107 var groupBy = group(function (result, value, key) { 21108 if (has$1(result, key)) result[key].push(value);else result[key] = [value]; 21109 }); 21110 21111 // Indexes the object's values by a criterion, similar to `_.groupBy`, but for 21112 // when you know that your index values will be unique. 21113 var indexBy = group(function (result, value, key) { 21114 result[key] = value; 21115 }); 21116 21117 // Counts instances of an object that group by a certain criterion. Pass 21118 // either a string attribute to count by, or a function that returns the 21119 // criterion. 21120 var countBy = group(function (result, value, key) { 21121 if (has$1(result, key)) result[key]++;else result[key] = 1; 21122 }); 21123 21124 // Split a collection into two arrays: one whose elements all pass the given 21125 // truth test, and one whose elements all do not pass the truth test. 21126 var partition = group(function (result, value, pass) { 21127 result[pass ? 0 : 1].push(value); 21128 }, true); 21129 21130 // Return the number of elements in a collection. 21131 function size(obj) { 21132 if (obj == null) return 0; 21133 return isArrayLike(obj) ? obj.length : keys(obj).length; 21134 } 21135 21136 // Internal `_.pick` helper function to determine whether `key` is an enumerable 21137 // property name of `obj`. 21138 function keyInObj(value, key, obj) { 21139 return key in obj; 21140 } 21141 21142 // Return a copy of the object only containing the allowed properties. 21143 var pick = restArguments(function (obj, keys) { 21144 var result = {},
vendor: 8,825 bytes, lines 21145-21414
21145 iteratee = keys[0]; 21146 if (obj == null) return result; 21147 if (isFunction$1(iteratee)) { 21148 if (keys.length > 1) iteratee = optimizeCb(iteratee, keys[1]); 21149 keys = allKeys(obj); 21150 } else { 21151 iteratee = keyInObj; 21152 keys = flatten$1(keys, false, false); 21153 obj = Object(obj); 21154 } 21155 for (var i = 0, length = keys.length; i < length; i++) { 21156 var key = keys[i]; 21157 var value = obj[key]; 21158 if (iteratee(value, key, obj)) result[key] = value; 21159 } 21160 return result; 21161 }); 21162 21163 // Return a copy of the object without the disallowed properties. 21164 var omit = restArguments(function (obj, keys) { 21165 var iteratee = keys[0], 21166 context; 21167 if (isFunction$1(iteratee)) { 21168 iteratee = negate(iteratee); 21169 if (keys.length > 1) context = keys[1]; 21170 } else { 21171 keys = map(flatten$1(keys, false, false), String); 21172 iteratee = function iteratee(value, key) { 21173 return !contains(keys, key); 21174 }; 21175 } 21176 return pick(obj, iteratee, context); 21177 }); 21178 21179 // Returns everything but the last entry of the array. Especially useful on 21180 // the arguments object. Passing **n** will return all the values in 21181 // the array, excluding the last N. 21182 function initial(array, n, guard) { 21183 return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); 21184 } 21185 21186 // Get the first element of an array. Passing **n** will return the first N 21187 // values in the array. The **guard** check allows it to work with `_.map`. 21188 function first(array, n, guard) { 21189 if (array == null || array.length < 1) return n == null || guard ? void 0 : []; 21190 if (n == null || guard) return array[0]; 21191 return initial(array, array.length - n); 21192 } 21193 21194 // Returns everything but the first entry of the `array`. Especially useful on 21195 // the `arguments` object. Passing an **n** will return the rest N values in the 21196 // `array`. 21197 function rest(array, n, guard) { 21198 return slice.call(array, n == null || guard ? 1 : n); 21199 } 21200 21201 // Get the last element of an array. Passing **n** will return the last N 21202 // values in the array. 21203 function last(array, n, guard) { 21204 if (array == null || array.length < 1) return n == null || guard ? void 0 : []; 21205 if (n == null || guard) return array[array.length - 1]; 21206 return rest(array, Math.max(0, array.length - n)); 21207 } 21208 21209 // Trim out all falsy values from an array. 21210 function compact(array) { 21211 return filter(array, Boolean); 21212 } 21213 21214 // Flatten out an array, either recursively (by default), or up to `depth`. 21215 // Passing `true` or `false` as `depth` means `1` or `Infinity`, respectively. 21216 function flatten(array, depth) { 21217 return flatten$1(array, depth, false); 21218 } 21219 21220 // Take the difference between one array and a number of other arrays. 21221 // Only the elements present in just the first array will remain. 21222 var difference = restArguments(function (array, rest) { 21223 rest = flatten$1(rest, true, true); 21224 return filter(array, function (value) { 21225 return !contains(rest, value); 21226 }); 21227 }); 21228 21229 // Return a version of the array that does not contain the specified value(s). 21230 var without = restArguments(function (array, otherArrays) { 21231 return difference(array, otherArrays); 21232 }); 21233 21234 // Produce a duplicate-free version of the array. If the array has already 21235 // been sorted, you have the option of using a faster algorithm. 21236 // The faster algorithm will not work with an iteratee if the iteratee 21237 // is not a one-to-one function, so providing an iteratee will disable 21238 // the faster algorithm. 21239 function uniq(array, isSorted, iteratee, context) { 21240 if (!isBoolean(isSorted)) { 21241 context = iteratee; 21242 iteratee = isSorted; 21243 isSorted = false; 21244 } 21245 if (iteratee != null) iteratee = cb(iteratee, context); 21246 var result = []; 21247 var seen = []; 21248 for (var i = 0, length = getLength(array); i < length; i++) { 21249 var value = array[i], 21250 computed = iteratee ? iteratee(value, i, array) : value; 21251 if (isSorted && !iteratee) { 21252 if (!i || seen !== computed) result.push(value); 21253 seen = computed; 21254 } else if (iteratee) { 21255 if (!contains(seen, computed)) { 21256 seen.push(computed); 21257 result.push(value); 21258 } 21259 } else if (!contains(result, value)) { 21260 result.push(value); 21261 } 21262 } 21263 return result; 21264 } 21265 21266 // Produce an array that contains the union: each distinct element from all of 21267 // the passed-in arrays. 21268 var union = restArguments(function (arrays) { 21269 return uniq(flatten$1(arrays, true, true)); 21270 }); 21271 21272 // Produce an array that contains every item shared between all the 21273 // passed-in arrays. 21274 function intersection(array) { 21275 var result = []; 21276 var argsLength = arguments.length; 21277 for (var i = 0, length = getLength(array); i < length; i++) { 21278 var item = array[i]; 21279 if (contains(result, item)) continue; 21280 var j; 21281 for (j = 1; j < argsLength; j++) { 21282 if (!contains(arguments[j], item)) break; 21283 } 21284 if (j === argsLength) result.push(item); 21285 } 21286 return result; 21287 } 21288 21289 // Complement of zip. Unzip accepts an array of arrays and groups 21290 // each array's elements on shared indices. 21291 function unzip(array) { 21292 var length = array && max(array, getLength).length || 0; 21293 var result = Array(length); 21294 for (var index = 0; index < length; index++) { 21295 result[index] = pluck(array, index); 21296 } 21297 return result; 21298 } 21299 21300 // Zip together multiple lists into a single array -- elements that share 21301 // an index go together. 21302 var zip = restArguments(unzip); 21303 21304 // Converts lists into objects. Pass either a single array of `[key, value]` 21305 // pairs, or two parallel arrays of the same length -- one of keys, and one of 21306 // the corresponding values. Passing by pairs is the reverse of `_.pairs`. 21307 function object(list, values) { 21308 var result = {}; 21309 for (var i = 0, length = getLength(list); i < length; i++) { 21310 if (values) { 21311 result[list[i]] = values[i]; 21312 } else { 21313 result[list[i][0]] = list[i][1]; 21314 } 21315 } 21316 return result; 21317 } 21318 21319 // Generate an integer Array containing an arithmetic progression. A port of 21320 // the native Python `range()` function. See 21321 // [the Python documentation](https://docs.python.org/library/functions.html#range). 21322 function range(start, stop, step) { 21323 if (stop == null) { 21324 stop = start || 0; 21325 start = 0; 21326 } 21327 if (!step) { 21328 step = stop < start ? -1 : 1; 21329 } 21330 var length = Math.max(Math.ceil((stop - start) / step), 0); 21331 var range = Array(length); 21332 for (var idx = 0; idx < length; idx++, start += step) { 21333 range[idx] = start; 21334 } 21335 return range; 21336 } 21337 21338 // Chunk a single array into multiple arrays, each containing `count` or fewer 21339 // items. 21340 function chunk(array, count) { 21341 if (count == null || count < 1) return []; 21342 var result = []; 21343 var i = 0, 21344 length = array.length; 21345 while (i < length) { 21346 result.push(slice.call(array, i, i += count)); 21347 } 21348 return result; 21349 } 21350 21351 // Helper function to continue chaining intermediate results. 21352 function chainResult(instance, obj) { 21353 return instance._chain ? _$1(obj).chain() : obj; 21354 } 21355 21356 // Add your own custom functions to the Underscore object. 21357 function mixin(obj) { 21358 each(functions(obj), function (name) { 21359 var func = _$1[name] = obj[name]; 21360 _$1.prototype[name] = function () { 21361 var args = [this._wrapped]; 21362 push.apply(args, arguments); 21363 return chainResult(this, func.apply(_$1, args)); 21364 }; 21365 }); 21366 return _$1; 21367 } 21368 21369 // Add all mutator `Array` functions to the wrapper. 21370 each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function (name) { 21371 var method = ArrayProto[name]; 21372 _$1.prototype[name] = function () { 21373 var obj = this._wrapped; 21374 if (obj != null) { 21375 method.apply(obj, arguments); 21376 if ((name === 'shift' || name === 'splice') && obj.length === 0) { 21377 delete obj[0]; 21378 } 21379 } 21380 return chainResult(this, obj); 21381 }; 21382 }); 21383 21384 // Add all accessor `Array` functions to the wrapper. 21385 each(['concat', 'join', 'slice'], function (name) { 21386 var method = ArrayProto[name]; 21387 _$1.prototype[name] = function () { 21388 var obj = this._wrapped; 21389 if (obj != null) obj = method.apply(obj, arguments); 21390 return chainResult(this, obj); 21391 }; 21392 }); 21393 21394 // Named Exports 21395 21396 var allExports = { 21397 __proto__: null, 21398 VERSION: VERSION, 21399 restArguments: restArguments, 21400 isObject: isObject, 21401 isNull: isNull, 21402 isUndefined: isUndefined, 21403 isBoolean: isBoolean, 21404 isElement: isElement, 21405 isString: isString, 21406 isNumber: isNumber, 21407 isDate: isDate, 21408 isRegExp: isRegExp, 21409 isError: isError, 21410 isSymbol: isSymbol, 21411 isArrayBuffer: isArrayBuffer, 21412 isDataView: isDataView$1, 21413 isArray: isArray, 21414 isFunction: isFunction$1,
21415 isArguments: isArguments$1, 21416 isFinite: isFinite$1, 21417 isNaN: isNaN$1, 21418 isTypedArray: isTypedArray$1, 21419 isEmpty: isEmpty, 21420 isMatch: isMatch, 21421 isEqual: isEqual, 21422 isMap: isMap, 21423 isWeakMap: isWeakMap, 21424 isSet: isSet, 21425 isWeakSet: isWeakSet, 21426 keys: keys, 21427 allKeys: allKeys, 21428 values: values, 21429 pairs: pairs, 21430 invert: invert, 21431 functions: functions, 21432 methods: functions, 21433 extend: extend, 21434 extendOwn: extendOwn, 21435 assign: extendOwn, 21436 defaults: defaults, 21437 create: create, 21438 clone: clone, 21439 tap: tap, 21440 get: get, 21441 has: has, 21442 mapObject: mapObject, 21443 identity: identity, 21444 constant: constant, 21445 noop: noop, 21446 toPath: toPath$1, 21447 property: property, 21448 propertyOf: propertyOf, 21449 matcher: matcher, 21450 matches: matcher, 21451 times: times, 21452 random: random, 21453 now: now, 21454 escape: _escape, 21455 unescape: _unescape, 21456 templateSettings: templateSettings, 21457 template: template, 21458 result: result, 21459 uniqueId: uniqueId, 21460 chain: chain, 21461 iteratee: iteratee, 21462 partial: partial, 21463 bind: bind, 21464 bindAll: bindAll, 21465 memoize: memoize, 21466 delay: delay, 21467 defer: defer, 21468 throttle: throttle, 21469 debounce: debounce, 21470 wrap: wrap, 21471 negate: negate, 21472 compose: compose, 21473 after: after, 21474 before: before, 21475 once: once, 21476 findKey: findKey, 21477 findIndex: findIndex, 21478 findLastIndex: findLastIndex, 21479 sortedIndex: sortedIndex, 21480 indexOf: indexOf, 21481 lastIndexOf: lastIndexOf, 21482 find: find, 21483 detect: find, 21484 findWhere: findWhere, 21485 each: each, 21486 forEach: each, 21487 map: map, 21488 collect: map, 21489 reduce: reduce, 21490 foldl: reduce, 21491 inject: reduce, 21492 reduceRight: reduceRight, 21493 foldr: reduceRight, 21494 filter: filter, 21495 select: filter, 21496 reject: reject, 21497 every: every, 21498 all: every, 21499 some: some, 21500 any: some, 21501 contains: contains, 21502 includes: contains, 21503 include: contains, 21504 invoke: invoke, 21505 pluck: pluck, 21506 where: where, 21507 max: max, 21508 min: min, 21509 shuffle: shuffle, 21510 sample: sample, 21511 sortBy: sortBy, 21512 groupBy: groupBy, 21513 indexBy: indexBy, 21514 countBy: countBy, 21515 partition: partition, 21516 toArray: toArray, 21517 size: size, 21518 pick: pick, 21519 omit: omit, 21520 first: first, 21521 head: first, 21522 take: first, 21523 initial: initial, 21524 last: last, 21525 rest: rest, 21526 tail: rest, 21527 drop: rest, 21528 compact: compact, 21529 flatten: flatten, 21530 without: without, 21531 uniq: uniq, 21532 unique: uniq, 21533 union: union, 21534 intersection: intersection, 21535 difference: difference, 21536 unzip: unzip, 21537 transpose: unzip, 21538 zip: zip, 21539 object: object, 21540 range: range, 21541 chunk: chunk, 21542 mixin: mixin, 21543 'default': _$1 21544 }; 21545 21546 // Default Export 21547 21548 // Add all of the Underscore functions to the wrapper object. 21549 var _ = mixin(allExports); 21550 // Legacy Node.js API. 21551 _._ = _; 21552 return _; 21553}); 21554 21555}).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) 21556},{}],9:[function(require,module,exports){ 21557"use strict"; 21558 21559function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 21560function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } 21561function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } 21562function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } 21563function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 21564function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 21565require("slick-carousel"); 21566require("devbridge-autocomplete"); 21567window.globalError = ('nexansConfig' in window ? window.nexansConfig.errorMessage : '') || 'Sorry the request failed. Please try again later.'; 21568 21569// Require plugins
21570var jQueryCarousels = require('./plugins/jquery.carousels-simple.js'); 21571var jQueryCarouselsOverlay = require('./plugins/jquery.carousels-overlay.js'); 21572var jQueryGallery = require('./plugins/jquery.carousels-gallery.js'); 21573var jQueryFinance = require('./plugins/jquery.carousels-finance.js'); 21574 21575// Require modules. 21576var utils = require('./modules/utils.js'); 21577var grid = require('./modules/grid.js'); 21578var accordion = require('./modules/accordion.js'); 21579var sectorExpand = require('./modules/expand-sector.js'); 21580var panelExpand = require('./modules/expand-panel.js'); 21581var scrollAnchorGenerate = require('./modules/scrollAnchorGenerate.js'); 21582var scrollToAnchor = require('./modules/scrollToAnchor.js'); 21583var carousels = require('./modules/carousels.js'); 21584var gallery = require('./modules/gallery.js'); 21585var viewMore = require('./modules/view-more.js'); 21586var quicklinks = require('./modules/quick-access-icons.js'); 21587window.toggleIcon = require('./modules/toggleIcon.js'); 21588var toggleVideo = require('./modules/toggleVideo.js'); 21589var dragSlider = require('./modules/dragSlider.js'); 21590var fixHeight = require('./modules/fix-height.js'); 21591var MainNav = require('./modules/mainNav.js'); 21592var navigationPanel = require('./modules/navigation-panel.js'); 21593var changeList = require('./modules/change-list.js'); 21594var fullPage = require('./modules/fullpage-slider.js'); 21595var addPadding = require('./modules/addPadding.js'); 21596var newsList = require('./modules/news-list.js'); 21597var filterList = require('./modules/filter-subnav.js'); 21598var responsiveTables = require('./modules/responsive-table.js'); 21599var modal = require('./modules/modal.js'); 21600var subscribeNewsletter = require('./modules/suscribe-newsletter.js'); 21601var tableselect = require('./modules/tableselect.js'); 21602var tabs = require('./modules/tabs.js');
21603var cookies = require('./modules/cookies.js'); 21604var showAccount = require('./modules/showAccount.js'); 21605var showSearch = require('./modules/showSearch.js'); 21606var showSubnav = require('./modules/showSubnav.js'); 21607var searchFilters = require('./modules/search-filters.js'); 21608window.menuDropdowns = require('./modules/menuDropdowns.js'); 21609var coverParallax = require('./modules/coverParallax.js'); 21610var docLists = require('./modules/docLists.js'); 21611var actionsMenu = require('./modules/actionsMenu.js'); 21612var truncate = require('./modules/truncate.js'); 21613var sticky = require('./modules/sticky.js'); 21614var rteArray = require('./modules/rteArray.js'); 21615var sharePrice = require('./modules/sharePrice.js'); 21616var redirect = require('./modules/redirect.js'); 21617var asyncForms = require('./modules/asyncForms.js'); 21618var askMail = require('./modules/ask-mail.js'); 21619var storage = require('./modules/storage.js'); 21620var autocomplete = require('./modules/autocomplete.js'); 21621var eshop = require('./modules/eshop.js'); 21622var retailers = require('./modules/retailers.js'); 21623var formValidation = require('./modules/form-validation.js'); 21624var formReset = require('./modules/form-reset.js'); 21625var dealerLocator = require('./modules/dealerLocator.js'); 21626 21627// panels 21628var panelProduct = require('./modules/panel-products.js'); 21629var panelGovernance = require('./modules/panel-governance.js'); 21630var panelSolutions = require('./modules/panel-solutions.js'); 21631var panelContact = require('./modules/panel-contact.js'); 21632var panelComparator = require('./modules/panel-comparator.js'); 21633var contactForm = require('./modules/panel-contact-form.js'); 21634var contactFormSpe = require('./modules/panel-contact-spe-form.js'); 21635var panelDop = require('./modules/panel-dop.js'); 21636var panelNewsletter = require('./modules/panel-newsletter.js'); 21637var panelLogin = require('./modules/panel-login.js'); 21638var panelStock = require('./modules/panel-stock.js'); 21639var panels = require('./modules/panels.js'); 21640$(function ($) { 21641 // needs to be called first 21642 if ($('.js-form-validation').length) { 21643 formValidation.init(); 21644 } 21645 if ($('.js-form-reset').length) { 21646 formReset.init(); 21647 } 21648 21649 // Utilitaires. 21650 utils.init(); 21651 carousels.init(); 21652 21653 // Gallery. 21654 gallery.init(); 21655 21656 // Grid. 21657 if ($('.js-dev-grid').length) { 21658 grid.init(); 21659 } 21660 21661 /* Accordion */ 21662 if ($('.js-accordion').length) { 21663 accordion.init(); 21664 } 21665 21666 /* Expand sector */ 21667 if ($('.js-expand-sector').length) { 21668 sectorExpand.init(); 21669 } 21670 21671 /* scroll to */ 21672 if ($('.js-scroll-anchor-generate').length) { 21673 scrollAnchorGenerate.init(); 21674 } 21675 21676 /* scroll to */ 21677 if ($('.js-scroll-to-trigger').length) { 21678 scrollToAnchor.init(); 21679 } 21680 21681 /* panelExpand */ 21682 if ($('.js-open-panel').length) { 21683 panelExpand.init(); 21684 } 21685 21686 /* load data panel */ 21687 if ($('.js-load-product').length) { 21688 panelProduct.init(); 21689 } 21690 if ($('.js-drag-slider').length) { 21691 dragSlider.init(); 21692 } 21693 if ($('.js-push-quick-access').length) { 21694 quicklinks.init(); 21695 } 21696 ; 21697 21698 // fixHeight 21699 if ($('.js-fix-height').length) { 21700 fixHeight.init(); 21701 } 21702 window.toggleIcon.init(storage); 21703 if ($('.box--video').length) { 21704 toggleVideo.init(); 21705 } 21706 if ($('.js-gp-panel').length) { 21707 panelGovernance.init(); 21708 } 21709 if ($('.js-panel-solution').length) { 21710 panelSolutions.init(); 21711 } 21712 if ($('.js-panel-newsletter').length) { 21713 panelNewsletter.init(); 21714 subscribeNewsletter.init(); 21715 } 21716 if ($('.js-user-login-form').length) { 21717 panelLogin.init(); 21718 } 21719 if ($('.js-panel-comparator').length) { 21720 panelComparator.init(storage.comparator); 21721 } 21722 if ($('.js-panel-trigger-stock').length) { 21723 panelStock.init(); 21724 } 21725 if ($('.js-panel').length) { 21726 panels.init(); 21727 } 21728 if ($('.js-change-list-container').length && $('.js-change-list-link').length) { 21729 changeList.init(); 21730 } 21731 if ($('.js-padding').length) { 21732 addPadding.init(); 21733 } 21734 if ($('.js-fullpage-slider').length) { 21735 fullPage.init(); 21736 }
21737 viewMore.init(); 21738 if ($('.js-news-list').length) { 21739 newsList.init(); 21740 } 21741 if ($('.js-result-filters-container').length) { 21742 searchFilters.init(); 21743 } 21744 if ($('.js-responsive-table').length) { 21745 responsiveTables.init(); 21746 } 21747 if ($('.js-filter').length) { 21748 filterList.init(); 21749 } 21750 if ($('.js-panel-contact').length && $('.js-panel-contact-spe')) { 21751 panelContact.init(); 21752 contactForm.init(); 21753 } 21754 if ($('.js-panel-contact-spe').length) { 21755 contactFormSpe.init(); 21756 } 21757 if ($('.js-panel-dop').length) { 21758 panelDop.init(); 21759 } 21760 if ($('.js-modal').length) { 21761 modal.init(); 21762 } 21763 if ($('.js-tabs').length) { 21764 tabs.init(); 21765 } 21766 if ($('.js-tableselect').length) { 21767 tableselect.init(); 21768 } 21769 if ($('.js-cookies').length) { 21770 cookies.init(); 21771 } 21772 if ($('.js-account').length) { 21773 showAccount.init(); 21774 } 21775 if ($('.js-search').length) { 21776 showSearch.init(); 21777 } 21778 if ($('.js-show-subnav').length) { 21779 showSubnav.init(); 21780 } 21781 if ($('.js-dropdown').length) { 21782 window.menuDropdowns.init(); 21783 } 21784 if ($('.js-parallax').length) { 21785 coverParallax.init(); 21786 } 21787 if ($('.js-doc-list-container').length) { 21788 docLists.init(); 21789 } 21790 if ($('.js-actions-menu').length) { 21791 actionsMenu.init(); 21792 } 21793 if ($('.js-truncate').length) { 21794 truncate.init(); 21795 } 21796 if ($('.js-sticky').length) { 21797 sticky.init(); 21798 } 21799 if ($('.js-menu-panel').length) { 21800 navigationPanel.init(); 21801 } 21802 if ($('div.rte-array').length) { 21803 rteArray.init(); 21804 } 21805 if ($('select.js-redirect').length) { 21806 redirect.init(); 21807 } 21808 asyncForms.init(); 21809 if ($('.js-ask-mail').length) { 21810 askMail.init(); 21811 } 21812 if ($('.js-autocomplete').length) { 21813 autocomplete.init(); 21814 } 21815 if ($('.carousel__wrapper').length) { 21816 $('.carousel__wrapper').each(function () { 21817 var slickSettings = $(this).data('slick'); 21818 var $this = $(this); 21819 if ($(this).hasClass('carousel__small')) { 21820 $(this).on('init breakpoint', function (event, slick, direction) { 21821 if (slick.options.slidesToShow >= slick.slideCount) { 21822 if (!$this.hasClass('no-slide')) { 21823 $this.addClass('no-slide'); 21824 } 21825 } else { 21826 $this.removeClass('no-slide'); 21827 } 21828 }).slick(_objectSpread(_defineProperty(_defineProperty(_defineProperty({ 21829 slidesToShow: 1, 21830 slidesToScroll: 1, 21831 dots: true, 21832 infinite: true, 21833 arrows: true, 21834 fade: false, 21835 cssEase: 'linear', 21836 autoplay: true, 21837 autoplaySpeed: 5000 21838 }, "infinite", false), "speed", 600), "responsive", [{ 21839 breakpoint: 850, 21840 settings: { 21841 arrows: false, 21842 dots: true, 21843 fade: false 21844 } 21845 }]), slickSettings)); 21846 } else { 21847 $(this).on('init breakpoint', function (event, slick, direction) { 21848 console.log('slick.options.slidesToShow >= slick.slideCoun', slick.options.slidesToShow, slick.slideCount); 21849 if (slick.options.slidesToShow >= slick.slideCount) { 21850 if (!$this.hasClass('no-slide')) { 21851 $this.addClass('no-slide'); 21852 } 21853 } else { 21854 $this.removeClass('no-slide'); 21855 } 21856 }).slick(_objectSpread({ 21857 slidesToShow: 1, 21858 slidesToScroll: 1, 21859 arrows: true, 21860 fade: false, 21861 cssEase: 'linear', 21862 asNavFor: '.carousel__nav', 21863 autoplay: true, 21864 autoplaySpeed: 5000, 21865 infinite: false, 21866 speed: 600, 21867 responsive: [{ 21868 breakpoint: 850, 21869 settings: { 21870 arrows: false, 21871 dots: true, 21872 fade: false 21873 } 21874 }] 21875 }, slickSettings)); 21876 } 21877 }); 21878 } 21879 if ($('.carousel__nav').length) { 21880 $('.carousel__nav').slick({ 21881 slidesToShow: 4, 21882 slidesToScroll: 1, 21883 asNavFor: '.carousel__wrapper', 21884 arrows: false, 21885 infinite: false, 21886 dots: false, 21887 centerMode: false, 21888 focusOnSelect: true, 21889 draggable: true 21890 }); 21891 } 21892 21893 // Navigation 21894 new MainNav(); 21895 21896 // sharePrice 21897 sharePrice.init(); 21898 21899 // eshop 21900 eshop.init(asyncForms); 21901 retailers.init(asyncForms); 21902 21903 // dealerlocator 21904 dealerLocator.init(); 21905 $('select.language-select').change(function () { 21906 var newLanguage = $(this).val(); 21907 if (newLanguage && newLanguage != window.nexansConfig.language) { 21908 var uri = window.location.href; 21909 var domainRe = /.*:\/\/[^\/]*/i; 21910 uri = uri.replace(domainRe, ""); 21911 if (uri.match(".*/" + window.nexansConfig.language + "/.*")) { 21912 uri = uri.replace("/" + window.nexansConfig.language + "/", "/" + newLanguage + "/"); 21913 } else { 21914 uri = uri.substr(uri.indexOf(window.nexansConfig.contextPath) + window.nexansConfig.contextPath.length); 21915 uri = window.nexansConfig.contextPath + "/" + newLanguage + uri; 21916 } 21917 window.location.href = uri; 21918 } 21919 }); 21920 $('ul.language--list a').click(function (e) { 21921 e.preventDefault(); 21922 var newLanguage = $(this).data('language'); 21923 if (newLanguage && newLanguage != window.nexansConfig.language) { 21924 var uri = window.location.href; 21925 var domainRe = /.*:\/\/[^\/]*/i; 21926 uri = uri.replace(domainRe, ""); 21927 if (uri.match(".*/" + window.nexansConfig.language + "/.*")) { 21928 uri = uri.replace("/" + window.nexansConfig.language + "/", "/" + newLanguage + "/"); 21929 } else { 21930 uri = uri.substr(uri.indexOf(window.nexansConfig.contextPath) + window.nexansConfig.contextPath.length); 21931 uri = window.nexansConfig.contextPath + "/" + newLanguage + uri; 21932 } 21933 window.location.href = uri; 21934 } 21935 }); 21936 $('body:not(.editMode) div.b2b-link-list').each(function () { 21937 if ($(this).find('li').length == 0) { 21938 $(this).remove(); 21939 } 21940 }); 21941 $(document).trigger('uiLoaded'); 21942}); 21943 21944},{"./modules/accordion.js":10,"./modules/actionsMenu.js":11,"./modules/addPadding.js":12,"./modules/ask-mail.js":13,"./modules/asyncForms.js":14,"./modules/autocomplete.js":15,"./modules/carousels.js":16,"./modules/change-list.js":17,"./modules/cookie
21944s.js":18,"./modules/coverParallax.js":19,"./modules/dealerLocator.js":20,"./modules/docLists.js":21,"./modules/dragSlider.js":22,"./modules/eshop.js":23,"./modules/expand-panel.js":24,"./modules/expand-sector.js":25,"./modules/filter-subnav.js":26,"./modules/fix-height.js":27,"./modules/form-reset.js":28,"./modules/form-validation.js":29,"./modules/fullpage-slider.js":30,"./modules/gallery.js":31,"./modules/grid.js":32,"./modules/mainNav.js":33,"./modules/menuDropdowns.js":34,"./modules/modal.js":36,"./modules/navigation-panel.js":38,"./modules/news-list.js":39,"./modules/panel-comparator.js":40,"./modules/panel-contact-form.js":41,"./modules/panel-contact-spe-form.js":42,"./modules/panel-contact.js":43,"./modules/panel-dop.js":44,"./modules/panel-governance.js":45,"./modules/panel-login.js":46,"./modules/panel-newsletter.js":47,"./modules/panel-products.js":48,"./modules/panel-solutions.js":49,"./modules/panel-stock.js":50,"./modules/panels.js":51,"./modules/quick-access-icons.js":52,"./modules/redirect.js":53,"./modules/responsive-table.js":54,"./modules/retailers.js":55,"./modules/rteArray.js":56,"./modules/scrollAnchorGenerate.js":57,"./modules/scrollToAnchor.js":58,"./modules/search-filters.js":59,"./modules/sharePrice.js":60,"./modules/showAccount.js":61,"./modules/showSearch.js":62,"./modules/showSubnav.js":63,"./modules/sticky.js":64,"./modules/storage.js":65,"./modules/suscribe-newsletter.js":66,"./modules/tableselect.js":67,"./modules/tabs.js":68,"./modules/toggleIcon.js":69,"./modules/toggleVideo.js":70,"./modules/truncate.js":71,"./modules/utils.js":72,"./modules/view-more.js":73,"./plugins/jquery.carousels-finance.js":74,"./plugins/jquery.carousels-gallery.js":75,"./plugins/jquery.carousels-overlay.js":76,"./plugins/jquery.carousels-simple.js":77,"devbridge-autocomplete":1,"slick-carousel":7}],10:[function(require,module,exports){ 21945"use strict"; 21946 21947var accordion = { 21948 ui: {}, 21949 init: function init() { 21950 this.bindUI(); 21951 this.bindEvents(); 21952 }, 21953 bindUI: function bindUI() { 21954 this.ui.$btnExpand = $('.js-accordion-trigger'); 21955 }, 21956 bindEvents: function bindEvents() { 21957 this.ui.$btnExpand.on('click', $.proxy(this.expandSection, this)); 21958 }, 21959 expandSection: function expandSection(e) { 21960 var $wrapper = $(e.currentTarget).closest('.js-accordion-wrapper'); 21961 var $content = $wrapper.find('.js-accordion-content').first(); 21962 $content.stop().slideToggle(); 21963 if ($(e.currentTarget).hasClass('js-accordion-trigger-hide')) { 21964 $(e.currentTarget).hide(); 21965 } 21966 $wrapper.toggleClass('is-open'); 21967 } 21968}; 21969module.exports = accordion; 21970 21971},{}],11:[function(require,module,exports){ 21972"use strict"; 21973 21974var actionsMenu = { 21975 ui: {}, 21976 init: function init() { 21977 this.bindUI(); 21978 this.bindEvents(); 21979 }, 21980 bindUI: function bindUI() { 21981 this.ui.$wrapper = $('.js-actions-menu'); 21982 this.ui.$trigger = $('.js-actions-details-toggle'); 21983 this.ui.$content = $('.js-actions-details'); 21984 }, 21985 bindEvents: function bindEvents() { 21986 this.ui.$trigger.on('click', $.proxy(this.toggleDetails, this)); 21987 }, 21988 toggleDetails: function toggleDetails(e) { 21989 this.ui.$content.stop().slideToggle(); 21990 this.ui.$trigger.toggleClass('is-open'); 21991 } 21992}; 21993module.exports = actionsMenu; 21994 21995},{}],12:[function(require,module,exports){ 21996"use strict"; 21997 21998var addPadding = { 21999 ui: {}, 22000 init: function init() { 22001 this.bindUI(); 22002 this.bindEvents(); 22003 this.paddingHandler(); 22004 }, 22005 bindUI: function bindUI() { 22006 this.ui.$win = $(window); 22007 this.ui.$body = $('body'); 22008 this.ui.$wrap = $('.main-wrapper'); 22009 this.ui.$grid = $('.grid'); 22010 this.ui.$container = $('.js-padding'); 22011 }, 22012 bindEvents: function bindEvents() { 22013 this.ui.$win.on('resize', $.proxy(this.paddingHandler, this)); 22014 }, 22015 paddingHandler: function paddingHandler() { 22016 var wrapW = this.ui.$wrap.outerWidth(); 22017 var gridW = this.ui.$grid.outerWidth(); 22018 var result = (wrapW - gridW) / 2; 22019 var $item = this.ui.$container.find('.js-padding-item'); 22020 if (this.isMobileTablet()) { 22021 $item.css('padding', 0); 22022 return; 22023 } 22024 $.each($item, function () { 22025 var direction = $(this).data('padding'); 22026 if (direction === 'left') { 22027 $(this).css('padding-left', result); 22028 } else { 22029 $(this).css('padding-right', result); 22030 } 22031 }); 22032 }, 22033 isMobileTablet: function isMobileTablet() { 22034 if (this.ui.$win.outerWidth() <= 1023) { 22035 return true; 22036 } else { 22037 return false;
22038 } 22039 } 22040}; 22041module.exports = addPadding; 22042 22043},{}],13:[function(require,module,exports){ 22044"use strict"; 22045 22046function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 22047function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 22048function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 22049function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 22050function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 22051function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 22052var Modal = require('./modalAdd.js'); 22053var AskMailBtn = /*#__PURE__*/function () { 22054 function AskMailBtn(el) { 22055 _classCallCheck(this, AskMailBtn); 22056 this.el = el; 22057 this.$el = $(el); 22058 this.$template = this.$el.find('.ask-mail-form'); 22059 this.bind(); 22060 } 22061 return _createClass(AskMailBtn, [{ 22062 key: "bind", 22063 value: function bind() { 22064 var self = this; 22065 this.$el.on('click', function (e) { 22066 e.preventDefault(); 22067 new Modal({ 22068 content: self.$template.html(), 22069 classes: ['modal--large'] 22070 }); 22071 }); 22072 } 22073 }]); 22074}(); 22075var askMail = { 22076 init: function init() { 22077 $('.js-ask-mail').each(function () { 22078 $(this).data('askMail', new AskMailBtn(this)); 22079 }); 22080 } 22081}; 22082module.exports = askMail; 22083 22084},{"./modalAdd.js":37}],14:[function(require,module,exports){ 22085"use strict"; 22086 22087function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 22088function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 22089function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 22090function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 22091function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 22092function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 22093var _require = require("./panel-contact-form"), 22094 initElements = _require.initElements; 22095function formToJson($el) { 22096 var data = $el.serializeArray(); 22097 var output = {}; 22098 for (var i = 0; i < data.length; i++) { 22099 if (data[i].name in output) { 22100 if (Array.isArray(output[data[i].name])) { 22101 output[data[i].name].push(data[i].value); 22102 } else { 22103 output[data[i].name] = [output[data[i].name], data[i].value]; 22104 } 22105 } else { 22106 output[data[i].name] = data[i].value; 22107 } 22108 } 22109 return JSON.stringify(output); 22110} 22111var AsyncForm = /*#__PURE__*/function () { 22112 function AsyncForm(el) { 22113 _classCallCheck(this, AsyncForm); 22114 this.el = el; 22115 this.$el = $(el); 22116 this.isSubmitting = false;
22117 this.successType = this.$el.data('success-type') || 'prepend'; 22118 this.failMsg = this.$el.data('fail') || window.globalError; 22119 this.overlay = '<div class="form-overlay"></div>'; 22120 this.$overlay = null; 22121 this.method = this.$el.attr('method') || 'POST'; 22122 this.success = null; 22123 this.sentData = null; 22124 this.alwaysDisplayMessage = false; 22125 var self = this; 22126 this.valueBuilder = function (asyncForm, submitter) { 22127 if (self.contentType === 'application/json') { 22128 return formToJson(self.$el); 22129 } 22130 return new FormData(asyncForm.el); 22131 }; 22132 this.contentType = this.$el.data('content-type') || false; 22133 this.processData = false; 22134 this.onBeforeSendCheck = null; 22135 this.$submitActors = this.$el.find('[type=submit]'); 22136 this.submitActor = null; 22137 this.bind(); 22138 } 22139 return _createClass(AsyncForm, [{ 22140 key: "bind", 22141 value: function bind() { 22142 var self = this; 22143 this.$submitActors.on('click', function () { 22144 self.submitActor = this; 22145 }); 22146 this.$el.on('submit', function (e) { 22147 e.preventDefault(); 22148 self.submit(e); 22149 }); 22150 } 22151 }, { 22152 key: "submit", 22153 value: function submit(event) { 22154 if (null === this.submitActor) { 22155 this.submitActor = this.$submitActors[0]; 22156 } 22157 if (!this.isSubmitting) { 22158 this.isSubmitting = true; 22159 this.$el.addClass('loading'); 22160 this.$el.find('.message-box, .async-error-msg').remove(); 22161 this.$el.find('.form-group.has-error').removeClass('has-error'); 22162 var values = {}; 22163 var submitter = event.submitter; 22164 if (!submitter && event.originalEvent) submitter = event.originalEvent.submitter; 22165 if (!!submitter && !!$(submitter).data('asyncForm-valueBuilder')) { 22166 values = $(submitter).data('asyncForm-valueBuilder').call(this, this, submitter); 22167 } else if (this.valueBuilder != null) { 22168 values = this.valueBuilder.call(this, this, null); 22169 } 22170 this.sentData = this.$el.serializeArray(); 22171 if (this.onBeforeSendCheck === null || this.onBeforeSendCheck.call(this)) { 22172 var settings = { 22173 url: this.$el.attr('action'), 22174 type: this.method, 22175 processData: this.processData, 22176 contentType: this.contentType, 22177 data: values 22178 }; 22179 if (this.$el.hasClass('js-async-form-pdf') || $(this.submitActor).hasClass('js-submit-pdf')) { 22180 settings.xhrFields = { 22181 responseType: 'blob' 22182 }; 22183 } 22184 this.sentData = settings.data; 22185 $.ajax(settings).done(this.done.bind(this)).fail(this.fail.bind(this)); 22186 } else { 22187 this.isSubmitting = false; 22188 this.$el.removeClass('loading'); 22189 } 22190 } 22191 } 22192 }, { 22193 key: "done", 22194 value: function done(data, textStatus, jqXHR) { 22195 var _this = this; 22196 var continueSubmitting = false; 22197 var contentType = jqXHR.getResponseHeader("Content-Type"); 22198 if (contentType.match(/application\/(?:pdf|vnd\.ms-excel)/)) { 22199 var blob = new Blob([data], { 22200 type: contentType 22201 }); 22202 if (window.navigator && window.navigator.msSaveOrOpenBlob) { 22203 window.navigator.msSaveOrOpenBlob(blob); 22204 } else { 22205 var contentDisposition = jqXHR.getResponseHeader("Content-Disposition"); 22206 var filename = null; 22207 var reUtf = /filename\*\s*=\s*(UTF-\d['"]*)?((['"]).*?[.]$\2|[^;\n]*)?/; 22208 var matchsUtf = contentDisposition.match(reUtf); 22209 if (matchsUtf && matchsUtf.length > 2 && matchsUtf[1] == "UTF-8''") { 22210 filename = decodeURIComponent(matchsUtf[2]); 22211 } 22212 if (!filename) { 22213 var re = /filename\s*=\s*((['"]).*?[.]$\2|[^;\n]*)?/; 22214 var matchs = contentDisposition.match(re); 22215 if (matchs && matchs.length > 1) { 22216 filename = decodeURIComponent(matchs[1].replace(/^"+|"+$/g, '')); 22217 } 22218 } 22219 var link = document.createElement('a'); 22220 link.href = window.URL.createObjectURL(blob); 22221 link.download = filename || this.$el.data('filename'); 22222 link.click(); 22223 setTimeout(function () { 22224 // For Firefox it is necessary to delay revoking the ObjectURL 22225 window.URL.revokeObjectURL(data); 22226 }, 100); 22227 } 22228 } else if (typeof data === 'string') { 22229 this.$el.html(data); 22230 } else { 22231 if ("success" in data && data.success) { 22232 var displayMessage = true; 22233 if (this.success !== null) { 22234 this.success.call(this, data, textStatus, jqXHR); 22235 displayMessage = this.alwaysDisplayMessage || false; // if specific callback, then message won't be displayed unless 'alwaysDisplayMessage' 22236 } else if ("redirect" in data && data.redirect) { 22237 if (data.redirect === 'reload') { 22238 document.location.reload(); 22239 } else { 22240 document.location = data.redirect; 22241 } 22242 } 22243 if (!!displayMessage) { 22244 switch (this.successType) { 22245 case 'prepend': 22246 this.$el.prepend('<div class="message-box message-box--info">' + data.message + '</div>'); 22247 break; 22248 case 'replace': 22249 this.$el.html(data.message); 22250 break; 22251 case 'append': 22252 this.$el.append('<div class="message-box message-box--info">' + data.message + '</div>'); 22253 break; 22254 } 22255 } 22256 } else if ('message' in data && data.message || 'errors' in data && data.errors.length > 0) { 22257 if ('message' in data && data.message) { 22258 this.$el.prepend('<div class="message-box message-box--error">' + data.message + '</div>'); 22259 } 22260 if ('errors' in data && data.errors.length > 0) { 22261 var _loop = function _loop(i) { 22262 _this.$el.find('[name="' + data.errors[i].field + '"]').each(function () { 22263 var formGroup = $(this).parents('.form-group'); 22264 formGroup.addClass('has-error'); 22265 if ('error' in data.errors[i]) { 22266 formGroup.append('<div class="async-error-msg">' + data.errors[i].error + '</div>'); 22267 } 22268 }); 22269 }; 22270 for (var i = 0; i < data.errors.length; i++) { 22271 _loop(i); 22272 } 22273 } 22274 } else { 22275 this.fail(); 22276 } 22277 } 22278 if (!continueSubmitting) { 22279 this.isSubmitting = false;
22280 this.$el.removeClass('loading'); 22281 } 22282 } 22283 }, { 22284 key: "fail", 22285 value: function fail(data, textStatus, jqXHR) { 22286 this.$el.prepend('<div class="message-box message-box--error">' + this.failMsg + '</div>'); 22287 this.isSubmitting = false; 22288 this.$el.removeClass('loading'); 22289 } 22290 }]); 22291}(); 22292var asyncForms = { 22293 init: function init() { 22294 $('.js-async-form').each(function () { 22295 $(this).data('asyncForm', new AsyncForm(this)); 22296 }); 22297 $(document).on('async-form', function (e, el, cb) { 22298 var async = new AsyncForm(el); 22299 $(el).data('asyncForm', async); 22300 if (cb) { 22301 cb(async); 22302 } 22303 }); 22304 }, 22305 initElement: function initElement(el) { 22306 return new AsyncForm(el); 22307 } 22308}; 22309module.exports = asyncForms; 22310 22311},{"./panel-contact-form":41}],15:[function(require,module,exports){ 22312"use strict"; 22313 22314function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 22315function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 22316function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 22317function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 22318function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 22319function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 22320var AutocompleteInput = /*#__PURE__*/function () { 22321 function AutocompleteInput(el) { 22322 _classCallCheck(this, AutocompleteInput); 22323 this.$el = $(el); 22324 this.settings = $.extend({ 22325 url: '', 22326 min: 4 22327 }, this.$el.data()); 22328 this.$el.wrap('<div class="autocomplete-container"></div>'); 22329 this.$container = this.$el.parent(); 22330 this.bind(); 22331 } 22332 return _createClass(AutocompleteInput, [{ 22333 key: "bind", 22334 value: function bind() { 22335 var self = this; 22336 this.$el.autocomplete({ 22337 minChars: this.settings.min, 22338 serviceUrl: this.settings.url, 22339 formatResult: function formatResult(suggestion, currentValue) { 22340 return suggestion.data; 22341 }, 22342 onSearchStart: function onSearchStart(params) { 22343 self.start(); 22344 }, 22345 onSearchComplete: function onSearchComplete(query, suggestions) { 22346 self.complete(); 22347 } 22348 }); 22349 } 22350 }, { 22351 key: "start", 22352 value: function start() { 22353 this.$container.append('<div class="loader"></div>'); 22354 } 22355 }, { 22356 key: "complete", 22357 value: function complete() { 22358 this.$container.find('.loader').remove(); 22359 } 22360 }]); 22361}(); 22362var autocomplete = { 22363 init: function init() { 22364 $('.js-autocomplete').each(function () { 22365 new AutocompleteInput(this); 22366 }); 22367 } 22368}; 22369module.exports = autocomplete; 22370 22371},{}],16:[function(require,module,exports){ 22372"use strict"; 22373 22374(function ($) { 22375 var carousel = { 22376 init: function init() { 22377 $.each($('.js-carousel-simple'), function () { 22378 $(this).carouselSimple(); 22379 }); 22380 $.each($('.js-carousel-overlay'), function () { 22381 $(this).carouselOverlay(); 22382 }); 22383 $.each($('.js-carousel-gallery'), function () { 22384 $(this).carouselGallery(); 22385 }); 22386 $.each($('.js-carousel-finance'), function () { 22387 $(this).carouselFinance(); 22388 }); 22389 } 22390 }; 22391 module.exports = carousel; 22392})(jQuery); 22393 22394},{}],17:[function(require,module,exports){ 22395"use strict"; 22396 22397var changeList = { 22398 ui: {},
22399 init: function init() { 22400 this.bindUI(); 22401 this.bindEvents(); 22402 }, 22403 bindUI: function bindUI() { 22404 this.ui.$win = $(window); 22405 this.ui.$body = $('body'); 22406 this.ui.$links = $('.js-change-list-link'); 22407 this.ui.$lists = $('.js-change-list'); 22408 this.ui.$container = $('.js-change-list-container'); 22409 this.ui.$select = $('.js-change-list-select'); 22410 }, 22411 bindEvents: function bindEvents() { 22412 this.ui.$links.on('click', $.proxy(this.clickHandler, this)); 22413 this.ui.$select.on('change', $.proxy(this.changeHandler, this)); 22414 }, 22415 clickHandler: function clickHandler(e) { 22416 e.preventDefault(); 22417 var $el = $(e.currentTarget), 22418 data = $el.data('list'), 22419 $currentList = this.ui.$container.find('.js-change-list[data-list=' + data + ']'); 22420 this.ui.$lists.removeClass('active'); 22421 $currentList.addClass('active'); 22422 }, 22423 changeHandler: function changeHandler(e) { 22424 var $el = $(e.currentTarget), 22425 data = $el.val(), 22426 $currentList = this.ui.$container.find('.js-change-list[data-list=' + data + ']'); 22427 this.ui.$lists.removeClass('active'); 22428 $currentList.addClass('active'); 22429 } 22430}; 22431module.exports = changeList; 22432 22433},{}],18:[function(require,module,exports){ 22434"use strict"; 22435 22436var cookies = { 22437 ui: {}, 22438 cookieName: 'cookiesAllowed', 22439 init: function init() { 22440 this.bindUI(); 22441 this.bindEvents(); 22442 }, 22443 bindUI: function bindUI() { 22444 this.ui.$cookies = $('.js-cookies'); 22445 this.ui.$accept = this.ui.$cookies.find('.js-cookies-accept'); 22446 this.ui.$deny = this.ui.$cookies.find('.js-cookies-deny'); 22447 }, 22448 bindEvents: function bindEvents() { 22449 // If the cookies are not set, show the banner. 22450 var cookieVal = this.getCookie(this.cookieName); 22451 if (cookieVal !== 'true' && cookieVal !== 'false') { 22452 this.showBanner(); 22453 } 22454 22455 // On click on the close btn, close the banner and set the cookies. 22456 this.ui.$accept.on('click', this.accept.bind(this)); 22457 this.ui.$deny.on('click', this.deny.bind(this)); 22458 }, 22459 showBanner: function showBanner() { 22460 this.ui.$cookies.removeClass('is-hidden'); 22461 }, 22462 accept: function accept(e) { 22463 // Prevent default. 22464 e.preventDefault(); 22465 22466 // Hide cookies. 22467 this.ui.$cookies.addClass('is-hidden'); 22468 setTracking(); 22469 22470 // Set the cookies. 22471 this.setCookies('true'); 22472 }, 22473 deny: function deny(e) { 22474 // Prevent default. 22475 e.preventDefault(); 22476 22477 // Hide cookies. 22478 this.ui.$cookies.addClass('is-hidden'); 22479 22480 // Set the cookies. 22481 this.setCookies('false'); 22482 }, 22483 setCookies: function setCookies(value) { 22484 var today = new Date(), 22485 expires = new Date(); 22486 22487 // Set the expire date. 22488 expires.setTime(today.getTime() + 3600 * 1000 * 24 * 30 * 13); 22489 22490 // Write the cookie. 22491 document.cookie = this.cookieName + "=" + value + ";path=/;expires=" + expires.toGMTString(); 22492 }, 22493 getCookie: function getCookie(name) { 22494 var _document$cookie$matc; 22495 return ((_document$cookie$matc = document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)')) === null || _document$cookie$matc === void 0 ? void 0 : _document$cookie$matc.pop()) || ''; 22496 } 22497}; 22498module.exports = cookies; 22499 22500},{}],19:[function(require,module,exports){ 22501"use strict"; 22502 22503var coverParallax = { 22504 ui: {}, 22505 isScrolling: false, 22506 reversed: false, 22507 lastScroll: 0, 22508 init: function init() { 22509 this.bindUI(); 22510 this.bindEvents(); 22511 }, 22512 bindUI: function bindUI() { 22513 this.ui.$win = $(window); 22514 this.ui.$container = $('.js-parallax'); 22515 this.ui.$visual = this.ui.$container.find('.js-parallax-visual'); 22516 }, 22517 bindEvents: function bindEvents() { 22518 var _this = this; 22519 this.ui.$win.on('scroll', function (e) { 22520 return _this.onScroll(e); 22521 }); 22522 this.ui.$win.on('scroll', function (e) { 22523 return _this.getDirection(e); 22524 }); 22525 }, 22526 onScroll: function onScroll(e) { 22527 e.preventDefault(); 22528 if (!this.isScrolling) { 22529 var scroll = $(e.currentTarget).scrollTop(), 22530 bImage = this.ui.$visual.offset().top + this.ui.$visual.outerHeight(), 22531 bBloc = this.ui.$container.offset().top + this.ui.$container.outerHeight(), 22532 tImage = this.ui.$visual.offset().top, 22533 tBloc = this.ui.$container.offset().top; 22534 var value = scroll / 10; 22535 if (!this.reversed) { 22536 if (bImage > bBloc) { 22537 this.ui.$visual.css({ 22538 'transform': 'translateY(' + -value + 'px)' 22539 }); 22540 } 22541 } else { 22542 if (scroll < bBloc && value != bBloc) { 22543 this.ui.$visual.css({ 22544 'transform': 'translateY(' + -value + 'px)' 22545 }); 22546 } 22547 } 22548 } 22549 }, 22550 getDirection: function getDirection(e) { 22551 e.preventDefault(); 22552 var scroll = $(e.currentTarget).scrollTop(); 22553 if (scroll > this.lastScroll) { 22554 this.reversed = false;
22555 } else { 22556 this.reversed = true; 22557 } 22558 this.lastScroll = scroll; 22559 } 22560}; 22561module.exports = coverParallax; 22562 22563},{}],20:[function(require,module,exports){ 22564"use strict"; 22565 22566var scriptLoaded = false; 22567function addScript(src) { 22568 return new Promise(function (resolve, reject) { 22569 if (!scriptLoaded) { 22570 var s = document.createElement('script'); 22571 s.setAttribute('src', src); 22572 s.addEventListener('load', resolve); 22573 s.addEventListener('error', reject); 22574 document.body.appendChild(s); 22575 } 22576 scriptLoaded = true; 22577 resolve(); 22578 }); 22579} 22580var dealerLocator = { 22581 init: function init() { 22582 var locators = $('.js-dealer-locator-page'); 22583 if (locators.length > 0) { 22584 addScript(locators.data('script')).catch(function (err) { 22585 console.error(err); 22586 locators.find('.loader-container').hide(); 22587 locators.find('.message-error').show(); 22588 }); 22589 } 22590 $('.panel-dealer-locator').on('opened', function (e, trigger) { 22591 var $this = $(this); 22592 var $trigger = $(trigger); 22593 var $dealerLocator = $this.find('.dealer-locator'); 22594 $dealerLocator.data('familyid', $trigger.data('familyid') || null); 22595 $dealerLocator.data('productid', $trigger.data('productid') || null); 22596 if ($this.data('loaded')) { 22597 $dealerLocator.trigger('refresh'); 22598 } else { 22599 addScript($dealerLocator.data('script')).then(function () { 22600 $this.data('loaded', true); 22601 }).catch(function (err) { 22602 console.error(err); 22603 $this.find('.loader-container').hide(); 22604 $dealerLocator.find('.message-error').show(); 22605 }); 22606 } 22607 }); 22608 } 22609}; 22610module.exports = dealerLocator; 22611 22612},{}],21:[function(require,module,exports){ 22613"use strict"; 22614 22615var docLists = { 22616 ui: {}, 22617 init: function init() { 22618 this.bindUI(); 22619 this.bindEvents(); 22620 }, 22621 bindUI: function bindUI() { 22622 this.ui.$container = $('.js-doc-list-container'); 22623 this.ui.$select = $('.js-doc-select', this.ui.$container); 22624 this.ui.$item = $('.js-doc-list', this.ui.$container); 22625 }, 22626 bindEvents: function bindEvents() { 22627 var _this = this; 22628 this.ui.$select.on('change', function (e) { 22629 return _this.onChange(e); 22630 }); 22631 }, 22632 onChange: function onChange(e) { 22633 e.preventDefault(); 22634 var $el = $(e.currentTarget), 22635 value = $el.val(), 22636 $target = this.ui.$container.find('.js-doc-list[data-year="' + value + '"]'); 22637 this.ui.$item.removeClass('active'); 22638 $target.addClass('active'); 22639 } 22640}; 22641module.exports = docLists; 22642 22643},{}],22:[function(require,module,exports){ 22644"use strict"; 22645 22646var _gsap = require("gsap"); 22647var _Draggable = _interopRequireDefault(require("gsap/Draggable")); 22648function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } 22649var dragSlider = { 22650 ui: {}, 22651 slidesLength: 0, 22652 width: 0, 22653 track: 0, 22654 init: function init() { 22655 this.bindUI(); 22656 this.bindEvents(); 22657 this.initSlider(); 22658 }, 22659 bindUI: function bindUI() { 22660 this.ui.$window = $(window); 22661 this.ui.$dragContainer = $('.js-drag-slider'); 22662 this.ui.$wrapper = ''; 22663 this.ui.$dragItems = ''; 22664 }, 22665 bindEvents: function bindEvents() { 22666 22667 // this.ui.$window.on('resize', () => this.updateTrack()); 22668 }, 22669 initSlider: function initSlider() { 22670 this.ui.$dragContainer.each(function (n, item) { 22671 console.log('item slider', item); 22672 $(item).find('.js-drag-wrapper').slick({ 22673 slidesToShow: 3, 22674 slidesToScroll: 1, 22675 dots: false, 22676 infinite: false, 22677 arrows: true, 22678 fade: false, 22679 cssEase: 'linear', 22680 autoplay: false, 22681 speed: 400, 22682 responsive: [{ 22683 breakpoint: 1024, 22684 settings: { 22685 slidesToShow: 2 22686 } 22687 }, { 22688 breakpoint: 768, 22689 settings: { 22690 slidesToShow: 1 22691 } 22692 }] 22693 }); 22694 // this.ui.$wrapper = $(item).find('.js-drag-wrapper'); 22695 // this.ui.$dragItems = $(item).find('.js-drag-item'); 22696 22697 // this.slidesLength = this.ui.$dragItems.length; 22698 22699 // this.updateTrack(); 22700 }); 22701 } 22702}; 22703module.exports = dragSlider; 22704 22705},{"gsap":5,"gsap/Draggable":3}],23:[function(require,module,exports){ 22706"use strict"; 22707 22708var _ = require('underscore'); 22709var message = require('./message.js'); 22710var refreshShopCount = function refreshShopCount(count) { 22711 if (count > 0) { 22712 $('.js-eshop-count').show().text(count); 22713 $('.js-eshop-count').parent().removeClass('is-disabled'); 22714 } else { 22715 $('.js-eshop-count').hide(); 22716 $('.js-eshop-count').parent().addClass('is-disabled'); 22717 } 22718}; 22719var addToCartInit = function addToCartInit(asyncForms) { 22720 var $panel = $('#panel-addtocart'); 22721 var $panelLoader = $panel.find('.loader-container'); 22722 var $panelError = $panel.find('.service-error'); 22723 var $panelContent = $panel.find('.panel-content'); 22724 var panelTemplate = _.template($('#product-addtocart-template').html()); 22725 var panel = $panel.data('panel'); 22726 var serviceError = function serviceError() { 22727 $panelLoader.hide(); 22728 $panelError.show(); 22729 $panelContent.hide(); 22730 }; 22731 $panel.on('opened', function (e, trigger) { 22732 $panelLoader.show(); 22733 $panelError.hide(); 22734 $panelContent.hide(); 22735 var url = window.nexansConfig.cartServiceUrl.replace('{action}', 'add') + '/' + $(trigger).data('id'); 22736 $.ajax({ 22737 url: url 22738 }).done(function (data, textStatus, jqXHR) { 22739 $panelLoader.hide(); 22740 $panelError.hide(); 22741 $panelContent.show().empty().html(panelTemplate(data)); 22742 var asyncForm = asyncForms.initElement($panelContent.find('.js-async-form').get(0)); 22743 asyncForm.contentType = 'application/json'; 22744 asyncForm.valueBuilder = function (self, submitter) { 22745 var values = $(self.el).serializeArray(); 22746 var data = {}; 22747 for (var i = 0; i < values.length; i++) { 22748 data[values[i].name] = values[i].value; 22749 } 22750 return JSON.stringify(data); 22751 }; 22752 asyncForm.alwaysDisplayMessage = true; 22753 asyncForm.success = function (data, textStatus, jqXHR) { 22754 window.sessionStorage.setItem('eshop-count', data.nbItems); 22755 refreshShopCount(data.nbItems); 22756 message.add(data.message, 'info', 3000); 22757 panel.close(); 22758 }; 22759 }).fail(function (xhr, status, error) { 22760 serviceError(); 22761 }); 22762 }); 22763}; 22764var eshop = { 22765 init: function init(asyncForms) { 22766 /* error "ReferenceError: TableSelect is not defined" in order backlog 22767 -> est-ce redondant par rapport au module tableselect ? 22768 $('.js-tableselect').each(function(){ 22769 $(this).data('tableselect', new TableSelect(this)); 22770 }); 22771 */
22772 if ($('.js-panel-trigger-eshop').length > 0) { 22773 $(document).on('uiLoaded', function () { 22774 eshop.addToCartInit(asyncForms); 22775 }); 22776 } 22777 if (window.nexansConfig.cartServiceUrl) { 22778 var count = window.sessionStorage.getItem('eshop-count'); 22779 if (!count && count !== 0) { 22780 $.ajax({ 22781 url: window.nexansConfig.cartServiceUrl.replace('{action}', 'count'), 22782 type: 'GET' 22783 }).done(function (data) { 22784 count = data.nbItems; 22785 window.sessionStorage.setItem('eshop-count', count); 22786 refreshShopCount(count); 22787 }); 22788 } else { 22789 refreshShopCount(count); 22790 } 22791 $(document).on('refresh-shop-count', function (e, count) { 22792 window.sessionStorage.setItem('eshop-count', count); 22793 refreshShopCount(count); 22794 }); 22795 } 22796 }, 22797 addToCartInit: function addToCartInit(asyncForms) { 22798 var $panel = $('#panel-addtocart'); 22799 var $panelLoader = $panel.find('.loader-container'); 22800 var $panelError = $panel.find('.service-error'); 22801 var $panelContent = $panel.find('.panel-content'); 22802 var panelTemplate = _.template($('#product-addtocart-template').html()); 22803 var panel = $panel.data('panel'); 22804 var serviceError = function serviceError() { 22805 $panelLoader.hide(); 22806 $panelError.show(); 22807 $panelContent.hide(); 22808 }; 22809 $panel.on('opened', function (e, trigger) { 22810 $panelLoader.show(); 22811 $panelError.hide(); 22812 $panelContent.hide(); 22813 var url = window.nexansConfig.cartServiceUrl.replace('{action}', 'add') + '/' + $(trigger).data('id'); 22814 $.ajax({ 22815 url: url 22816 }).done(function (data, textStatus, jqXHR) { 22817 $panelLoader.hide(); 22818 $panelError.hide(); 22819 $panelContent.show().empty().html(panelTemplate(data)); 22820 var asyncForm = asyncForms.initElement($panelContent.find('.js-async-form').get(0)); 22821 asyncForm.contentType = 'application/json'; 22822 asyncForm.valueBuilder = function (self, submitter) { 22823 var values = $(self.el).serializeArray(); 22824 var data = {}; 22825 for (var i = 0; i < values.length; i++) { 22826 data[values[i].name] = values[i].value; 22827 } 22828 return JSON.stringify(data); 22829 }; 22830 asyncForm.alwaysDisplayMessage = true; 22831 asyncForm.success = function (data, textStatus, jqXHR) { 22832 window.sessionStorage.setItem('eshop-count', data.nbItems); 22833 refreshShopCount(data.nbItems); 22834 message.add(data.message, 'info', 3000); 22835 panel.close(); 22836 }; 22837 }).fail(function (xhr, status, error) { 22838 serviceError(); 22839 }); 22840 }); 22841 } 22842}; 22843module.exports = eshop; 22844 22845},{"./message.js":35,"underscore":8}],24:[function(require,module,exports){ 22846"use strict"; 22847 22848var panelExpand = { 22849 ui: {}, 22850 init: function init() { 22851 this.bindUI(); 22852 this.bindEvents(); 22853 }, 22854 bindUI: function bindUI() { 22855 this.ui.$win = $(window); 22856 this.ui.$body = $('body'); 22857 this.ui.$btnOpen = $('.js-open-panel'); 22858 this.ui.$btnClose = $('.js-close-panel'); 22859 this.ui.$mask = $('.js-mask-panel'); 22860 this.ui.container = $('.js-panel-container'); 22861 }, 22862 bindEvents: function bindEvents() { 22863 this.ui.$btnOpen.on('click', $.proxy(this.openPanel, this)); 22864 this.ui.$btnClose.on('click', $.proxy(this.closePanel, this)); 22865 this.ui.$mask.on('click', $.proxy(this.closePanel, this)); 22866 //$(document).on('keyup', $.proxy(this.closePanel, this)); 22867 }, 22868 openPanel: function expandSection(e) { 22869 e.preventDefault(); 22870 22871 // open modale. 22872 this.ui.$body.addClass('is-locked'); 22873 this.ui.$body.addClass('is-panel-open'); 22874 }, 22875 closePanel: function closePanel(e) { 22876 e.preventDefault(); 22877 22878 // close modale. 22879 this.ui.$body.removeClass('is-locked'); 22880 this.ui.$body.removeClass('is-panel-open'); 22881 22882 // close modal with keyboard esc. 22883 if (e.keyCode === 27) { 22884 this.ui.$body.removeClass('is-locked'); 22885 this.ui.$body.removeClass('is-panel-open'); 22886 } 22887 22888 // back to top of panel view. 22889 var ofTop = $('body').offset().top; 22890 $('.js-panel-container').scrollTop(ofTop); 22891 } 22892}; 22893module.exports = panelExpand; 22894 22895},{}],25:[function(require,module,exports){ 22896"use strict"; 22897 22898var sectorExpand = { 22899 ui: {},
22900 init: function init() { 22901 this.bindUI(); 22902 this.bindEvents(); 22903 }, 22904 bindUI: function bindUI() { 22905 this.ui.$win = $(window); 22906 this.ui.$body = $('body'); 22907 this.ui.$btnExpand = $('.js-expand-sector'); 22908 }, 22909 bindEvents: function bindEvents() { 22910 this.ui.$btnExpand.on('click', $.proxy(this.scrollToPanel, this)); 22911 }, 22912 scrollToPanel: function scrollToPanel(e) { 22913 e.preventDefault(); 22914 var self = this; 22915 var $item = $(e.currentTarget).closest('.js-sector-container'); 22916 22917 // Test if section is open for apply scroll effect or not. 22918 if (!$item.hasClass('is-open')) { 22919 // Calcute position of item animate. 22920 var pos = Math.max($item.offset().top, 0); 22921 22922 // Animate scroll to section opened. 22923 $('html').animate({ 22924 scrollTop: pos 22925 }, 'slow', function () { 22926 // Call expand section. 22927 // waiting callback for animate show / hide after scroll effect. 22928 self.expandSection(e); 22929 }); 22930 } else { 22931 // Call expand section without scroll animation. 22932 self.expandSection(e); 22933 } 22934 }, 22935 expandSection: function expandSection(e) { 22936 // Get item for open section 22937 var $item = $(e.currentTarget).closest('.js-sector-container'); 22938 $item.find('.list-sector').stop().slideToggle(); 22939 if ($item.hasClass('is-open')) { 22940 $item.removeClass('is-open'); 22941 $(e.currentTarget).removeClass('is-open'); 22942 } else { 22943 $item.addClass('is-open'); 22944 $(e.currentTarget).addClass('is-open'); 22945 } 22946 } 22947}; 22948module.exports = sectorExpand; 22949 22950},{}],26:[function(require,module,exports){ 22951"use strict"; 22952 22953var _ = require('underscore'); 22954var filterList = { 22955 ui: {}, 22956 init: function init() { 22957 this.bindUI(); 22958 this.bindEvents(); 22959 this.selectedCategories = window.nexansSelectedCategories || []; 22960 this.selectedYear = window.nexansSelectedYear || null; 22961 this.selectedType = window.nexansSelectedType || null; 22962 }, 22963 bindUI: function bindUI() { 22964 this.ui.$win = $(window); 22965 this.ui.$body = $('body'); 22966 this.ui.$dropdownParent = $('.js-filter-dropdown-parent'); 22967 this.ui.$dropdown = $('.js-filter-dropdown'); 22968 this.ui.$wrapper = $('.js-filter-dropdown-content'); 22969 this.ui.$content = $('.js-filter-mobile-content'); 22970 this.ui.$select = $('.js-filter-select'); 22971 this.ui.$showFilter = $('.js-show-filter'); 22972 this.ui.$jsFilter = $('.js-filter'); 22973 this.ui.$filterLinks = this.ui.$jsFilter.find('.link:not(.js-filter-dropdown)'); 22974 this.ui.$selectYear = $('select.filter-year-select'); 22975 this.ui.$selectType = $('select.filter-type-select'); 22976 }, 22977 bindEvents: function bindEvents() { 22978 var self = this; 22979 this.ui.$dropdown.on('click', $.proxy(this.showSubnav, this)); 22980 this.ui.$filterLinks.on('click', $.proxy(this.clickLink, this)); 22981 //this.ui.$wrapper.on('mouseleave', $.proxy(this.hideSubnav, this)); 22982 22983 this.ui.$select.on('change', $.proxy(this.selectCatChange, this)); 22984 this.ui.$selectYear.on('change', $.proxy(this.selectYearChange, this)); 22985 this.ui.$selectType.on('change', $.proxy(this.selectTypeChange, this)); 22986 this.ui.$showFilter.on('click', $.proxy(this.showFilter, this)); 22987 22988 // On click everywhere, close the search. 22989 $(document).click(function (e) { 22990 if ($(e.target).closest('.js-filter-dropdown').length === 0) { 22991 self.closeFilter(); 22992 } 22993 }); 22994 }, 22995 clickLink: function clickLink(e) { 22996 var $el = $(e.currentTarget); 22997 var cat = this.getCategoryFromUrl($el.attr('href')); 22998 if (cat !== null) { 22999 e.preventDefault(); 23000 this.setCategory(cat); 23001 } 23002 }, 23003 getCategoryFromUrl: function getCategoryFromUrl(url) { 23004 var match = url.match(/category=([^&]+)/); 23005 if (match && match.length > 1) { 23006 return match[1]; 23007 } 23008 return null; 23009 }, 23010 setCategory: function setCategory(category) { 23011 var index = this.selectedCategories.indexOf(category); 23012 if (index < 0) { 23013 this.selectedCategories.push(category); 23014 } else { 23015 this.selectedCategories.splice(index, 1); 23016 } 23017 this.goto(); 23018 }, 23019 closeFilter: function closeFilter() { 23020 this.ui.$dropdownParent.removeClass('is-open'); 23021 }, 23022 showSubnav: function showSubnav(e) { 23023 e.preventDefault(); 23024 var $el = $(e.currentTarget); 23025 if (!$el.parent().hasClass('is-open')) { 23026 this.closeFilter(); 23027 } 23028 $el.parent().toggleClass('is-open'); 23029 }, 23030 hideSubnav: function hideSubnav(e) { 23031 var $el = $(e.currentTarget); 23032 setTimeout(function () { 23033 $el.parent().removeClass('is-open'); 23034 $('.js-filter-dropdown').removeClass('is-open'); 23035 }, 200); 23036 }, 23037 selectCatChange: function selectCatChange(e) { 23038 var val = $(e.currentTarget).val(); 23039 // Check if the value is defined. 23040 if (val === 'subnav') { 23041 var selected = $('.js-filter-select option:selected'), 23042 ref = selected.data('ref'); 23043 $('#' + ref).addClass('is-selected'); 23044 } else { 23045 var cat = this.getCategoryFromUrl(val); 23046 if (cat !== null) { 23047 this.setCategory(cat); 23048 } 23049 } 23050 }, 23051 selectYearChange: function selectYearChange(e) { 23052 var year = $(e.currentTarget).val(); 23053 if (year && year.length > 0) { 23054 year = parseInt(year, 10); 23055 this.selectedYear = year; 23056 } else { 23057 this.selectedYear = null; 23058 } 23059 this.goto(); 23060 }, 23061 selectTypeChange: function selectTypeChange(e) { 23062 var type = $(e.currentTarget).val(); 23063 if (type && type.length > 0) { 23064 this.selectedType = type; 23065 } else { 23066 this.selectedType = null; 23067 } 23068 this.goto(); 23069 }, 23070 goto: function goto() { 23071 var url = window.nexansFilterUrl; 23072 var parameters = []; 23073 if (this.selectedCategories && this.selectedCategories.length) { 23074 parameters.push('category=' + this.selectedCategories.join()); 23075 } 23076 if (this.selectedYear) { 23077 parameters.push('year=' + this.selectedYear); 23078 } 23079 if (this.selectedType) { 23080 parameters.push('type=' + this.selectedType); 23081 } 23082 if (parameters.length > 0) { 23083 url += '?' + parameters.join('&'); 23084 } 23085 window.location.href = url; 23086 }, 23087 showFilter: function showFilter(e) { 23088 e.preventDefault(); 23089 var $el = $(e.currentTarget); 23090 $el.closest('.filter-mobile').toggleClass('is-open'); 23091 } 23092}; 23093module.exports = filterList; 23094 23095},{"underscore":8}],27:[function(require,module,exports){ 23096"use strict"; 23097 23098var fixHeight = { 23099 ui: {},
23100 init: function init() { 23101 this.bindUI(); 23102 this.bindEvents(); 23103 }, 23104 bindUI: function bindUI() { 23105 this.ui.$win = $(window); 23106 this.ui.$body = $('body'); 23107 this.ui.$height = $('.js-fix-height'); 23108 this.ui.$items = $('.js-fix-height-item'); 23109 }, 23110 bindEvents: function bindEvents() { 23111 var _this = this; 23112 this.ui.$win.on('load', function () { 23113 return _this.heightHandler(); 23114 }); 23115 23116 // Reset height when window is resized. 23117 this.ui.$win.on('resize', function () { 23118 return _this.heightHandler(); 23119 }); 23120 }, 23121 unbindEvents: function unbindEvents() { 23122 var self = this; 23123 23124 // Reset height when window is resized. 23125 this.ui.$win.off('resize'); 23126 }, 23127 update: function update() { 23128 if (Object.keys(this.ui).length) { 23129 this.unbindEvents(); 23130 } 23131 this.bindUI(); 23132 this.bindEvents(); 23133 }, 23134 heightHandler: function heightHandler() { 23135 var self = this; 23136 23137 // Loop through each element and launch function. 23138 $.each(this.ui.$height, function () { 23139 self.setHeight($(this)); 23140 }); 23141 }, 23142 setHeight: function setHeight($el) { 23143 var self = this, 23144 maxH = 0, 23145 $items = $el.find('.js-fix-height-item'), 23146 $img = $el.find('img'); 23147 23148 // Reset items height. 23149 $items.outerHeight('auto'); 23150 23151 // Get maxH. 23152 $.each($items, function () { 23153 var itemH = $(this).outerHeight(); 23154 23155 // If item height > to maxH, reset it. 23156 if (itemH > maxH) { 23157 maxH = itemH; 23158 } 23159 }); 23160 23161 // Set maxH on elements. 23162 $items.outerHeight(maxH, true); 23163 } 23164}; 23165module.exports = fixHeight; 23166 23167},{}],28:[function(require,module,exports){ 23168"use strict"; 23169 23170var formReset = { 23171 init: function init() { 23172 $('.js-form-reset').on('click', function (e) { 23173 e.preventDefault(); 23174 var form = jQuery(e.target).parents('form'); 23175 form.find('input:not([type=submit]):not([type=reset]):not([type=hidden]):not([type=checkbox])').val(''); 23176 form.find('select option:selected').removeAttr('selected'); 23177 form.find('input[type=checkbox]:checked').removeAttr('checked'); 23178 }); 23179 } 23180}; 23181module.exports = formReset; 23182 23183},{}],29:[function(require,module,exports){ 23184"use strict"; 23185 23186function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 23187function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 23188function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 23189function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 23190function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 23191function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 23192var FormValidation = /*#__PURE__*/function () { 23193 function FormValidation(el) { 23194 _classCallCheck(this, FormValidation); 23195 this.$el = $(el); 23196 el.noValidate = true; 23197 this.$inputs = this.$el.find(':input'); 23198 this.bind(); 23199 } 23200 return _createClass(FormValidation, [{ 23201 key: "bind", 23202 value: function bind() { 23203 var self = this; 23204 this.$el.on('submit', function (e) { 23205 self.$el.find('.message__error').remove(); 23206 self.$el.find('.error').removeClass('error'); 23207 if (!self.checkValidation()) { 23208 e.stopImmediatePropagation(); 23209 e.preventDefault(); 23210 } else { 23211 self.$el.trigger('validated', e); 23212 } 23213 }); 23214 } 23215 }, { 23216 key: "checkValidation", 23217 value: function checkValidation() { 23218 var check = true; 23219 var top = null;
23220 var $focus = null; 23221 this.$inputs.each(function () { 23222 if (!this.checkValidity()) { 23223 check = false; 23224 var $this = $(this); 23225 $this.parents('.form-group').addClass('error'); 23226 var customMessage = $this.data('error-message'); 23227 if (customMessage) { 23228 $this.parent().append('<div class="message message__error">' + customMessage + '</div>'); 23229 } else if ('validationMessage' in this && this.validationMessage) { 23230 $this.parent().append('<div class="message message__error">' + this.validationMessage + '</div>'); 23231 } 23232 var nTop = $this.offset().top; 23233 if (top === null || nTop < top) { 23234 top = nTop; 23235 $focus = $this; 23236 } 23237 } 23238 }); 23239 if (!check && !this.isInViewport($focus)) { 23240 $(window).scrollTop(top - 50); 23241 } 23242 return check; 23243 } 23244 }, { 23245 key: "isInViewport", 23246 value: function isInViewport($e) { 23247 var elementTop = $e.offset().top; 23248 var elementBottom = elementTop + $e.outerHeight(); 23249 var viewportTop = $(window).scrollTop(); 23250 var viewportBottom = viewportTop + $(window).height(); 23251 return elementBottom > viewportTop && elementTop < viewportBottom; 23252 } 23253 }]); 23254}(); 23255var formValidation = { 23256 init: function init() { 23257 $('.js-form-validation').each(function () { 23258 new FormValidation(this); 23259 }); 23260 $(document).on('async-form', function (e, el) { 23261 if ($(el).hasClass('js-form-validation')) { 23262 new FormValidation(el); 23263 } 23264 }); 23265 } 23266}; 23267module.exports = formValidation; 23268 23269},{}],30:[function(require,module,exports){ 23270"use strict"; 23271 23272var fullPage = { 23273 ui: {}, 23274 throttle: true, 23275 init: function init() { 23276 this.bindUI(); 23277 this.bindEvents(); 23278 this.initComponents(); 23279 }, 23280 bindUI: function bindUI() { 23281 this.ui.$win = $(window); 23282 this.ui.$body = $('body'); 23283 this.ui.$container = $('.js-fullpage-slider'); 23284 this.ui.$slide = ''; 23285 }, 23286 bindEvents: function bindEvents() { 23287 var _this = this; 23288 this.ui.$win.on('scroll', function (e) { 23289 return _this.activeOnScroll(e); 23290 }); 23291 }, 23292 initComponents: function initComponents() { 23293 var _this2 = this; 23294 this.ui.$container.each(function (n, item) { 23295 _this2.ui.$slide = $(item).find('.js-fullpage-slide'); 23296 }); 23297 }, 23298 activeOnScroll: function activeOnScroll(e) { 23299 var _this3 = this; 23300 e.preventDefault(); 23301 if (this.isMobileTablet()) { 23302 return; 23303 } 23304 if (this.throttle) { 23305 this.throttle = !this.throttle; 23306 var scroll = $(e.currentTarget).scrollTop(); 23307 this.ui.$slide.each(function (n, item) { 23308 var offset = $(item).offset().top, 23309 vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0), 23310 height = $(item).outerHeight(), 23311 trigger = offset - vh + height / 3; // trigger when reaching 1/3 of item's height 23312 23313 if (scroll >= trigger) { 23314 $(item).addClass('active'); 23315 } 23316 }); 23317 } 23318 setTimeout(function () { 23319 _this3.throttle = !_this3.throttle; 23320 }, 5); 23321 }, 23322 isMobileTablet: function isMobileTablet() { 23323 if (this.ui.$win.outerWidth() <= 1024) { 23324 return true; 23325 } else { 23326 return false; 23327 } 23328 } 23329}; 23330module.exports = fullPage; 23331 23332},{}],31:[function(require,module,exports){ 23333"use strict"; 23334 23335var zoom = require('jquery-zoom'); 23336var gallery = { 23337 ui: {}, 23338 countImages: 0, 23339 init: function init() { 23340 var _this = this; 23341 $(document).on('init-gallery', function (e) { 23342 _this.initGallery(); 23343 }); 23344 this.initGallery(); 23345 }, 23346 initGallery: function initGallery() { 23347 if ($('.js-gallery').length) { 23348 this.bindUI(); 23349 this.bindEvents(); 23350 this.initZoom(); 23351 this.updateControls(0); 23352 } 23353 }, 23354 bindUI: function bindUI() { 23355 this.ui.$win = $(window); 23356 this.ui.$body = $('body'); 23357 this.ui.$container = $('.js-gallery'); 23358 this.ui.$thumbnail = $('.js-gallery-thumbnail'); 23359 this.ui.$imageWrapper = $('.js-gallery-image-wrapper'); 23360 this.ui.$navPrev = $('.js-gallery-prev'); 23361 this.ui.$navNext = $('.js-gallery-next'); 23362 this.countImages = this.ui.$imageWrapper.find('.js-gallery-image').length; 23363 }, 23364 bindEvents: function bindEvents() { 23365 var _this2 = this; 23366 this.ui.$thumbnail.on('click', function (e) { 23367 return _this2.onThumbnail(e); 23368 });
23369 this.ui.$navPrev.on('click', function (e) { 23370 return _this2.onNav('prev'); 23371 }); 23372 this.ui.$navNext.on('click', function (e) { 23373 return _this2.onNav('next'); 23374 }); 23375 }, 23376 initZoom: function initZoom() { 23377 if (!this.isMobileVersion()) { 23378 var imageUrl = this.ui.$imageWrapper.find('img.is-active').attr('src'); 23379 this.ui.$imageWrapper.zoom({ 23380 url: imageUrl, 23381 duration: 500 23382 }); 23383 } 23384 }, 23385 onThumbnail: function onThumbnail(e) { 23386 e.preventDefault(); 23387 var $el = $(e.currentTarget), 23388 index = $el.index(); 23389 this.setImage(index); 23390 }, 23391 onNav: function onNav(direction) { 23392 var $el = this.ui.$imageWrapper.find('img.is-active'), 23393 indexCurrent = $el.index(), 23394 indexToSet; 23395 if (direction == 'prev') { 23396 indexToSet = indexCurrent - 1; 23397 } else { 23398 indexToSet = indexCurrent + 1; 23399 } 23400 indexToSet = Math.min(this.countImages - 1, indexToSet); 23401 indexToSet = Math.max(0, indexToSet); 23402 this.setImage(indexToSet); 23403 }, 23404 setImage: function setImage(index) { 23405 // Set active image 23406 this.ui.$imageWrapper.find('img').removeClass('is-active'); 23407 this.ui.$imageWrapper.find('img').eq(index).addClass('is-active'); 23408 23409 // Set zoom image 23410 if (!this.isMobileVersion()) { 23411 var imageUrl = this.ui.$imageWrapper.find('img.is-active').attr('src'); 23412 this.ui.$imageWrapper.trigger('zoom.destroy'); 23413 this.ui.$imageWrapper.zoom({ 23414 url: imageUrl, 23415 duration: 500 23416 }); 23417 } 23418 23419 // Set controls 23420 this.updateControls(index); 23421 }, 23422 updateControls: function updateControls(index) { 23423 // Set active thumbnail 23424 this.ui.$thumbnail.removeClass('is-active'); 23425 this.ui.$thumbnail.eq(index).addClass('is-active'); 23426 23427 // Set nav 23428 if (index >= this.countImages - 1) { 23429 this.ui.$navNext.addClass('is-disabled'); 23430 } else { 23431 this.ui.$navNext.removeClass('is-disabled'); 23432 } 23433 if (index <= 0) { 23434 this.ui.$navPrev.addClass('is-disabled'); 23435 } else { 23436 this.ui.$navPrev.removeClass('is-disabled'); 23437 } 23438 }, 23439 isMobileVersion: function isMobileVersion() { 23440 return !this.ui.$thumbnail.is(":visible"); 23441 } 23442}; 23443module.exports = gallery; 23444 23445},{"jquery-zoom":6}],32:[function(require,module,exports){ 23446"use strict"; 23447 23448var grid = { 23449 ui: {}, 23450 init: function init() { 23451 this.bindUI(); 23452 this.bindEvents(); 23453 }, 23454 bindUI: function bindUI() { 23455 this.ui.$grid = $('.js-dev-grid'); 23456 this.ui.$btn = $('.js-dev-grid-btn'); 23457 }, 23458 bindEvents: function bindEvents() { 23459 this.ui.$btn.on('click', $.proxy(this.toggleGrid, this)); 23460 }, 23461 toggleGrid: function toggleGrid() { 23462 this.ui.$grid.toggleClass('is-hidden'); 23463 } 23464}; 23465module.exports = grid; 23466 23467},{}],33:[function(require,module,exports){ 23468"use strict"; 23469 23470function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 23471function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } 23472function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } 23473function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } 23474function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 23475function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 23476function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 23477function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 23478function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 23479var MainNav = /*#__PURE__*/function () { 23480 function MainNav() { 23481 _classCallCheck(this, MainNav); 23482 this.isOpened = false;
23483 this.bindUi(); 23484 this.openedLinks = [null, null, null]; 23485 this.$deposit = $('<div></div>').appendTo(this.$mainNav).hide(); 23486 this.hierarchy = this.createHierarchy(this.$mainNav.children(), 0); 23487 } 23488 return _createClass(MainNav, [{ 23489 key: "bindUi", 23490 value: function bindUi() { 23491 this.$mainNav = $('.main-nav'); 23492 this.$mainSubnav = $('.main-subnav'); 23493 this.$menuTrigger = $('.js-menu-trigger'); 23494 this.$menuClose = $('.js-menu-close'); 23495 this.$header = $('header.header'); 23496 this.mainSubnavs = [$('.main-subnav--level-1'), $('.main-subnav--level-2'), $('.main-subnav--level-3')]; 23497 var self = this; 23498 var clickLink = function clickLink(e) { 23499 e.stopPropagation(); 23500 e.preventDefault(); 23501 var linkInfos = self.hierarchy[$(this).data('id')]; 23502 if (linkInfos.$link.hasClass('active')) { 23503 if (linkInfos.level === 0) { 23504 self.close(); 23505 } else { 23506 self.closeLink(linkInfos); 23507 } 23508 } else { 23509 self.openLink(linkInfos); 23510 } 23511 }; 23512 $('.main-nav, .main-subnav').on('click', function (e) { 23513 e.stopPropagation(); 23514 }); 23515 this.$mainNav.on('click', 'a.expand', clickLink); 23516 this.$mainSubnav.on('click', 'a.expand', clickLink); 23517 this.$menuTrigger.on('click', function (e) { 23518 e.preventDefault(); 23519 self.$header.addClass('is-opened'); 23520 }); 23521 this.$menuClose.on('click', function (e) { 23522 e.preventDefault(); 23523 self.$header.removeClass('is-opened'); 23524 }); 23525 $(document).on('click', function () { 23526 self.close(); 23527 }); 23528 $('.js-link-to-top').on('click', function (e) { 23529 e.preventDefault(); 23530 $('body, html').animate({ 23531 scrollTop: 0 23532 }, 'slow'); 23533 }); 23534 } 23535 }, { 23536 key: "createHierarchy", 23537 value: function createHierarchy($lis, level) { 23538 var prevId = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'menulink'; 23539 var hierarchy = {}; 23540 var self = this; 23541 var i = 0; 23542 $lis.each(function () { 23543 var $this = $(this); 23544 var id = prevId + '-' + level + '-' + i; 23545 var $a = $this.children('a'); 23546 var $ul = $this.children('ul'); 23547 var $highlight = $this.children('.highlight'); 23548 self.$deposit.append($ul); 23549 if ($highlight.length > 0) { 23550 self.$deposit.append($highlight); 23551 } 23552 var hierarchyLi = { 23553 id: id, 23554 title: $a.html(), 23555 $link: $a, 23556 level: level, 23557 $ul: $ul, 23558 $highlight: $highlight 23559 }; 23560 hierarchy[id] = hierarchyLi; 23561 if ($this.hasClass('has-children')) { 23562 $a.addClass('expand').data('id', id); 23563 $ul.addClass(id); 23564 $highlight.addClass(id); 23565 hierarchy = _objectSpread(_objectSpread({}, hierarchy), self.createHierarchy($ul.children(), level + 1, id)); 23566 } 23567 i++; 23568 }); 23569 return hierarchy; 23570 } 23571 }, { 23572 key: "closeLink", 23573 value: function closeLink(linkInfos, checkChildren) { 23574 linkInfos.$link.removeClass('active'); 23575 linkInfos.$ul.appendTo(this.$deposit); 23576 this.mainSubnavs[linkInfos.level].find('.main-subnav--nav').empty(); 23577 this.mainSubnavs[linkInfos.level].removeClass('active'); 23578 if (linkInfos.$highlight.length > 0) { 23579 linkInfos.$highlight.appendTo(this.$deposit); 23580 } 23581 this.openedLinks[linkInfos.level] = null; 23582 if (!checkChildren && linkInfos.level + 1 < 3 && this.openedLinks[linkInfos.level + 1]) { 23583 this.closeLink(this.openedLinks[linkInfos.level + 1]); 23584 } 23585 } 23586 }, { 23587 key: "openLink", 23588 value: function openLink(linkInfos) { 23589 var self = this; 23590 if (!this.isOpened) { 23591 this.$mainSubnav.addClass('active'); 23592 this.isOpened = true; 23593 } 23594 if (this.openedLinks[linkInfos.level]) { 23595 this.closeLink(this.openedLinks[linkInfos.level]); 23596 } 23597 this.openedLinks[linkInfos.level] = linkInfos; 23598 linkInfos.$link.addClass('active'); 23599 this.mainSubnavs[linkInfos.level].addClass('active'); 23600 this.mainSubnavs[linkInfos.level].find('.main-subnav--links').append(linkInfos.$ul); 23601 var $backlink = $('<a href="#"></a>').append(linkInfos.title).on('click', function (e) { 23602 e.preventDefault(); 23603 self.closeLink(linkInfos); 23604 }); 23605 this.mainSubnavs[linkInfos.level].find('.main-subnav--nav').html($backlink); 23606 if (linkInfos.$highlight.length > 0) { 23607 linkInfos.$highlight.appendTo(this.mainSubnavs[2].find('.main-subnav--links')); 23608 } 23609 } 23610 }, { 23611 key: "close", 23612 value: function close() { 23613 for (var i = 0; i < this.openedLinks.length; i++) { 23614 if (this.openedLinks[i]) { 23615 this.closeLink(this.openedLinks[i], true); 23616 } 23617 } 23618 this.$mainSubnav.removeClass('active'); 23619 this.isOpened = false;
23620 } 23621 }]); 23622}(); 23623module.exports = MainNav; 23624 23625},{}],34:[function(require,module,exports){ 23626"use strict"; 23627 23628function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 23629function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 23630function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 23631function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 23632function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 23633function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 23634var JSDropdown = /*#__PURE__*/function () { 23635 function JSDropdown(el, list) { 23636 _classCallCheck(this, JSDropdown); 23637 this.el = el; 23638 this.$el = $(el); 23639 this.list = list; 23640 var target = this.$el.data('target'); 23641 if (target) { 23642 this.$target = $('.' + target); 23643 } else { 23644 this.$target = this.$el.parents('.simple-dropdown').find('.submenu'); 23645 } 23646 this.scroll = this.$el.hasClass('js-dropdown-scroll'); 23647 this.$btClose = this.$target.find('.js-close-btn'); 23648 this.bind(); 23649 } 23650 return _createClass(JSDropdown, [{ 23651 key: "bind", 23652 value: function bind() { 23653 var self = this; 23654 this.$el.on('click', function (e) { 23655 e.preventDefault(); 23656 e.stopPropagation(); 23657 if (self.$el.hasClass('active')) { 23658 self.close(); 23659 } else { 23660 self.open(); 23661 } 23662 self.$el.blur(); 23663 }); 23664 this.$target.on('click', function (e) { 23665 e.stopPropagation(); 23666 }); 23667 if (this.$btClose.length > 0) { 23668 this.$btClose.on('click', function (e) { 23669 e.stopPropagation(); 23670 self.close(); 23671 }); 23672 } 23673 } 23674 }, { 23675 key: "close", 23676 value: function close() { 23677 this.$el.removeClass('active'); 23678 this.$target.removeClass('active'); 23679 } 23680 }, { 23681 key: "open", 23682 value: function open() { 23683 this.closeOthers(); 23684 this.$el.addClass('active'); 23685 this.$target.addClass('active'); 23686 var self = this; 23687 if (this.scroll) { 23688 $('html, body').stop().animate({ 23689 scrollTop: this.$target.offset().top 23690 }, 400, function () { 23691 var $form = self.$target.find('form'); 23692 if ($form.length) { 23693 $form.find('input,textarea,select').first()[0].focus(); 23694 } 23695 }); 23696 } 23697 } 23698 }, { 23699 key: "closeOthers", 23700 value: function closeOthers() { 23701 for (var i = 0; i < this.list.length; i++) { 23702 if (this.list[i] !== this) this.list[i].close(); 23703 } 23704 } 23705 }]); 23706}(); 23707var menuDropdowns = { 23708 obj: JSDropdown, 23709 list: [], 23710 init: function init() { 23711 var self = this; 23712 $('.js-dropdown').each(function () { 23713 self.list.push(new JSDropdown(this, self.list)); 23714 }); 23715 $('body').click(function () { 23716 for (var i = 0; i < self.list.length; i++) { 23717 self.list[i].close(); 23718 } 23719 }); 23720 } 23721}; 23722module.exports = menuDropdowns; 23723 23724},{}],35:[function(require,module,exports){ 23725"use strict"; 23726 23727var message = { 23728 add: function add(text, type, timeout) { 23729 if (timeout !== false) { 23730 timeout = parseInt(timeout, 10); 23731 if (timeout < 1) { 23732 timeout = 5000; 23733 } 23734 } 23735 if (type !== 'info' && type !== 'warning' && type !== 'error') { 23736 type = 'info'; 23737 } 23738 var $mess = $('<div class="quick-message quick-message--' + type + '"><button type="button" class="quick-message__close"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" class="icon icon-close" viewBox="0 0 20 20"><path fill="#000000" fill-rule="evenodd" d="M10,8.58578644 L4.34314575,2.92893219 L2.92893219,4.34314575 L8.58578644,10 L2.92893219,15.6568542 L4.34314575,17.0710678 L10,11.4142136 L15.6568542,17.0710678 L17.0710678,15.6568542 L11.4142136,10 L17.0710678,4.34314575 L15.6568542,2.92893219 L10,8.58578644 Z" /></svg></button><div class="content"></div></div>'); 23739 $mess.find('.content').html(text); 23740 $('body').append($mess); 23741 if (timeout !== false) { 23742 var _timer = setTimeout(function () { 23743 $mess.fadeOut(function () { 23744 $mess.remove(); 23745 }); 23746 }, timeout); 23747 } 23748 $('.quick-message__close').on('click', function () { 23749 if (timeout !== false) clearTimeout(timer); 23750 $mess.remove(); 23751 }); 23752 } 23753}; 23754module.exports = message; 23755 23756},{}],36:[function(require,module,exports){ 23757"use strict"; 23758 23759var modal = { 23760 ui: {},
23761 init: function init() { 23762 this.bindUI(); 23763 this.bindEvents(); 23764 }, 23765 bindUI: function bindUI() { 23766 // Global 23767 this.ui.$win = $(window); 23768 this.ui.$body = $('body'); 23769 this.ui.$document = $(document); 23770 23771 // Module 23772 this.ui.$btn = $('.js-modal-btn'); 23773 this.ui.$modal = $('.js-modal'); 23774 this.ui.$close = $('.js-modal-close'); 23775 }, 23776 bindEvents: function bindEvents() { 23777 this.ui.$btn.on('click', $.proxy(this.showModal, this)); 23778 this.ui.$close.on('click', $.proxy(this.closeModal, this)); 23779 // this.ui.$document.on('keyup', $.proxy(this.closeModal, this)); 23780 }, 23781 showModal: function showModal(e) { 23782 e.preventDefault(); 23783 23784 // get ref modal. 23785 var ref = $(e.currentTarget).data('modal'); 23786 23787 // Parsing all modal to get clicked by ref. 23788 $.each(this.ui.$modal, function () { 23789 // Test ref clicked. 23790 if ($(this).data('modal') == ref) { 23791 // Show modal. 23792 $(this).addClass('is-open'); 23793 23794 // Lock body. 23795 $('body').addClass('is-locked'); 23796 } 23797 }); 23798 }, 23799 closeModal: function closeModal(e) { 23800 e.preventDefault(); 23801 23802 // Get wrapper of btn close. 23803 var wrapper = $(e.currentTarget).closest('.js-modal'); 23804 23805 // Close modal. 23806 wrapper.removeClass('is-open'); 23807 23808 // Unlock body. 23809 this.ui.$body.removeClass('is-locked'); 23810 23811 // Close by keyboard. 23812 if (e.keyCode === 27) { 23813 this.ui.$modal.removeClass('is-open'); 23814 this.ui.$body.removeClass('is-locked'); 23815 } 23816 } 23817}; 23818module.exports = modal; 23819 23820},{}],37:[function(require,module,exports){ 23821"use strict"; 23822 23823function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 23824function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 23825function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 23826function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 23827function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 23828function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 23829var Modal = /*#__PURE__*/function () { 23830 function Modal(params) { 23831 _classCallCheck(this, Modal); 23832 this.params = $.extend({ 23833 content: '', 23834 open: true, 23835 classes: [], 23836 onClose: null 23837 }, params); 23838 this.params.classes.unshift('modal'); 23839 if (this.params.open) this.open(); 23840 } 23841 return _createClass(Modal, [{ 23842 key: "open", 23843 value: function open() { 23844 var modal = "<div class=\"".concat(this.params.classes.join(' '), "\"><div class=\"modal--modal\"><button type=\"button\" class=\"modal__close\">Close<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"20\" height=\"20\" class=\"icon icon-close\" viewBox=\"0 0 20 20\"><path fill=\"#000000\" fill-rule=\"evenodd\" d=\"M10,8.58578644 L4.34314575,2.92893219 L2.92893219,4.34314575 L8.58578644,10 L2.92893219,15.6568542 L4.34314575,17.0710678 L10,11.4142136 L15.6568542,17.0710678 L17.0710678,15.6568542 L11.4142136,10 L17.0710678,4.34314575 L15.6568542,2.92893219 L10,8.58578644 Z\" /></svg></button><div class=\"modal--content\"></div></div></div></div>"); 23845 this.$modal = $(modal); 23846 this.$modal.appendTo('body'); 23847 this.bind(); 23848 this.$modal.find('.modal--content').html(this.params.content); 23849 this.$modal.addClass('is-open'); 23850 } 23851 }, { 23852 key: "close", 23853 value: function close() { 23854 this.unbind(); 23855 this.$modal.remove(); 23856 if (this.params.onClose) { 23857 this.params.onClose(); 23858 } 23859 } 23860 }, { 23861 key: "bind", 23862 value: function bind() { 23863 $(document).on('keyup.modal', function (e) { 23864 if (e.keyCode === 27) { 23865 this.close(); 23866 } 23867 }.bind(this)); 23868 this.$modal.on('click', this.close.bind(this)); 23869 this.$modal.find('.modal__close').on('click', this.close.bind(this));
23870 this.$modal.find('.modal--modal').on('click', function (e) { 23871 e.stopPropagation(); 23872 }); 23873 } 23874 }, { 23875 key: "unbind", 23876 value: function unbind() { 23877 $(document).off('keyup.modal'); 23878 } 23879 }]); 23880}(); 23881module.exports = Modal; 23882 23883},{}],38:[function(require,module,exports){ 23884"use strict"; 23885 23886var navigationPanel = { 23887 ui: {}, 23888 init: function init() { 23889 this.bindUI(); 23890 this.bindEvents(); 23891 }, 23892 bindUI: function bindUI() { 23893 this.ui.$win = $(window); 23894 this.ui.$body = $('body'); 23895 this.ui.$document = $(document); 23896 23897 // Menu 23898 this.ui.$menuPanelOpenTrigger = $('.js-menu-panel-trigger'); 23899 this.ui.$menuPanelWrapper = $('.js-menu-panel'); 23900 this.ui.$menuPanelOverlay = $('.js-overlay'); 23901 this.ui.$menuPanelCloseTrigger = $('.js-menu-panel-close'); 23902 23903 // Expends 23904 this.ui.$menuPanelExpendTrigger = $('.js-menu-panel-expend-trigger'); 23905 this.ui.$menuPanelBackTrigger = $('.js-menu-panel-back-trigger'); 23906 }, 23907 bindEvents: function bindEvents() { 23908 this.ui.$menuPanelOpenTrigger.on('click', $.proxy(this.openNavigation, this)); 23909 this.ui.$menuPanelCloseTrigger.add(this.ui.$menuPanelOverlay).on('click', $.proxy(this.closeNavigation, this)); 23910 this.ui.$menuPanelExpendTrigger.on('click', this.openExpend); 23911 this.ui.$menuPanelBackTrigger.on('click', this.closeExpend); 23912 }, 23913 openNavigation: function openNavigation(e) { 23914 e.preventDefault(); 23915 var $menuPanelWrapper = $('.js-menu-panel#' + $(e.currentTarget).attr('data-panel')); 23916 $menuPanelWrapper.addClass('is-opened'); 23917 this.ui.$menuPanelOverlay.addClass('active'); 23918 this.ui.$body.addClass('is-locked'); 23919 }, 23920 closeNavigation: function closeNavigation(e) { 23921 e.preventDefault(); 23922 this.ui.$menuPanelWrapper.removeClass('is-opened'); 23923 this.ui.$menuPanelOverlay.removeClass('active'); 23924 this.ui.$body.removeClass('is-locked'); 23925 }, 23926 openExpend: function openExpend(e) { 23927 e.preventDefault(); 23928 var $wrapper = $(this).hasClass('js-menu-panel-expend-wrapper') ? $(this) : $(this).closest('.js-menu-panel-expend-wrapper'), 23929 $expend = $wrapper.find('.js-menu-panel-expend').first(), 23930 $menuExpend = $expend.find('.navigation__expends'); 23931 if ($expend.hasClass('is-opened')) { 23932 $expend.height(0); 23933 $expend.removeClass('is-opened'); 23934 } else { 23935 $expend.addClass('is-opened'); 23936 $expend.height($menuExpend.outerHeight()); 23937 } 23938 }, 23939 closeExpend: function closeExpend(e) { 23940 e.preventDefault(); 23941 var $wrapper = $(this).closest('.js-menu-panel-expend'); 23942 $wrapper.removeClass('is-opened'); 23943 } 23944}; 23945module.exports = navigationPanel; 23946 23947},{}],39:[function(require,module,exports){ 23948"use strict"; 23949 23950var _ = require('underscore'); 23951var newsList = { 23952 ui: {}, 23953 newsJSON: {}, 23954 init: function init() { 23955 this.bindUI(); 23956 this.bindEvents(); 23957 this.getData(); 23958 }, 23959 bindUI: function bindUI() { 23960 this.ui.$win = $(window); 23961 this.ui.$body = $('body'); 23962 this.ui.$urlJson = $('.js-json-url').data('json'); 23963 console.log(this.ui.$urlJson); 23964 }, 23965 bindEvents: function bindEvents() { 23966 //this.ui.$btnProduct.on('click', $.proxy(this.openProduct, this)); 23967 }, 23968 getData: function getData(e) { 23969 $.getJSON(this.ui.$urlJson, function (data) { 23970 self.newsJSON = data; 23971 }).done(function (data) { 23972 // LOAD ok 23973 }); 23974 } 23975}; 23976module.exports = newsList; 23977 23978},{"underscore":8}],40:[function(require,module,exports){ 23979"use strict"; 23980 23981function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 23982function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 23983function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 23984function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 23985function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 23986function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 23987var Comparator = /*#__PURE__*/function () { 23988 function Comparator($panel, $btnPanel, storage) { 23989 _classCallCheck(this, Comparator); 23990 this.$panel = $panel; 23991 this.$btnPanel = $btnPanel; 23992 this.$el = $('.panel-comparator__inner'); 23993 this.url = $panel.data('service'); 23994 this.storage = storage; 23995 this.trans = $panel.data('i18n'); 23996 this.init(); 23997 this.bind(); 23998 } 23999 return _createClass(Comparator, [{ 24000 key: "init",
24001 value: function init() { 24002 var self = this; 24003 var reqData = { 24004 site: window.nexansConfig.site, 24005 language: document.documentElement.lang, 24006 ids: this.storage.data.familyIds 24007 }; 24008 $.ajax({ 24009 url: self.url, 24010 type: 'get', 24011 dataType: 'json', 24012 contentType: 'application/json', 24013 data: reqData, 24014 traditional: true 24015 }).done(function (data) { 24016 self.data = data; 24017 self.render(); 24018 }); 24019 } 24020 }, { 24021 key: "bind", 24022 value: function bind() { 24023 this.$el.click(); 24024 var self = this; 24025 this.$el.on('click', '.btn-switch', function (e) { 24026 e.preventDefault(); 24027 self.$el.toggleClass('highlighted'); 24028 }); 24029 this.$el.on('click', '.js-remove', function (e) { 24030 e.preventDefault(); 24031 self.removeRow(parseInt($(this).data('index'), 10), $(this).data('id')); 24032 }); 24033 } 24034 }, { 24035 key: "removeRow", 24036 value: function removeRow(index, id) { 24037 this.data.families.splice(index, 1); 24038 this.storage.delete(parseInt(id, 10)); 24039 for (var i = 0; i < this.data.features.length; i++) { 24040 this.data.features[i].values.splice(index, 1); 24041 } 24042 $('body').trigger('comparator_update', [this.storage.count, true]); 24043 this.render(); 24044 } 24045 }, { 24046 key: "getImageUrl", 24047 value: function getImageUrl(imageId) { 24048 return window.nexansConfig.eserviceDamServiceUrl + '/image/' + imageId + '?site=' + window.nexansConfig.site + '&variant=264x264&scaleType=FILL'; 24049 } 24050 }, { 24051 key: "render", 24052 value: function render() { 24053 var output = '<table><thead><tr>'; 24054 output += '<td></td>'; 24055 for (var i = 0; i < this.data.families.length; i++) { 24056 output += '<td>'; 24057 output += '<div class="actions text-current-small"><button class="js-remove" data-index="' + i + '" data-id="' + this.data.families[i].id + '" type="button"><span>' + this.trans.remove + '</span><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><path fill="currentColor" fill-rule="evenodd" d="M10,8.58578644 L4.34314575,2.92893219 L2.92893219,4.34314575 L8.58578644,10 L2.92893219,15.6568542 L4.34314575,17.0710678 L10,11.4142136 L15.6568542,17.0710678 L17.0710678,15.6568542 L11.4142136,10 L17.0710678,4.34314575 L15.6568542,2.92893219 L10,8.58578644 Z"/></svg></button></div>'; 24058 if ('imageId' in this.data.families[i] && this.data.families[i].imageId) { 24059 output += '<img src="' + this.getImageUrl(this.data.families[i].imageId) + '" alt="' + this.data.families[i].name + '">'; 24060 } 24061 output += '<h3>' + this.data.families[i].name + '</h3>'; 24062 } 24063 output += '</tr></thead><tbody>'; 24064 for (var _i = 0; _i < this.data.features.length; _i++) { 24065 var same = this.data.features[_i].values.every(function (val, ind, arr) { 24066 return val === arr[0]; 24067 }); 24068 output += '<tr class="' + (same ? 'same' : 'diff') + '">'; 24069 output += '<td class="title">' + this.data.features[_i].name + '</td>'; 24070 for (var j = 0; j < this.data.features[_i].values.length; j++) { 24071 if (this.data.features[_i].values[j] === '##-##') { 24072 output += '<td>' + this.trans['specific_per_product'] + '</td>'; 24073 } else { 24074 output += '<td>' + this.data.features[_i].values[j] + '</td>'; 24075 } 24076 } 24077 output += '</tr>'; 24078 } 24079 output += '</tbody></table>'; 24080 this.$panel.removeAttr('style'); 24081 this.$el.html(output); 24082 this.$panel.width(this.$el.find('table').width() + 40); 24083 } 24084 }]); 24085}(); 24086var panelComparator = { 24087 ui: {}, 24088 init: function init(storage) { 24089 this.bindUI(); 24090 this.bindEvents(storage); 24091 }, 24092 bindUI: function bindUI() { 24093 this.ui.$win = $(window); 24094 this.ui.$body = $('body'); 24095 this.ui.$document = $(document); 24096 this.ui.$btnProduct = $('.js-open-panel-comparator'); 24097 this.ui.$panel = $('.js-panel-comparator'); 24098 this.ui.$container = this.ui.$panel.find('.js-panel-container'); 24099 this.ui.$mask = $('.js-overlay'); 24100 this.ui.$close = this.ui.$panel.find('.js-close-panel'); 24101 }, 24102 bindEvents: function bindEvents(storage) { 24103 var self = this; 24104 this.ui.$btnProduct.on('click', function (e) {
24105 self.openPanel(e, storage); 24106 }); 24107 this.ui.$close.on('click', $.proxy(this.closePanel, this)); 24108 this.ui.$mask.on('click', $.proxy(this.closePanel, this)); 24109 }, 24110 /* Desktop */ 24111 24112 openPanel: function openPanel(e, storage) { 24113 e.preventDefault(); 24114 if (!!this.ui.$btnProduct.hasClass('is-disabled')) return; 24115 this.ui.$body.addClass('is-locked'); 24116 this.ui.$panel.addClass('is-open'); 24117 this.ui.$mask.addClass('active'); 24118 new Comparator(this.ui.$panel, this.ui.$btnProduct, storage); 24119 }, 24120 closePanel: function closePanel(e) { 24121 e.preventDefault(); 24122 this.ui.$body.removeClass('is-locked'); 24123 this.ui.$panel.removeClass('is-open'); 24124 this.ui.$mask.removeClass('active'); 24125 24126 // Close by keyboard. 24127 if (e.keyCode === 27) { 24128 this.ui.$body.removeClass('is-locked'); 24129 this.ui.$panel.removeClass('is-open'); 24130 this.ui.$mask.removeClass('active'); 24131 } 24132 } 24133}; 24134module.exports = panelComparator; 24135 24136},{}],41:[function(require,module,exports){ 24137"use strict"; 24138 24139var contactForm = { 24140 ui: {}, 24141 topic: [], 24142 valid: false, 24143 init: function init() { 24144 this.bindUI(); 24145 this.initElements(); 24146 this.reCaptchaSiteKey = this.ui.$contactForm.data("recaptcha_sitekey"); 24147 this.bindEvents(); 24148 }, 24149 bindUI: function bindUI() { 24150 this.ui.$body = $('body'); 24151 this.ui.$document = $(document); 24152 this.ui.$panel = $('.js-panel-contact'); 24153 this.ui.$formContainer = ''; 24154 this.ui.$contactForm = ''; 24155 this.ui.$validation = ''; 24156 this.ui.$errorInfo = ''; 24157 this.ui.$required = ''; 24158 this.ui.$selectRequired = ''; 24159 this.ui.$topic = ''; 24160 this.ui.$requiredEmail = ''; 24161 this.ui.$validationMsg = ''; 24162 this.ui.$success = ''; 24163 this.ui.$error = ''; 24164 }, 24165 initElements: function initElements() { 24166 var _this = this; 24167 this.ui.$panel.each(function (n, item) { 24168 _this.ui.$formContainer = $(item).find('.js-form'); 24169 _this.ui.$contactForm = $(item).find('.js-contact-form'); 24170 _this.ui.$errorInfo = $(item).find('.js-error-info'); 24171 _this.ui.$required = $(item).find('.js-required'); 24172 _this.ui.$selectRequired = $(item).find('.js-select-required'); 24173 _this.ui.$topic = $(item).find('.js-select-topic'); 24174 _this.ui.$requiredEmail = $(item).find('.js-mail-required'); 24175 _this.ui.$validation = $(item).find('.js-contact-validation'); 24176 _this.ui.$validationMsg = $(item).closest('.panel-contact').find('.js-validation'); 24177 _this.ui.$success = $(item).closest('.panel-contact').find('.js-contact-success'); 24178 _this.ui.$error = $(item).closest('.panel-contact').find('.js-contact-error'); 24179 }); 24180 }, 24181 bindEvents: function bindEvents() { 24182 var _this2 = this; 24183 this.ui.$topic.on('change', function (e) { 24184 return _this2.topics(e); 24185 }); 24186 this.ui.$required.on('keyup', function (e) { 24187 return _this2.controlChange(e); 24188 }); 24189 this.ui.$selectRequired.on('change', function (e) { 24190 return _this2.controlChange(e); 24191 }); 24192 this.ui.$validation.on('click', function (e) { 24193 return _this2.controlForm(e); 24194 }); 24195 },
24196 topics: function topics(e) { 24197 var id = $(e.currentTarget).find(':checkbox').attr('id'); 24198 24199 // Tags list 24200 if (id.length) { 24201 if (this.topic.includes(id)) { 24202 var index = this.topic.indexOf(id); 24203 if (index !== -1) this.topic.splice(index, 1); 24204 } else { 24205 // add item on array tags. 24206 this.topic.push(id); 24207 } 24208 } 24209 }, 24210 controlForm: function controlForm(e) { 24211 var _this3 = this; 24212 if (this.reCaptchaSiteKey) { 24213 var response = grecaptcha.getResponse(0); 24214 if (response.length == 0) { 24215 return false; 24216 } 24217 } 24218 var ofTop = $('body').offset().top; 24219 24220 // check all input. 24221 this.ui.$required.each(function (e, item) { 24222 if ($(item).val() == '') { 24223 // Set required input. 24224 $(item).addClass('is-required'); 24225 24226 // Show msg error. 24227 _this3.ui.$errorInfo.fadeIn(); 24228 24229 // back to top. 24230 $(item).closest('.panel-contact').scrollTop(ofTop); 24231 } else if ($(item).hasClass('is-required') && $(item).val() != "") { 24232 $(item).removeClass('is-required'); 24233 } 24234 if (_this3.ui.$selectRequired.val() == null) { 24235 $(item).addClass('is-required'); 24236 } 24237 }); 24238 24239 // check input mail. 24240 this.ui.$requiredEmail.each(function (n, item) { 24241 if (item.checkValidity()) { 24242 $(item).parent().removeClass('warning'); 24243 } else { 24244 $(item).parent().addClass('warning'); 24245 } 24246 }); 24247 if (!this.ui.$required.hasClass('is-required') && !this.ui.$requiredEmail.parent().hasClass('warning')) { 24248 this.valid = true; 24249 } else { 24250 this.valid = false; 24251 } 24252 if (this.valid) { 24253 this.ui.$validation.closest('.js-form').removeClass('form-hidden').hide(); 24254 this.ui.$validationMsg.addClass('form-show').show(); 24255 this.postForm(e); 24256 return false; 24257 } else { 24258 return false; 24259 } 24260 }, 24261 controlChange: function controlChange(e) { 24262 if ($(e.currentTarget).val() != "") { 24263 $(e.currentTarget).removeClass('is-required'); 24264 } 24265 $(e.currentTarget).removeClass('is-required'); 24266 }, 24267 postForm: function postForm(e) { 24268 e.preventDefault(); 24269 var self = this, 24270 resourceUrl = this.ui.$contactForm.find("#url").val(); 24271 var requestdata = { 24272 topics: this.topic, 24273 siteId: this.ui.$contactForm.find("#site").val(), 24274 pageId: this.ui.$contactForm.find("#pageid").val(), 24275 firstName: this.ui.$contactForm.find("input[name='first-name']").val(), 24276 lastName: this.ui.$contactForm.find("input[name='last-name']").val(), 24277 email: this.ui.$contactForm.find("input[name='email']").val(), 24278 phone: this.ui.$contactForm.find("input[name='phone-number']").val(), 24279 country: this.ui.$contactForm.find("select[name='country']").val(), 24280 company: this.ui.$contactForm.find("input[name='company']").val(), 24281 address: this.ui.$contactForm.find("input[name='address']").val(), 24282 postalCode: this.ui.$contactForm.find("input[name='postal-code']").val(), 24283 city: this.ui.$contactForm.find("input[name='city']").val(), 24284 subject: this.ui.$contactForm.find("input[name='subject']").val(), 24285 message: this.ui.$contactForm.find("textarea[name='message']").val(), 24286 hCaptchaToken: this.ui.$contactForm.find("textarea[name='h-captcha-response']").val(), 24287 emailCopy: this.ui.$contactForm.find("#send-copy").prop('checked') 24288 }; 24289 $.ajax({ 24290 url: resourceUrl, 24291 type: 'POST', 24292 data: JSON.stringify(requestdata), 24293 contentType: "application/json; charset=utf-8", 24294 dataType: 'json', 24295 success: function success(html, status) { 24296 self.ui.$success.show(); 24297 }, 24298 error: function error(result, status, _error) { 24299 self.ui.$error.show(); 24300 } 24301 }); 24302 this.valid = false; 24303 } 24304}; 24305module.exports = contactForm; 24306 24307},{}],42:[function(require,module,exports){ 24308"use strict"; 24309 24310var contactFormSpe = { 24311 ui: {}, 24312 valid: false, 24313 init: function init() { 24314 this.bindUI(); 24315 this.initElements(); 24316 this.reCaptchaSiteKey = this.ui.$contactForm.data("recaptcha_sitekey"); 24317 this.bindEvents(); 24318 }, 24319 bindUI: function bindUI() { 24320 this.ui.$body = $('body'); 24321 this.ui.$document = $(document); 24322 this.ui.$panel = $('.js-panel-contact-spe'); 24323 this.ui.$formContainer = ''; 24324 this.ui.$contactForm = ''; 24325 this.ui.$validation = ''; 24326 this.ui.$errorInfo = ''; 24327 this.ui.$required = ''; 24328 this.ui.$selectRequired = ''; 24329 this.ui.$requiredEmail = ''; 24330 this.ui.$validationMsg = ''; 24331 this.ui.$success = ''; 24332 this.ui.$error = ''; 24333 }, 24334 initElements: function initElements() { 24335 var _this = this; 24336 this.ui.$panel.each(function (n, item) { 24337 _this.ui.$formContainer = $(item).find('.js-form'); 24338 _this.ui.$contactForm = $(item).find('.js-contact-form'); 24339 _this.ui.$errorInfo = $(item).find('.js-error-info'); 24340 _this.ui.$required = $(item).find('.js-required'); 24341 _this.ui.$selectRequired = $(item).find('.js-select-required'); 24342 _this.ui.$requiredEmail = $(item).find('.js-mail-required'); 24343 _this.ui.$validation = $(item).find('.js-contact-validation'); 24344 _this.ui.$validationMsg = $(item).closest('.panel-contact').find('.js-validation'); 24345 _this.ui.$success = $(item).closest('.panel-contact').find('.js-contact-success'); 24346 _this.ui.$error = $(item).closest('.panel-contact').find('.js-contact-error'); 24347 }); 24348 }, 24349 bindEvents: function bindEvents() { 24350 var _this2 = this; 24351 this.ui.$required.on('keyup', function (e) { 24352 return _this2.controlChange(e); 24353 }); 24354 this.ui.$selectRequired.on('change', function (e) { 24355 return _this2.controlChange(e); 24356 }); 24357 this.ui.$validation.on('click', function (e) { 24358 return _this2.controlForm(e); 24359 }); 24360 }, 24361 controlForm: function controlForm(e) { 24362 var _this3 = this; 24363 if (this.reCaptchaSiteKey) { 24364 var response = grecaptcha.getResponse(1); 24365 if (response.length == 0) { 24366 return false;
24367 } 24368 } 24369 var ofTop = $('body').offset().top; 24370 24371 // check all input. 24372 this.ui.$required.each(function (e, item) { 24373 if ($(item).val() == '') { 24374 // Set required input. 24375 $(item).addClass('is-required'); 24376 24377 // Show msg error. 24378 _this3.ui.$errorInfo.fadeIn(); 24379 24380 // back to top. 24381 $(item).closest('.panel-contact').scrollTop(ofTop); 24382 } else if ($(item).hasClass('is-required') && $(item).val() != "") { 24383 $(item).removeClass('is-required'); 24384 } 24385 if (_this3.ui.$selectRequired.val() == null) { 24386 $(item).addClass('is-required'); 24387 } 24388 }); 24389 24390 // check input mail. 24391 this.ui.$requiredEmail.each(function (n, item) { 24392 var check = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/; 24393 var val = $(item).val(); 24394 if (check.test(val)) { 24395 $(item).parent().removeClass('warning'); 24396 } else { 24397 $(item).parent().addClass('warning'); 24398 } 24399 }); 24400 if (!this.ui.$required.hasClass('is-required') && !this.ui.$requiredEmail.parent().hasClass('warning')) { 24401 this.valid = true; 24402 } else { 24403 this.valid = false; 24404 } 24405 if (this.valid) { 24406 this.ui.$validation.closest('.js-form').addClass('form-hidden').hide(); 24407 this.ui.$validationMsg.addClass('form-show').show(); 24408 this.postForm(e); 24409 return false; 24410 } else { 24411 return false; 24412 } 24413 }, 24414 controlChange: function controlChange(e) { 24415 if ($(e.currentTarget).val() != "") { 24416 $(e.currentTarget).removeClass('is-required'); 24417 } 24418 $(e.currentTarget).removeClass('is-required'); 24419 }, 24420 postForm: function postForm(e) { 24421 e.preventDefault(); 24422 var self = this, 24423 resourceUrl = this.ui.$contactForm.find("#url").val(); 24424 var requestdata = { 24425 contactId: this.ui.$contactForm.find("#contactid").val(), 24426 pageId: this.ui.$contactForm.find("#pageid").val(), 24427 siteId: this.ui.$contactForm.find("#site").val(), 24428 firstName: this.ui.$contactForm.find("input[name='first-name']").val(), 24429 lastName: this.ui.$contactForm.find("input[name='last-name']").val(), 24430 email: this.ui.$contactForm.find("input[name='email']").val(), 24431 phone: this.ui.$contactForm.find("input[name='phone-number']").val(), 24432 country: this.ui.$contactForm.find("select[name='country']").val(), 24433 company: this.ui.$contactForm.find("input[name='company']").val(), 24434 address: this.ui.$contactForm.find("input[name='address']").val(), 24435 postalCode: this.ui.$contactForm.find("input[name='postal-code']").val(), 24436 city: this.ui.$contactForm.find("input[name='city']").val(), 24437 subject: this.ui.$contactForm.find("input[name='subject']").val(), 24438 message: this.ui.$contactForm.find("textarea[name='message']").val(), 24439 hCaptchaToken: this.ui.$contactForm.find("textarea[name='h-captcha-response']").val(), 24440 emailCopy: this.ui.$contactForm.find("#send-copy-spe").prop('checked') 24441 }; 24442 $.ajax({ 24443 url: resourceUrl, 24444 type: 'POST', 24445 data: JSON.stringify(requestdata), 24446 contentType: "application/json; charset=utf-8", 24447 dataType: 'json', 24448 success: function success(html, status) { 24449 self.ui.$success.show(); 24450 }, 24451 error: function error(result, status, _error) { 24452 self.ui.$error.show(); 24453 } 24454 }); 24455 this.valid = false; 24456 } 24457}; 24458module.exports = contactFormSpe; 24459 24460},{}],43:[function(require,module,exports){ 24461"use strict"; 24462 24463var contactPanel = { 24464 ui: {}, 24465 init: function init() { 24466 this.bindUI(); 24467 this.bindEvents(); 24468 }, 24469 bindUI: function bindUI() { 24470 this.ui.$body = $('body'); 24471 this.ui.$document = $(document); 24472 this.ui.$checkboxes = $('.js-contact-checkboxes'); 24473 this.ui.$hidden = $('#contactid'); 24474 this.ui.$panel = $('.js-panel-contact'); 24475 this.ui.$panelSpe = $('.js-panel-contact-spe'); 24476 this.ui.$trigger = $('.js-toggle-contact'); 24477 this.ui.$triggerSpe = $('.js-toggle-contact-spe'); 24478 this.ui.$close = $('.js-close-contact'); 24479 this.ui.$closeSpe = $('.js-close-contact-spe'); 24480 this.ui.$mask = $('.js-overlay'); 24481 this.ui.$btnClose = $('.js-close-panel'); 24482 }, 24483 bindEvents: function bindEvents() { 24484 var _this = this; 24485 this.ui.$trigger.on('click', function (e) {
24486 return _this.openPanel(e); 24487 }); 24488 this.ui.$close.add(this.ui.$mask).on('click', function (e) { 24489 return _this.closePanel(e); 24490 }); 24491 this.ui.$btnClose.add(this.ui.$mask).on('click', function (e) { 24492 return _this.closePanel(e); 24493 }); 24494 this.ui.$triggerSpe.on('click', function (e) { 24495 return _this.openPanelSpe(e); 24496 }); 24497 this.ui.$closeSpe.add(this.ui.$mask).on('click', function (e) { 24498 return _this.closePanelSpe(e); 24499 }); 24500 //this.ui.$document.on('keyup', (e) => this.closePanel(e)); 24501 }, 24502 openPanel: function openPanel(e) { 24503 e.preventDefault(); 24504 var $el = $(e.currentTarget), 24505 categoryid = $el.data('categoryid'), 24506 // $checkboxes = this.ui.$checkboxes.find('input[type="checkbox"]'), 24507 $selfcheck = this.ui.$checkboxes.find('#' + categoryid); 24508 if ($selfcheck.length) { 24509 // $checkboxes.prop('checked', false); 24510 $selfcheck.prop('checked', true); 24511 } 24512 this.ui.$body.addClass('is-locked'); 24513 this.ui.$panel.add(this.ui.$mask).addClass('active'); 24514 }, 24515 openPanelSpe: function openPanelSpe(e) { 24516 e.preventDefault(); 24517 var $el = $(e.currentTarget), 24518 contactid = $el.data('contactid'), 24519 categoryid = $el.data('categoryid'); 24520 if (contactid && contactid.length > 1) { 24521 this.ui.$hidden.val(contactid); 24522 } 24523 if (!this.ui.$hidden.val() || '' == this.ui.$hidden.val()) { 24524 // no specific contact -> fallback to generic panel 24525 this.openPanel(e); 24526 return; 24527 } 24528 if (categoryid && '' != categoryid) { 24529 $selfcheck = this.ui.$checkboxes.find('#' + categoryid); 24530 if ($selfcheck.length) { 24531 $selfcheck.prop('checked', true); 24532 } 24533 } 24534 this.ui.$body.addClass('is-locked'); 24535 this.ui.$panelSpe.add(this.ui.$mask).addClass('active'); 24536 }, 24537 closePanel: function closePanel(e) { 24538 e.preventDefault(); 24539 var $el = $(e.currentTarget); 24540 if ($('.js-validation').hasClass('form-show') || $('.js-form').hasClass('form-hidden')) { 24541 $('.js-validation').removeClass('form-show').hide(); 24542 $('.js-form').removeClass('form-hidden').show(); 24543 } 24544 this.ui.$body.removeClass('is-locked'); 24545 this.ui.$panel.add(this.ui.$mask).removeClass('active'); 24546 24547 // Close by keyboard. 24548 if (e.keyCode === 27) { 24549 this.ui.$panel.add(this.ui.$mask).removeClass('active'); 24550 this.ui.$body.removeClass('is-locked'); 24551 } 24552 }, 24553 closePanelSpe: function closePanelSpe(e) { 24554 e.preventDefault(); 24555 var $el = $(e.currentTarget); 24556 if ($('.js-validation').hasClass('form-show') || $('.js-form').hasClass('form-hidden')) { 24557 $('.js-validation').removeClass('form-show').hide(); 24558 $('.js-form').removeClass('form-hidden').show(); 24559 } 24560 this.ui.$body.removeClass('is-locked'); 24561 this.ui.$panelSpe.add(this.ui.$mask).removeClass('active'); 24562 24563 // Close by keyboard. 24564 if (e.keyCode === 27) { 24565 this.ui.$panelSpe.add(this.ui.$mask).removeClass('active'); 24566 this.ui.$body.removeClass('is-locked'); 24567 } 24568 } 24569}; 24570module.exports = contactPanel; 24571 24572},{}],44:[function(require,module,exports){ 24573"use strict"; 24574 24575var dopPanel = { 24576 ui: {}, 24577 init: function init() { 24578 this.bindUI(); 24579 this.bindEvents(); 24580 }, 24581 bindUI: function bindUI() { 24582 this.ui.$body = $('body'); 24583 this.ui.$document = $(document); 24584 this.ui.$panel = $('.js-panel-dop'); 24585 this.ui.$trigger = $('.js-toggle-dop'); 24586 this.ui.$close = $('.js-close-dop'); 24587 this.ui.$mask = $('.js-overlay'); 24588 this.ui.$btnClose = $('.js-close-panel'); 24589 }, 24590 bindEvents: function bindEvents() { 24591 var _this = this; 24592 this.ui.$trigger.on('click', function (e) { 24593 return _this.openPanel(e); 24594 }); 24595 this.ui.$close.add(this.ui.$mask).on('click', function (e) { 24596 return _this.closePanel(e); 24597 }); 24598 this.ui.$btnClose.add(this.ui.$mask).on('click', function (e) { 24599 return _this.closePanel(e); 24600 }); 24601 //this.ui.$document.on('keyup', (e) => this.closePanel(e)); 24602 }, 24603 openPanel: function openPanel(e) { 24604 e.preventDefault(); 24605 this.ui.$body.addClass('is-locked'); 24606 this.ui.$panel.add(this.ui.$mask).addClass('active'); 24607 }, 24608 closePanel: function closePanel(e) { 24609 e.preventDefault(); 24610 var $el = $(e.currentTarget); 24611 this.ui.$body.removeClass('is-locked'); 24612 this.ui.$panel.add(this.ui.$mask).removeClass('active'); 24613 24614 // Close by keyboard. 24615 if (e.keyCode === 27) { 24616 this.ui.$panel.add(this.ui.$mask).removeClass('active'); 24617 this.ui.$body.removeClass('is-locked'); 24618 } 24619 } 24620}; 24621module.exports = dopPanel; 24622 24623},{}],45:[function(require,module,exports){ 24624"use strict"; 24625 24626var panelGovernance = { 24627 ui: {}, 24628 governanceJSON: {},
24629 init: function init() { 24630 this.bindUI(); 24631 this.bindEvents(); 24632 this.getData(); 24633 }, 24634 bindUI: function bindUI() { 24635 this.ui.$win = $(window); 24636 this.ui.$body = $('body'); 24637 this.ui.$overlay = $('.js-overlay'); 24638 this.ui.$trigger = $('.js-gp-trigger'); 24639 this.ui.$close = $('.js-gp-close'); 24640 this.ui.$panel = $('.js-gp-panel'); 24641 this.ui.$cover = $('.js-gp-cover'); 24642 this.ui.$name = $('.js-gp-name'); 24643 this.ui.$title = $('.js-gp-title'); 24644 this.ui.$bio = $('.js-gp-bio'); 24645 }, 24646 bindEvents: function bindEvents() { 24647 this.ui.$trigger.on('click', $.proxy(this.openPanel, this)); 24648 this.ui.$close.on('click', $.proxy(this.closePanel, this)); 24649 this.ui.$overlay.on('click', $.proxy(this.closePanel, this)); 24650 }, 24651 // getData: function getData(e) { 24652 // // TODO : Get JSON URL form data attribut 24653 // var url = window.oojson.url; 24654 // 24655 // $.getJSON(url, function(data) { 24656 // self.governanceJSON = data; 24657 // }).done(function(data) { 24658 // // Everything is alright 24659 // }); 24660 // }, 24661 24662 getData: function getData(t) { 24663 if (window.oojson.data) { 24664 self.governanceJSON = window.oojson.data; 24665 } else { 24666 var e = window.oojson.url; 24667 $.getJSON(e, function (t) { 24668 self.governanceJSON = t; 24669 }).done(function (t) {}); 24670 } 24671 }, 24672 openPanel: function openPanel(e) { 24673 e.preventDefault(); 24674 var $el = $(e.currentTarget), 24675 id = $el.data('bio'); 24676 this.ui.$overlay.addClass('active'); 24677 this.ui.$panel.addClass('active'); 24678 this.ui.$body.addClass('is-locked'); 24679 this.fillPanel(id); 24680 }, 24681 // closePanel: function closePanel(e) { 24682 // e.preventDefault(); 24683 // 24684 // this.ui.$overlay.removeClass('active'); 24685 // this.ui.$panel.removeClass('active'); 24686 // this.ui.$body.removeClass('is-locked'); 24687 // }, 24688 24689 closePanel: function closePanel(e) { 24690 e.preventDefault(); 24691 24692 // Close by btn close or mask. 24693 if (this.ui.$panel.hasClass('active') || $(e.currentTarget).hasClass('js-gp-mask')) { 24694 this.ui.$overlay.removeClass('active'); 24695 this.ui.$panel.removeClass('active'); 24696 this.ui.$body.removeClass('is-locked'); 24697 } 24698 ; 24699 }, 24700 fillPanel: function fillPanel(id) { 24701 this.ui.$cover.css('background-image', 'url(' + self.governanceJSON[id]["cover"] + ')'); 24702 this.ui.$name.html(self.governanceJSON[id]["name"]); 24703 this.ui.$title.html(self.governanceJSON[id]["title"]); 24704 this.ui.$bio.html(self.governanceJSON[id]["bio"]); 24705 } 24706}; 24707module.exports = panelGovernance; 24708 24709},{}],46:[function(require,module,exports){ 24710"use strict"; 24711 24712var panelLogin = { 24713 ui: {}, 24714 init: function init() { 24715 this.bindUI(); 24716 this.bindEvents(); 24717 }, 24718 bindUI: function bindUI() { 24719 this.ui.$document = $(document); 24720 var forms = $('.js-user-login-form'); 24721 this.ui.$loginForm = forms.find('.js-user-sign-form'); 24722 this.ui.$resetForm = forms.find('.js-user-reset-form'); 24723 this.ui.$showResetForm = forms.find('.js-show-user-reset-form'); 24724 this.ui.$showSignForm = forms.find('.js-show-user-sign-form'); 24725 this.ui.$signInput = this.ui.$loginForm.find('.js-email-field'); 24726 this.ui.$resetInput = this.ui.$resetForm.find('.js-email-field'); 24727 }, 24728 bindEvents: function bindEvents() { 24729 var self = this; 24730 this.ui.$showResetForm.on('click', function (e) { 24731 e.preventDefault(); 24732 self.ui.$loginForm.hide(); 24733 self.ui.$resetForm.show(); 24734 }); 24735 this.ui.$showSignForm.on('click', function (e) { 24736 e.preventDefault(); 24737 self.ui.$resetForm.hide(); 24738 self.ui.$loginForm.show(); 24739 }); 24740 this.ui.$signInput.on('input', function () { 24741 self.ui.$resetInput.val($(this).val()); 24742 }); 24743 this.ui.$resetInput.on('input', function () { 24744 self.ui.$signInput.val($(this).val()); 24745 }); 24746 this.ui.$loginForm.submit(function (e) { 24747 e.preventDefault(); 24748 var data = {}; 24749 var url = window.nexans_ctx + '/.rest/user/v1/authenticate'; 24750 if (self.ui.$loginForm.find('button[type="submit"]').hasClass('user-login')) { 24751 // user log-in with un/pw 24752 var usernameInput = self.ui.$loginForm.find('input[name=mgnlUserId]'); 24753 usernameInput.removeClass('error'); 24754 var passwordInput = self.ui.$loginForm.find('input[name=mgnlUserPSWD]'); 24755 passwordInput.removeClass('error'); 24756 self.ui.$loginForm.find('.error-message').removeClass('error'); 24757 var username = usernameInput.val(); 24758 var password = passwordInput.val(); 24759 if (!password) { 24760 passwordInput.addClass('error'); 24761 passwordInput.focus(); 24762 } 24763 if (!username) { 24764 usernameInput.addClass('error'); 24765 usernameInput.focus(); 24766 } 24767 if (!username || !password) { 24768 return; 24769 } 24770 data.userId = username; 24771 data.password = password; 24772 //url += '/current?mgnlUserId=' + username + '&mgnlUserPSWD=' + password; 24773 //url += '/authenticate?foo=bar'; 24774 jQuery.ajax({ 24775 method: "POST", 24776 url: url, 24777 data: self.ui.$loginForm.serialize(), 24778 success: function success(data) { 24779 location.reload(); 24780 } 24781 }).fail(function (xhr, status, error) { 24782 console.error("Login failed with status ".concat(xhr.status)); 24783 usernameInput.addClass('error').focus(); 24784 passwordInput.addClass('error'); 24785 self.ui.$loginForm.find('.error-message').addClass('error'); 24786 }); 24787 } else { 24788 // editor log-in through cms user session 24789 //url += '/authenticate?nexans-site=${window.nexans_site}'; 24790 jQuery.ajax({ 24791 url: url, 24792 type: 'GET', 24793 contentType: 'application/json', 24794 success: function success(data) { 24795 location.reload(); 24796 } 24797 }).fail(function (xhr, status, error) { 24798 console.error("Login failed with status ".concat(xhr.status)); 24799 self.ui.$loginForm.find('.error-message').addClass('error'); 24800 }); 24801 } 24802 }); 24803 } 24804}; 24805module.exports = panelLogin; 24806 24807},{}],47:[function(require,module,exports){ 24808"use strict"; 24809 24810var panelNewsletter = { 24811 ui: {},
24812 init: function init() { 24813 this.bindUI(); 24814 this.bindEvents(); 24815 }, 24816 bindUI: function bindUI() { 24817 this.ui.$win = $(window); 24818 this.ui.$body = $('body'); 24819 this.ui.$document = $(document); 24820 this.ui.$btnProduct = $('.js-open-panel-newsletter'); 24821 this.ui.$panel = $('.js-panel-newsletter'); 24822 this.ui.$container = this.ui.$panel.find('.js-panel-container'); 24823 this.ui.$mask = $('.js-overlay'); 24824 this.ui.$close = this.ui.$panel.find('.js-close-panel'); 24825 24826 // list 24827 this.ui.entry = $('.js-list-item'); 24828 //this.ui.$subEntry = $('.js-list-subnav'); 24829 }, 24830 bindEvents: function bindEvents() { 24831 this.ui.$btnProduct.on('click', $.proxy(this.openPanel, this)); 24832 this.ui.$close.on('click', $.proxy(this.closePanel, this)); 24833 //this.ui.$document.on('keyup', $.proxy(this.closePanel, this)); 24834 this.ui.$mask.on('click', $.proxy(this.closePanel, this)); 24835 // this.ui.entry.on('mouseenter', $.proxy(this.showSubNav, this)); 24836 24837 // nav mobile version 24838 if (this.ui.$win.outerWidth >= 767) { 24839 this.ui.entry.on('click', $.proxy(this.mobShowSubNav, this)); 24840 } 24841 }, 24842 /* Desktop */ 24843 24844 openPanel: function openPanel(e) { 24845 e.preventDefault(); 24846 24847 // this.ui.$body.addClass('is-panel-solution-open'); 24848 this.ui.$body.addClass('is-locked'); 24849 this.ui.$panel.addClass('is-open'); 24850 this.ui.$mask.addClass('active'); 24851 }, 24852 closePanel: function closePanel(e) { 24853 e.preventDefault(); 24854 this.ui.$body.removeClass('is-locked'); 24855 this.ui.$panel.removeClass('is-open'); 24856 this.ui.$mask.removeClass('active'); 24857 24858 // Close by keyboard. 24859 if (e.keyCode === 27) { 24860 this.ui.$body.removeClass('is-locked'); 24861 this.ui.$panel.removeClass('is-open'); 24862 this.ui.$mask.removeClass('active'); 24863 } 24864 }, 24865 showSubNav: function showSubNav(e) { 24866 //get this 24867 var $this = $(e.currentTarget); 24868 24869 //remove all subnav. 24870 this.ui.entry.removeClass('is-open'); 24871 $this.addClass('is-open'); 24872 }, 24873 hideSubNav: function hideSubNav(e) { 24874 setTimeout(function () { 24875 $(e.currentTarget).removeClass('is-open'); 24876 }, 200); 24877 }, 24878 /* Mobile nav */ 24879 24880 mobShowSubNav: function mobShowSubNav(e) { 24881 e.preventDefault(); 24882 console.log(e); 24883 } 24884}; 24885module.exports = panelNewsletter; 24886 24887},{}],48:[function(require,module,exports){ 24888"use strict"; 24889 24890var loadProductPanel = { 24891 ui: {}, 24892 productJSON: {}, 24893 products: [], 24894 related: [], 24895 init: function init() { 24896 this.bindUI(); 24897 this.bindEvents(); 24898 this.getData(); 24899 }, 24900 bindUI: function bindUI() { 24901 this.ui.$win = $(window); 24902 this.ui.$body = $('body'); 24903 this.ui.$document = $(document); 24904 this.ui.$openSolution = $('.js-open-panel-solution'); 24905 this.ui.$btnProduct = $('.js-load-product'); 24906 this.ui.$panel = $('.js-panel-product');
24907 this.ui.$overlay = $('.js-overlay'); 24908 this.ui.$close = this.ui.$panel.find('.js-close-panel'); 24909 24910 // Panel elements 24911 this.ui.$jsonCategory = $('.js-json-category'); 24912 this.ui.$jsonName = $('.js-json-name'); 24913 this.ui.$jsonCover = $('.js-json-cover'); 24914 this.ui.$jsonInfos = $('.js-json-infos'); 24915 this.ui.$jsonUrl = $('.js-json-url'); 24916 this.ui.$jsonRelated = $('.js-json-related'); 24917 this.ui.$jsonCoverMobile = $('.js-json-cover-mobile'); 24918 }, 24919 bindEvents: function bindEvents() { 24920 var _this = this; 24921 this.ui.$btnProduct.on('click', $.proxy(this.openProduct, this)); 24922 this.ui.$close.on('click', $.proxy(this.closePanel, this)); 24923 this.ui.$overlay.on('click', $.proxy(this.closePanel, this)); 24924 //this.ui.$document.on('keyup', $.proxy(this.closePanel, this)); 24925 24926 this.ui.$openSolution.on('click', function (e) { 24927 return _this.showSolution(e); 24928 }); 24929 }, 24930 // getData: function getData(e) { 24931 // var url = window.oojson.url; 24932 // 24933 // $.getJSON(url, function(data) { 24934 // self.productJSON = data; 24935 // }).done(function(data) { 24936 // }); 24937 // }, 24938 24939 getData: function getData(e) { 24940 if (window.oojson.data) { 24941 self.productJSON = window.oojson.data; 24942 } else { 24943 var e = window.oojson.url; 24944 $.getJSON(e, function (t) { 24945 self.productJSON = t; 24946 }).done(function (t) {}); 24947 } 24948 }, 24949 openProduct: function openProduct(e) { 24950 // get ID of product selected. 24951 var $el = $(e.currentTarget), 24952 id = $el.data('productid'); 24953 this.clearProduct(); 24954 24955 // Load product by ID. 24956 this.loadProduct(id); 24957 24958 // Open overlay. 24959 this.ui.$overlay.addClass('active'); 24960 this.ui.$panel.addClass('is-open'); 24961 this.ui.$body.addClass('is-locked'); 24962 }, 24963 showSolution: function showSolution(e) { 24964 e.preventDefault(); 24965 this.ui.$panel.removeClass('is-open'); 24966 }, 24967 closePanel: function closePanel(e) { 24968 e.preventDefault(); 24969 this.ui.$body.removeClass('is-locked'); 24970 this.ui.$panel.removeClass('is-open'); 24971 this.ui.$overlay.removeClass('active'); 24972 24973 // Close by keyboard. 24974 if (e.keyCode === 27) { 24975 this.ui.$body.removeClass('is-locked'); 24976 this.ui.$panel.removeClass('is-open'); 24977 this.ui.$overlay.removeClass('active'); 24978 } 24979 }, 24980 clearProduct: function clearProduct() { 24981 // Clear planel product. 24982 this.ui.$jsonCategory.html(''); 24983 this.ui.$jsonName.html(''); 24984 this.ui.$jsonCover.attr('src', ''); 24985 this.ui.$jsonCoverMobile.attr('src', ''); 24986 this.ui.$jsonInfos.html(''); 24987 this.ui.$jsonUrl.attr('href', '').removeClass('hidden'); 24988 this.ui.$jsonRelated.html(''); 24989 this.ui.$openSolution.addClass('hidden'); 24990 }, 24991 loadProduct: function loadProduct(id) { 24992 // ID of product selected. 24993 var reference_id = id; 24994 24995 // Foreach all product items form JSON. 24996 for (var i = 0; i < self.productJSON.length; i++) { 24997 // Get product select by ID. 24998 if (self.productJSON[i]["id"] == reference_id) { 24999 var id = self.productJSON[i]["id"], 25000 categoryID = self.productJSON[i]["category_id"]; 25001 25002 //console.log(self.productJSON[i]["name"]); 25003 this.ui.$jsonCategory.html(self.productJSON[i]["category_name"]); 25004 this.ui.$jsonName.html(self.productJSON[i]["name"]); 25005 this.ui.$jsonCover.attr('src', self.productJSON[i]["cover_large"]); 25006 this.ui.$jsonCoverMobile.attr('src', self.productJSON[i]["cover_mobile"]); 25007 this.ui.$jsonInfos.html(self.productJSON[i]["resume"]); 25008 if (self.productJSON[i]["url_product"] && self.productJSON[i]["url_product"].length) { 25009 this.ui.$jsonUrl.attr('href', self.productJSON[i]["url_product"]); 25010 this.ui.$openSolution.addClass('hidden'); 25011 } else { 25012 this.ui.$jsonUrl.addClass('hidden'); 25013 this.ui.$openSolution.removeClass('hidden'); 25014 } 25015 this.realatedProduct(id, categoryID); 25016 } 25017 } 25018 }, 25019 realatedProduct: function realatedProduct(id, categoryID) { 25020 var related = []; 25021 25022 // Search product related 25023 $.each(self.productJSON, function () { 25024 // select product with same category ID 25025 if (this.category_id == categoryID) { 25026 // escape current product with ID 25027 // push infos related in array
25028 if (this.id != id) { 25029 related.push(this); 25030 } 25031 } 25032 }); 25033 25034 // Shuffle array for set random position of elements 25035 function Shuffle(o) { 25036 for (var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x); 25037 return o; 25038 } 25039 ; 25040 var arrayShuff = Shuffle(related); 25041 this.buildRelated(arrayShuff); 25042 }, 25043 buildRelated: function buildRelated(related) { 25044 var nb = 0; 25045 25046 // Get infos form array 25047 $.each(related, function () { 25048 nb++; 25049 25050 // select only 2 items form Array 25051 if (nb < 3) { 25052 var relatedTpl = '<div class="panel-product__content__related--cell">' + '<div class="box box__item trailer-60">' + '<div class="box__item__cover box__item__cover--full js-related-item" data-productid="' + this.id + '">' + '<img src="' + this.cover_small + '" alt="">' + '</div>' + '<div class="box__item__info">' + this.category_name + '</div>' + '<div class="box box__item trailer-60">' + '<div class="box__item__title js-related-item" data-productid="' + this.id + '">' + this.name + '</div>' + ' </div> </div>'; 25053 $('.js-json-related').append(relatedTpl); 25054 } 25055 }); 25056 25057 // Get new items and bind events. 25058 this.ui.$relatedItem = this.ui.$panel.find('.js-related-item'); 25059 this.ui.$relatedItem.on('click', $.proxy(this.reloadPanel, this)); 25060 }, 25061 reloadPanel: function reloadPanel(e) { 25062 // get ID of product selected. 25063 var $el = $(e.currentTarget), 25064 id = $el.data('productid'); 25065 25066 // Clear panel 25067 this.clearProduct(); 25068 25069 // Load panel width ID 25070 this.loadProduct(id); 25071 25072 // scroll animation 25073 this.ui.$panel.animate({ 25074 scrollTop: $('body').offset().top 25075 }, '500'); 25076 } 25077}; 25078module.exports = loadProductPanel; 25079 25080},{}],49:[function(require,module,exports){ 25081"use strict"; 25082 25083var panelSolutions = { 25084 ui: {}, 25085 init: function init() { 25086 this.bindUI(); 25087 this.bindEvents(); 25088 }, 25089 bindUI: function bindUI() { 25090 this.ui.$win = $(window); 25091 this.ui.$body = $('body'); 25092 this.ui.$document = $(document); 25093 this.ui.$btnProduct = $('.js-open-panel-solution'); 25094 this.ui.$panel = $('.js-panel-solution'); 25095 this.ui.$btnBack = $('.js-sub-back'); 25096 this.ui.$container = this.ui.$panel.find('.js-panel-container'); 25097 this.ui.$mask = $('.js-overlay'); 25098 this.ui.$close = this.ui.$panel.find('.js-close-panel'); 25099 25100 // list 25101 this.ui.entry = $('.js-list-item'); 25102 this.ui.wrapper = $('.js-list-wrapper'); 25103 }, 25104 bindEvents: function bindEvents() { 25105 // Modal. 25106 this.ui.$btnProduct.on('click', $.proxy(this.openPanel, this)); 25107 this.ui.$close.on('click', $.proxy(this.closePanel, this)); 25108 this.ui.$mask.on('click', $.proxy(this.closePanel, this)); 25109 25110 // List. 25111 this.ui.entry.on('click', $.proxy(this.showSubNav, this)); 25112 25113 // Only mobile version. 25114 this.ui.$btnBack.on('click', $.proxy(this.backMobile, this)); 25115 }, 25116 /* Desktop */ 25117 25118 openPanel: function openPanel(e) { 25119 e.preventDefault(); 25120 25121 // this.ui.$body.addClass('is-panel-solution-open'); 25122 this.ui.$body.addClass('is-locked'); 25123 this.ui.$panel.addClass('is-open'); 25124 this.ui.$mask.addClass('active'); 25125 }, 25126 closePanel: function closePanel(e) { 25127 e.preventDefault(); 25128 this.ui.$body.removeClass('is-locked'); 25129 this.ui.$panel.removeClass('is-open'); 25130 this.ui.$mask.removeClass('active'); 25131 25132 // Close by keyboard. 25133 if (e.keyCode === 27) { 25134 this.ui.$body.removeClass('is-locked'); 25135 this.ui.$panel.removeClass('is-open'); 25136 this.ui.$mask.removeClass('active'); 25137 } 25138 }, 25139 showSubNav: function showSubNav(e) { 25140 // e.preventDefault(); 25141 25142 //get this 25143 var $this = $(e.currentTarget); 25144 25145 //remove all subnav. 25146 this.ui.entry.removeClass('is-open'); 25147 this.ui.entry.parent().removeClass('is-translate'); 25148 $this.addClass('is-open'); 25149 $this.parent().addClass('is-translate'); 25150 }, 25151 backMobile: function backMobile(e) { 25152 // e.preventDefault(); 25153 25154 //get this. 25155 var $this = $(e.currentTarget); 25156 $('.js-list-wrapper').removeClass('is-translate'); 25157 setTimeout(function () { 25158 $('.js-list-wrapper').removeClass('is-translate'); 25159 $('.js-list-item').removeClass('is-open'); 25160 }, 100); 25161 } 25162}; 25163module.exports = panelSolutions; 25164 25165},{}],50:[function(require,module,exports){ 25166"use strict"; 25167 25168function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 25169function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 25170function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 25171function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 25172function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 25173function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 25174var StockPanel = /*#__PURE__*/function () { 25175 function StockPanel(trigger) { 25176 var _this = this; 25177 _classCallCheck(this, StockPanel);
25178 this.$trigger = $(trigger); 25179 this.$panel = $(this.$trigger.attr('href')); 25180 this.$field = $('#' + this.$trigger.data('fieldid')); 25181 this.$pager = this.$panel.find('.panel-stock-pager'); 25182 this.$table = this.$panel.find('.js-table-stock'); 25183 this.$tableBody = this.$panel.find('.js-table-stock tbody'); 25184 this.$asyncLikeForm = this.$panel.find('.async-like-form'); 25185 this.$searchForm = this.$panel.find('.js-stocks-form'); 25186 this.$searchInput = this.$searchForm.find('.js-search-input'); 25187 this.$serviceError = this.$panel.find('.service-error'); 25188 this.initialized = false; 25189 this.searchTerm = null; 25190 $(document).on('uiLoaded', function () { 25191 _this.panel = _this.$panel.data('panel'); 25192 }); 25193 this.$panel.on('opened', function () { 25194 _this.init(); 25195 }); 25196 this.activePage = 0; 25197 } 25198 return _createClass(StockPanel, [{ 25199 key: "init", 25200 value: function init() { 25201 if (!this.initialized) { 25202 this.bind(); 25203 this.initialized = true; 25204 } 25205 var oldSearch = this.searchTerm; 25206 if (!this.$searchInput.val() && this.$field.val()) { 25207 this.$searchInput.val(this.$field.val()); 25208 } 25209 this.searchTerm = this.$searchInput.val(); 25210 if (this.searchTerm.length > 1) { 25211 if (oldSearch !== this.searchTerm) { 25212 this.loadData(); 25213 } 25214 } else { 25215 this.$table.hide(); 25216 this.$pager.hide(); 25217 } 25218 } 25219 }, { 25220 key: "bind", 25221 value: function bind() { 25222 var _this2 = this; 25223 var self = this; 25224 this.$pager.on('click', 'a', this.pagerNav.bind(this)); 25225 this.$searchForm.on('submit', function (e) { 25226 e.preventDefault(); 25227 _this2.$serviceError.hide(); 25228 _this2.searchTerm = _this2.$searchInput.val(); 25229 _this2.activePage = 0; 25230 _this2.loadData(); 25231 }); 25232 this.$tableBody.on('click', 'tr', function () { 25233 self.panel.close(); 25234 self.$field.val($(this).data('ref')).trigger('stock-panel-update'); 25235 }); 25236 } 25237 }, { 25238 key: "loadData", 25239 value: function loadData() { 25240 var _this3 = this; 25241 this.$asyncLikeForm.addClass('loading'); 25242 $.ajax({ 25243 url: this.$searchForm.attr('action'), 25244 data: JSON.stringify({ 25245 searchTerm: this.searchTerm, 25246 currentPage: this.activePage 25247 }), 25248 method: "POST", 25249 contentType: "application/json" 25250 }).done(function (data, textStatus, jqXHR) { 25251 _this3.$asyncLikeForm.removeClass('loading'); 25252 _this3.numPages = data.numPages; 25253 _this3.$table.show(); 25254 if (_this3.numPages > 1) { 25255 _this3.$pager.show(); 25256 _this3.populatePager(); 25257 } else { 25258 _this3.$pager.hide(); 25259 } 25260 if (data.items.length < 1) { 25261 _this3.emptyTable(data); 25262 _this3.$serviceError.show(); 25263 } else { 25264 _this3.fillTable(data); 25265 _this3.populatePager(); 25266 } 25267 }).fail(function (xhr, status, error) { 25268 _this3.$serviceError.show(); 25269 }); 25270 } 25271 }, { 25272 key: "emptyTable", 25273 value: function emptyTable() { 25274 this.$tableBody.empty(); 25275 } 25276 }, { 25277 key: "fillTable", 25278 value: function fillTable(data) { 25279 var contents = ''; 25280 for (var i = 0; i < data.items.length; i++) { 25281 contents += '<tr data-ref="' + data.items[i].nexansRef + '"><td>' + data.items[i].nexansRef + '</td><td>' + data.items[i].countryRef + '</td><td>' + data.items[i].name + '</td></tr>'; 25282 } 25283 this.$tableBody.html(contents); 25284 } 25285 }, { 25286 key: "populatePager", 25287 value: function populatePager() { 25288 var items = ''; 25289 var start = Math.max(0, this.activePage - 2); 25290 if (start == 1) start = 0; 25291 var end = Math.min(this.numPages - 1, this.activePage + 2); 25292 if (end == this.numPages - 2) end = this.numPages - 1; 25293 if (start > 0) { 25294 items += '<li class="pager__list-item"><a href="#0">1</a></li>'; 25295 items += '<li class="pager__list-item"><span>...</span></li>'; 25296 } 25297 for (var i = start; i <= end; i++) { 25298 items += '<li class="pager__list-item"><a ' + (i == this.activePage ? 'class="is-active" ' : '') + 'href="#' + i + '">' + (i + 1) + '</a></li>'; 25299 } 25300 if (end < this.numPages - 2) { 25301 items += '<li class="pager__list-item"><span>...</span></li>'; 25302 items += '<li class="pager__list-item"><a href="#' + (this.numPages - 1) + '">' + this.numPages + '</a></li>'; 25303 } 25304 this.$pager.find('.pager__list').html(items); 25305 } 25306 }, { 25307 key: "pagerNav", 25308 value: function pagerNav(e) { 25309 e.preventDefault(); 25310 var $link = $(e.currentTarget); 25311 if ($link.parent().hasClass('pager__list-item')) { 25312 this.activePage = parseInt($link.attr('href').substring(1), 10); 25313 } else {
25314 if ($link.hasClass('pager__round--left')) { 25315 this.activePage = Math.max(0, this.activePage - 1); 25316 } else if ($link.hasClass('pager__round--right')) { 25317 this.activePage = Math.min(this.numPages - 1, this.activePage + 1); 25318 } 25319 } 25320 this.refreshItems(); 25321 } 25322 }, { 25323 key: "refreshItems", 25324 value: function refreshItems() { 25325 this.loadData(); 25326 } 25327 }]); 25328}(); 25329; 25330var stockPanel = { 25331 init: function init() { 25332 $('.js-panel-trigger-stock').each(function () { 25333 new StockPanel(this); 25334 }); 25335 } 25336}; 25337module.exports = stockPanel; 25338 25339},{}],51:[function(require,module,exports){ 25340"use strict"; 25341 25342function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 25343function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 25344function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 25345function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 25346function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 25347function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 25348var Panel = /*#__PURE__*/function () { 25349 function Panel(el, mask, body) { 25350 _classCallCheck(this, Panel); 25351 this.el = el; 25352 this.$el = $(el); 25353 this.$mask = mask; 25354 this.$body = body; 25355 this.bind(); 25356 } 25357 return _createClass(Panel, [{ 25358 key: "bind", 25359 value: function bind() { 25360 var self = this; 25361 $('.js-panel-trigger').each(function () { 25362 if (this.getAttribute('href').substr(1) == self.el.id) { 25363 var trigger = this; 25364 $(this).on('click', function (e) { 25365 e.preventDefault(); 25366 self.open(trigger); 25367 }); 25368 } 25369 }); 25370 this.$el.find('.js-close-panel').on('click', function (e) { 25371 e.preventDefault(); 25372 self.close(); 25373 }); 25374 this.$mask.on('click', function (e) { 25375 self.close(); 25376 }); 25377 } 25378 }, { 25379 key: "open", 25380 value: function open(trigger) { 25381 this.$body.addClass('is-locked'); 25382 this.$el.addClass('active'); 25383 this.$mask.addClass('active'); 25384 this.$el.trigger('opened', trigger); 25385 var self = this; 25386 $(document).on('keyup.panels', function (e) { 25387 if (e.key == "Escape") { 25388 self.close(); 25389 } 25390 }); 25391 } 25392 }, { 25393 key: "close", 25394 value: function close() { 25395 this.$body.removeClass('is-locked'); 25396 this.$el.removeClass('active'); 25397 this.$mask.removeClass('active'); 25398 this.$el.trigger('closed'); 25399 $(document).off('keyup.panels'); 25400 } 25401 }]); 25402}(); 25403var panels = { 25404 init: function init() { 25405 var $mask = $('.js-overlay'); 25406 var $body = $('body'); 25407 $('.js-panel').each(function () { 25408 $(this).data('panel', new Panel(this, $mask, $body)); 25409 }); 25410 } 25411}; 25412module.exports = panels; 25413 25414},{}],52:[function(require,module,exports){ 25415"use strict"; 25416 25417var quicklinks = { 25418 ui: {}, 25419 init: function init() { 25420 this.bindUI(); 25421 this.bindEvents(); 25422 }, 25423 bindUI: function bindUI() { 25424 this.ui.$win = $(window); 25425 this.ui.$body = $('body'); 25426 this.ui.$quicklinks = $('.js-push-quick-access'); 25427 }, 25428 bindEvents: function bindEvents() { 25429 this.ui.$win.on('scroll', $.proxy(this.showQuicklinks, this)); 25430 }, 25431 showQuicklinks: function showQuicklinks(e) { 25432 var self = this; 25433 var scrollTop = this.ui.$win.scrollTop(), 25434 contentHeight = parseInt(this.ui.$body.outerHeight()), 25435 // calcul 10% of page height 25436 contentHeightCalc = parseInt(contentHeight * 10 / 100); 25437 25438 // test position of page > if +10% of page > show quick access 25439 if (scrollTop > contentHeightCalc) { 25440 self.ui.$quicklinks.addClass('is-active'); 25441 } else { 25442 self.ui.$quicklinks.removeClass('is-active'); 25443 } 25444 } 25445}; 25446module.exports = quicklinks; 25447 25448},{}],53:[function(require,module,exports){ 25449"use strict"; 25450 25451var redirect = {
25452 init: function init() { 25453 $('select.js-redirect').on('change', function () { 25454 var val = $(this).val(); 25455 if (val) { 25456 window.location.href = val; 25457 } 25458 }); 25459 } 25460}; 25461module.exports = redirect; 25462 25463},{}],54:[function(require,module,exports){ 25464"use strict"; 25465 25466function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 25467function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 25468function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 25469function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 25470function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 25471function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 25472var RTable = /*#__PURE__*/function () { 25473 function RTable(el) { 25474 _classCallCheck(this, RTable); 25475 this.el = el; 25476 this.$el = $(el); 25477 this.$win = $(window); 25478 this.$target = $('#' + this.$el.data('subnav')); 25479 this.appened = false; 25480 this.cols = {}; 25481 this.getCols(); 25482 this.refresh(); 25483 } 25484 return _createClass(RTable, [{ 25485 key: "getCols", 25486 value: function getCols() { 25487 var self = this; 25488 this.$el.find('[data-coltitle]').each(function () { 25489 var $this = $(this); 25490 if ($this.find('.coltitle').length) { 25491 self.cols[$this.data('coltitle')] = $this.find('.coltitle').html(); 25492 } else { 25493 self.cols[$this.data('coltitle')] = $this.html(); 25494 } 25495 }); 25496 } 25497 }, { 25498 key: "refresh", 25499 value: function refresh() { 25500 if (this.isDesktop()) { 25501 this.remove(); 25502 } else { 25503 this.append(); 25504 } 25505 } 25506 }, { 25507 key: "isDesktop", 25508 value: function isDesktop() { 25509 if (this.$win.outerWidth() > 1024) { 25510 return true; 25511 } else { 25512 return false; 25513 } 25514 } 25515 }, { 25516 key: "remove", 25517 value: function remove() { 25518 this.appened = false; 25519 this.$el.find('.m-title').each(function () { 25520 $(this).removeClass('append'); 25521 $(this).find('.title').remove(); 25522 $(this).find('.content').contents().unwrap(); 25523 }); 25524 } 25525 }, { 25526 key: "append", 25527 value: function append() { 25528 this.appened = true; 25529 var self = this; 25530 this.$el.find('.m-title').each(function () { 25531 var $this = $(this); 25532 if (!$this.hasClass('append')) { 25533 var newTitle = '<div class="title">'; 25534 $this.addClass('append'); 25535 var col = $(this).data('col'); 25536 if (col && col in self.cols) { 25537 newTitle += self.cols[$(this).data('col')]; 25538 } else if (this.hasAttribute('data-title')) { 25539 newTitle += $this.data('title'); 25540 } 25541 newTitle += '</div>'; 25542 $this.wrapInner('<div class="content"></div>'); 25543 $this.prepend(newTitle); 25544 } 25545 }); 25546 } 25547 }]); 25548}(); 25549var responsiveTable = { 25550 init: function init() { 25551 var rtables = []; 25552 $('.js-responsive-table').each(function () { 25553 var table = new RTable(this); 25554 $(this).data('responsivetable', table); 25555 rtables.push(table); 25556 }); 25557 $(window).on('resize', function () { 25558 for (var i = 0; i < rtables.length; i++) { 25559 rtables[i].refresh(); 25560 } 25561 }); 25562 } 25563}; 25564module.exports = responsiveTable; 25565 25566},{}],55:[function(require,module,exports){ 25567"use strict"; 25568 25569function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 25570function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 25571function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 25572function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 25573function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 25574function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 25575var _ = require('underscore'); 25576var message = require('./message.js'); 25577var userCart = null; 25578var refreshShopCount = function refreshShopCount(cart, count) { 25579 if (count > 0) { 25580 $('.js-retailers-shop-icon').removeClass('hidden'); 25581 $('.js-retailers-count').text(count); 25582 var o = '<table class="table-small">'; 25583 for (var i = 0; i < cart.cart.items.length; i++) { 25584 o += '<tr><td>' + cart.cart.items[i].productName + '</td>'; 25585 o += '<td>' + cart.cart.items[i].factor + '</td></tr>'; 25586 } 25587 o += '</table>'; 25588 $('.js-retailers-infos').each(function () { 25589 $(this).html(o); 25590 }); 25591 } else { 25592 $('.js-retailers-shop-icon').addClass('hidden'); 25593 } 25594}; 25595var CustomQuantity = /*#__PURE__*/function () { 25596 function CustomQuantity($el) { 25597 _classCallCheck(this, CustomQuantity); 25598 this.$el = $el; 25599 this.$input = $el.find('input'); 25600 this.$btPlus = $el.find('.bt-plus'); 25601 this.$btMinus = $el.find('.bt-minus'); 25602 this.min = this.$input.attr('min') || 0; 25603 this.setValue(); 25604 this.bind(); 25605 } 25606 return _createClass(CustomQuantity, [{ 25607 key: "setValue", 25608 value: function setValue() { 25609 this.count = parseInt(this.$input.val(), 10); 25610 if (isNaN(this.count)) this.count = 0; 25611 } 25612 }, { 25613 key: "updateValue", 25614 value: function updateValue() { 25615 this.$input.val(this.count).trigger('change'); 25616 } 25617 }, { 25618 key: "bind", 25619 value: function bind() { 25620 this.$btMinus.on('click', this.minus.bind(this)); 25621 this.$btPlus.on('click', this.plus.bind(this)); 25622 } 25623 }, { 25624 key: "minus", 25625 value: function minus(e) { 25626 e.preventDefault(); 25627 this.setValue(); 25628 if (this.count > this.min) this.count--;
25629 this.updateValue(); 25630 } 25631 }, { 25632 key: "plus", 25633 value: function plus(e) { 25634 e.preventDefault(); 25635 this.setValue(); 25636 this.count++; 25637 this.updateValue(); 25638 } 25639 }]); 25640}(); 25641var Cart = /*#__PURE__*/function () { 25642 function Cart() { 25643 _classCallCheck(this, Cart); 25644 } 25645 return _createClass(Cart, [{ 25646 key: "init", 25647 value: function init() { 25648 var _this = this; 25649 var data = window.localStorage.getItem('retailers-cart'); 25650 if (data) { 25651 this.cart = JSON.parse(data); 25652 if (!('lastCheck' in this.cart) || Date.now() - this.cart.lastCheck > 259200000) { 25653 // 3 days 25654 window.localStorage.removeItem('retailers-cart'); 25655 this.cart = null; 25656 $('body').data('retailer-cart', this); 25657 $('body').trigger('retailer-cart-loaded'); 25658 } else if (Date.now() - this.cart.lastCheck > 60000) { 25659 $.ajax({ 25660 url: window.nexansConfig.retailerServiceUrl + '/status/' + this.cart.id, 25661 type: 'GET' 25662 }).done(function (data) { 25663 _this.cart.lastCheck = Date.now(); 25664 _this.cart.items = data.items; 25665 _this.save(); 25666 $('body').data('retailer-cart', _this); 25667 $('body').trigger('retailer-cart-loaded'); 25668 refreshShopCount(_this, _this.cart.items.length); 25669 }).fail(function () { 25670 _this.cart = null; 25671 $('body').data('retailer-cart', _this); 25672 $('body').trigger('retailer-cart-loaded'); 25673 }); 25674 } else { 25675 $('body').data('retailer-cart', this); 25676 $('body').trigger('retailer-cart-loaded'); 25677 refreshShopCount(this, this.cart.items.length); 25678 } 25679 } else { 25680 this.cart = null; 25681 $('body').data('retailer-cart', this); 25682 $('body').trigger('retailer-cart-loaded'); 25683 } 25684 } 25685 }, { 25686 key: "loadData", 25687 value: function loadData() { 25688 var _this2 = this; 25689 return new Promise(function (resolve, reject) { 25690 $.ajax({ 25691 url: window.nexansConfig.retailerServiceUrl + '/status/' + _this2.cart.id, 25692 type: 'GET' 25693 }).done(function (data) { 25694 if ('items' in data) { 25695 _this2.cart.lastCheck = Date.now(); 25696 _this2.cart.items = data.items; 25697 _this2.save(); 25698 refreshShopCount(_this2, _this2.cart.items.length); 25699 resolve(_this2.cart.items); 25700 } else { 25701 reject(); 25702 } 25703 }).fail(function () { 25704 reject(); 25705 }); 25706 }); 25707 } 25708 }, { 25709 key: "submitRetailers", 25710 value: function submitRetailers() { 25711 return new Promise(function (resolve, reject) { 25712 $.ajax({ 25713 url: window.nexansConfig.retailerServiceUrl + '/checkRetailers', 25714 type: 'POST', 25715 contentType: "application/json; charset=utf-8", 25716 data: '{}' 25717 }).done(function (data) { 25718 resolve(data); 25719 }).fail(function () { 25720 reject(); 25721 }); 25722 }); 25723 } 25724 }, { 25725 key: "retailerRequest", 25726 value: function retailerRequest(retailerCartId) { 25727 return new Promise(function (resolve, reject) { 25728 $.ajax({ 25729 url: window.nexansConfig.retailerServiceUrl + '/submitRetailerCart', 25730 type: 'POST', 25731 contentType: "application/json; charset=utf-8", 25732 data: JSON.stringify({ 25733 retailerCartId: retailerCartId 25734 }) 25735 }).done(function (data) { 25736 resolve(data); 25737 }).fail(function () { 25738 reject(); 25739 }); 25740 }); 25741 } 25742 }, { 25743 key: "initShop", 25744 value: function initShop() { 25745 var _this3 = this; 25746 return new Promise(function (resolve, reject) { 25747 var uniqId = Math.random().toString(36).substring(2, 10) + '-' + Date.now(); 25748 $.ajax({ 25749 url: window.nexansConfig.retailerServiceUrl + '/status/' + uniqId, 25750 type: 'GET' 25751 }).done(function (data) { 25752 _this3.cart = { 25753 id: uniqId, 25754 items: data.items, 25755 lastCheck: Date.now() 25756 }; 25757 _this3.save(); 25758 refreshShopCount(_this3, data.items.length); 25759 resolve(); 25760 }); 25761 }); 25762 } 25763 }, { 25764 key: "save", 25765 value: function save() { 25766 window.localStorage.setItem('retailers-cart', JSON.stringify(this.cart)); 25767 } 25768 }, { 25769 key: "updateItem", 25770 value: function updateItem(id, quantity, cb) { 25771 var _this4 = this;
25772 var update = function update() { 25773 $.ajax({ 25774 url: window.nexansConfig.retailerServiceUrl + '/updateItem', 25775 type: 'POST', 25776 data: JSON.stringify({ 25777 productId: id, 25778 factor: parseInt(quantity, 10) 25779 }), 25780 contentType: "application/json; charset=utf-8" 25781 }).done(function (data) { 25782 var ind = _this4.cart.items.findIndex(function (el) { 25783 return el.productId === id; 25784 }); 25785 if (ind === -1) { 25786 if (quantity > 0) _this4.cart.items.push(data.cartItem); 25787 } else { 25788 if (quantity > 0) { 25789 _this4.cart.items[ind] = data.cartItem; 25790 } else { 25791 _this4.cart.items.splice(ind, 1); 25792 } 25793 } 25794 refreshShopCount(_this4, _this4.cart.items.length); 25795 _this4.save(); 25796 if (cb) { 25797 cb(data); 25798 } 25799 }); 25800 }; 25801 if (this.cart === null) { 25802 this.initShop().then(function (data) { 25803 update(); 25804 }); 25805 } else { 25806 update(); 25807 } 25808 } 25809 }, { 25810 key: "get_", 25811 value: function get_() { 25812 return _; 25813 } 25814 }, { 25815 key: "setTemplate", 25816 value: function setTemplate(id) { 25817 this.template = _.template($('#' + id).html()); 25818 } 25819 }, { 25820 key: "setCustomQuantity", 25821 value: function setCustomQuantity(element) { 25822 return new CustomQuantity(element); 25823 } 25824 }, { 25825 key: "addMessage", 25826 value: function addMessage(msg, type, delay) { 25827 message.add(msg, type, delay); 25828 } 25829 }]); 25830}(); 25831; 25832var RetailersShop = /*#__PURE__*/function () { 25833 function RetailersShop($el) { 25834 var _this5 = this; 25835 _classCallCheck(this, RetailersShop); 25836 this.$el = $el; 25837 this.$submit = this.$el.find('.js-retailer-order'); 25838 this.id = parseInt(this.$submit.data('id'), 10); 25839 this.$submit.on('click', function (e) { 25840 e.preventDefault(); 25841 var qtty = _this5.$el.find('.js-quantity').val(); 25842 userCart.updateItem(_this5.id, qtty, function (data) { 25843 userCart.addMessage(data.message, 'info', 3000); 25844 _this5.setUpdated(); 25845 }); 25846 }); 25847 if (userCart) { 25848 var ind = userCart.cart.items.findIndex(function (it) { 25849 return it.productId === _this5.id; 25850 }); 25851 if (ind !== -1) { 25852 this.update(userCart.cart.items[ind].factor); 25853 } 25854 } 25855 } 25856 return _createClass(RetailersShop, [{ 25857 key: "update", 25858 value: function update(qtty) { 25859 this.$el.find('.js-quantity').val(qtty); 25860 this.setUpdated(); 25861 } 25862 }, { 25863 key: "setUpdated", 25864 value: function setUpdated() { 25865 this.$el.find('.button__text.add').hide(); 25866 this.$el.find('.button__text.update').show(); 25867 } 25868 }]); 25869}(); 25870var retailers = { 25871 init: function init() { 25872 if ($('.js-retailers-shop-icon').length > 0) { 25873 $('body').on('retailer-cart-loaded', function () { 25874 retailers.addToCartInit(); 25875 }); 25876 $(document).on('uiLoaded', function () { 25877 userCart = new Cart(); 25878 userCart.init(); 25879 }); 25880 } 25881 $('.form-retailers-shop .custom-quantity').each(function () { 25882 new CustomQuantity($(this)); 25883 }); 25884 }, 25885 addToCartInit: function addToCartInit(asyncForms) { 25886 $('.form-retailers-shop').each(function () { 25887 new RetailersShop($(this)); 25888 }); 25889 } 25890}; 25891module.exports = retailers; 25892 25893},{"./message.js":35,"underscore":8}],56:[function(require,module,exports){ 25894"use strict"; 25895 25896function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 25897function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 25898function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 25899function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 25900function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 25901function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 25902var JSTable = /*#__PURE__*/function () { 25903 function JSTable(el) { 25904 _classCallCheck(this, JSTable); 25905 this.el = el; 25906 this.ui = { 25907 $el: $(el) 25908 }; 25909 this.setWidths(); 25910 this.setHeaders(); 25911 } 25912 return _createClass(JSTable, [{ 25913 key: "setWidths", 25914 value: function setWidths() { 25915 this.ui.$el.find('table:not(.table-footnote)').each(function () { 25916 var tableWidth = $(this).prop('style')['width']; 25917 if (tableWidth) $(this).next('.table-footnote').css('width', tableWidth); 25918 }); 25919 } 25920 }, { 25921 key: "setHeaders", 25922 value: function setHeaders() { 25923 this.ui.$el.find('table').each(function () { 25924 var headers = $(this).find('thead th'); 25925 // add a <div> to all table body cells with the corresponding header text 25926 if (headers.length > 0) { 25927 $(this).find('tbody > tr').each(function () { 25928 $(this).find('th, td').each(function (index) { 25929 var $cell = $(this); 25930 if (!$cell.find(">:first-child").is('div')) { 25931 if (headers.length >= index) { 25932 $cell.prepend('<div>' + headers.eq(index).html() + '</div>'); 25933 } 25934 } 25935 }); 25936 }); 25937 } 25938 }); 25939 } 25940 }]); 25941}(); 25942var rteArray = {
25943 init: function init() { 25944 $('div.rte-array').each(function () { 25945 new JSTable(this); 25946 }); 25947 } 25948}; 25949module.exports = rteArray; 25950 25951},{}],57:[function(require,module,exports){ 25952"use strict"; 25953 25954var scrollAnchorGenerate = { 25955 init: function init() { 25956 $('.js-scroll-anchor-generate').each(function () { 25957 var $this = $(this); 25958 var $list = $this.find('.bloc--anchors-list'); 25959 $('.js-anchor').each(function () { 25960 var li = $('<li><a href="#" data-anchor="' + this.id + '" class="js-scroll-to-trigger link link--grey bloc--anchors__item"></a></li>'); 25961 li.find('a').html($(this).html()); 25962 $list.append(li); 25963 }); 25964 }); 25965 } 25966}; 25967module.exports = scrollAnchorGenerate; 25968 25969},{}],58:[function(require,module,exports){ 25970"use strict"; 25971 25972var scrollToAnchor = { 25973 ui: {}, 25974 init: function init() { 25975 this.bindUI(); 25976 this.bindEvents(); 25977 this.scrollTo(); 25978 }, 25979 bindUI: function bindUI() { 25980 this.ui.$win = $(window); 25981 this.ui.$body = $('body'); 25982 this.ui.$document = $(document); 25983 this.ui.$links = $('.js-scroll-to-trigger'); 25984 this.ui.$select = $('.js-scroll-to-select'); 25985 this.ui.$sticky = $('.js-sticky'); 25986 this.isGenerated = $('.js-scroll-to.js-scroll-anchor-generate').length > 0; 25987 }, 25988 bindEvents: function bindEvents() { 25989 this.ui.$win.on('scroll', $.proxy(this.handleStickyAnchors, this)); 25990 }, 25991 scrollTo: function scrollTo() { 25992 var self = this; 25993 this.ui.$links.on('click', function (e) { 25994 e.preventDefault(); 25995 var $self = $(this), 25996 data = $(this).data('anchor'), 25997 $target = $('body').find('#' + data), 25998 pos = Math.max($target.offset().top, 0); 25999 if ('stickySize' in window.nexansConfig) { 26000 pos = pos - window.nexansConfig.stickySize; 26001 } 26002 $('body, html').animate({ 26003 scrollTop: pos 26004 }, 'slow'); 26005 }); 26006 this.ui.$select.on('change', function () { 26007 var $self = $(this), 26008 value = $self.val(), 26009 $target = $('body').find('#' + value), 26010 pos = Math.max($target.offset().top, 0); 26011 $('body, html').animate({ 26012 scrollTop: pos 26013 }, 'slow'); 26014 }); 26015 }, 26016 handleStickyAnchors: function handleStickyAnchors(e) { 26017 if (this.ui.$sticky.length) { 26018 var offset = 'stickySize' in window.nexansConfig ? window.nexansConfig.stickySize : 0; 26019 var scrollPos = this.ui.$document.scrollTop() + offset + 1; 26020 var self = this; 26021 if (this.isGenerated) { 26022 var i = 0; 26023 var anchors = []; 26024 $('.js-anchor').each(function () { 26025 var top = $(this).offset().top; 26026 anchors.push({ 26027 top: top 26028 }); 26029 if (i > 0) anchors[i - 1].bottom = top; 26030 i++; 26031 }); 26032 i = 0; 26033 $('.js-scroll-to-trigger').each(function () { 26034 var $currentAnchor = $(this); 26035 var $refElement = $('#' + $currentAnchor.attr('data-anchor')); 26036 if ($refElement.hasClass('js-anchor')) ; 26037 if (anchors[i].top <= scrollPos && (!('bottom' in anchors[i]) || anchors[i].bottom > scrollPos)) { 26038 $('.is-sticky-current').removeClass('is-sticky-current'); 26039 $currentAnchor.addClass('is-sticky-current'); 26040 } else { 26041 $currentAnchor.removeClass('is-sticky-current'); 26042 } 26043 i++; 26044 }); 26045 } else { 26046 $('.js-scroll-to-trigger').each(function () { 26047 var $currentAnchor = $(this); 26048 var $refElement = $('#' + $currentAnchor.attr('data-anchor')); 26049 if ($refElement.offset().top <= scrollPos && $refElement.offset().top + $refElement.height() > scrollPos) { 26050 $('.is-sticky-current').removeClass('is-sticky-current'); 26051 $currentAnchor.addClass('is-sticky-current'); 26052 } else { 26053 $currentAnchor.removeClass('is-sticky-current'); 26054 } 26055 }); 26056 } 26057 } 26058 } 26059}; 26060module.exports = scrollToAnchor; 26061 26062},{}],59:[function(require,module,exports){ 26063"use strict"; 26064 26065var searchFilters = { 26066 ui: {}, 26067 init: function init() { 26068 this.bindUI(); 26069 this.bindEvents(); 26070 }, 26071 bindUI: function bindUI() { 26072 this.ui.$document = $(document); 26073 this.ui.$close = $('.js-close-filters'); 26074 this.ui.$container = $('.js-result-filters-container'); 26075 this.ui.$filterItem = $('.js-result-filters'); 26076 this.ui.$sub = $('.js-result-filters-sub'); 26077 this.ui.$select = $('.js-result-filter-select'); 26078 this.ui.$subselect = $('.js-result-filter-subselect'); 26079 this.ui.$tagsList = $('.js-search-tags-list'); 26080 this.ui.$tags = $('.js-search-tags'); 26081 }, 26082 bindEvents: function bindEvents() { 26083 var _this = this; 26084 this.ui.$filterItem.on('click', function (e) {
26085 return _this.showFilters(e); 26086 }); 26087 this.ui.$document.on('click', function (e) { 26088 return _this.closeFilters(e); 26089 }); 26090 this.ui.$close.on('click', function (e) { 26091 return _this.onClickClose(e); 26092 }); 26093 this.ui.$select.on('change', function (e) { 26094 return _this.showSubSelect(e); 26095 }); 26096 this.ui.$tags.on('click', function (e) { 26097 return _this.deleteTags(e); 26098 }); 26099 }, 26100 showFilters: function showFilters(e) { 26101 e.preventDefault(); 26102 var $el = $(e.currentTarget), 26103 data = $el.data('filter'); 26104 this.ui.$filterItem.removeClass('active'); 26105 $el.addClass('active'); 26106 this.ui.$sub.removeClass('active'); 26107 $('.js-result-filters-sub[data-filter="' + data + '"]').addClass('active'); 26108 }, 26109 onClickClose: function onClickClose(e) { 26110 e.preventDefault(); 26111 this.ui.$sub.removeClass('active'); 26112 }, 26113 closeFilters: function closeFilters(e) { 26114 if ($(e.target).closest('.js-result-filters-container').length === 0) { 26115 this.ui.$sub.removeClass('active'); 26116 } 26117 }, 26118 showSubSelect: function showSubSelect(e) { 26119 var $el = $(e.currentTarget), 26120 val = $el.val(); 26121 this.ui.$select.removeClass('active'); 26122 $el.addClass('active'); 26123 if (val === 'subnav') { 26124 var $selected = this.ui.$select.find('option[value="' + val + '"]'), 26125 ref = $selected.data('ref'), 26126 $target = $('#' + ref); 26127 if ($target) { 26128 $target.addClass('active'); 26129 } else { 26130 this.ui.$subselect.removeClass('active'); 26131 } 26132 } 26133 }, 26134 deleteTags: function deleteTags(e) { 26135 e.preventDefault(); 26136 var $el = $(e.currentTarget), 26137 $tags = this.ui.$tagsList.find('.js-search-tags'); 26138 if ($tags.length <= 1) { 26139 $el.remove(); 26140 this.ui.$tagsList.addClass('inactive'); 26141 } else { 26142 $el.remove(); 26143 } 26144 } 26145}; 26146module.exports = searchFilters; 26147 26148},{}],60:[function(require,module,exports){ 26149"use strict"; 26150 26151var sharePrice = { 26152 ui: {}, 26153 init: function init() { 26154 if ('nexansConfig' in window && 'sharePriceServiceUrl' in window.nexansConfig) this.updateSharePrice(); 26155 this.bindUI(); 26156 if (this.ui.$iframe.length > 0) { 26157 this.ui.$iframe.on('load', function () { 26158 this.checkSharePriceHeight(); 26159 $(window).on('resize', this.checkSharePriceHeight.bind(this)); 26160 }.bind(this)); 26161 setTimeout(this.checkSharePriceReload.bind(this), 120000); 26162 } 26163 }, 26164 bindUI: function bindUI() { 26165 this.ui.$iframe = $('iframe#shareprice-iframe'); 26166 this.ui.$input = $('input#shareprice-auto-reload'); 26167 this.ui.$spData = $('div.share-price > a > span, div.navigation__infos > p.share-price, div.navigation__infos > a > p.share-price'); 26168 this.ui.$spMeta = $('div#share-price-highlight > div.push-action__meta'); 26169 this.ui.$spKey = $('div#share-price-highlight > div.push-action__key'); 26170 }, 26171 checkSharePriceReload: function checkSharePriceReload() { 26172 if (this.ui.$input.is(':checked')) { 26173 this.ui.$iframe[0].src = this.ui.$iframe[0].src; 26174 } 26175 setTimeout(this.checkSharePriceReload.bind(this), 120000); 26176 }, 26177 checkSharePriceHeight: function checkSharePriceHeight() { 26178 if (this.ui.$iframe.width() < 560) { 26179 this.ui.$iframe.height('1320px'); 26180 } else { 26181 this.ui.$iframe.height('1080px'); 26182 } 26183 }, 26184 updateSharePrice: function updateSharePrice() { 26185 var self = this; 26186 $.getJSON(window.nexansConfig.sharePriceServiceUrl, function (jsonData) { 26187 if (jsonData) { 26188 self.ui.$spMeta.html(jsonData.place + ', ' + jsonData.date + ' ' + jsonData.time); 26189 self.ui.$spKey.html(jsonData.value + '<sup class="push-action__sup">' + jsonData.currency + '</sup>'); 26190 self.ui.$spData.html(jsonData.value + jsonData.currency + ' - ' + jsonData.place + ', ' + jsonData.date + ' ' + jsonData.time); 26191 } else { 26192 self.ui.$spMeta.html('Share price<br/>temporary unavailable'); 26193 self.ui.$spKey.html(''); 26194 self.ui.$spData.text('temporary unavailable'); 26195 } 26196 }).fail(function () { 26197 self.ui.$spMeta.html('Share price<br/>temporary unavailable'); 26198 self.ui.$spKey.html(''); 26199 self.ui.$spData.text('temporary unavailable'); 26200 }); 26201 window.setTimeout(this.updateSharePrice.bind(this), 120000); 26202 } 26203}; 26204module.exports = sharePrice; 26205 26206},{}],61:[function(require,module,exports){ 26207"use strict"; 26208 26209var showAccount = { 26210 ui: {},
26211 init: function init() { 26212 this.bindUI(); 26213 this.bindEvents(); 26214 this.ui.$secondary.hide(); 26215 this.onChangeMain(); 26216 }, 26217 bindUI: function bindUI() { 26218 this.ui.$document = $(document); 26219 this.ui.$trigger = $('.js-account-trigger'); 26220 this.ui.$account = $('.js-account'); 26221 this.ui.$main = $('.account__main'); 26222 this.ui.$secondary = $('.account__secondary'); 26223 this.ui.$mobileHeader = $('header.mobile-header'); 26224 this.ui.$desktopHeader = $('header.header'); 26225 }, 26226 bindEvents: function bindEvents() { 26227 var _this = this; 26228 this.ui.$trigger.on('click', function (e) { 26229 return _this.onClick(e); 26230 }); 26231 this.ui.$main.on('change', function (e) { 26232 return _this.onChangeMain(e); 26233 }); 26234 this.ui.$account.on('click', function (e) { 26235 return e.stopPropagation(); 26236 }); 26237 $(document).on('click', function (e) { 26238 return _this.close(); 26239 }); 26240 }, 26241 close: function close() { 26242 this.ui.$account.removeClass('is-open'); 26243 this.ui.$trigger.removeClass('active'); 26244 }, 26245 onClick: function onClick(e) { 26246 e.preventDefault(); 26247 e.stopPropagation(); 26248 if (this.ui.$mobileHeader.is(':visible')) { 26249 this.ui.$mobileHeader.append(this.ui.$account); 26250 } else { 26251 this.ui.$desktopHeader.append(this.ui.$account); 26252 } 26253 var $el = $(e.currentTarget); 26254 $el.toggleClass('active'); 26255 this.ui.$account.toggleClass('is-open'); 26256 }, 26257 onChangeMain: function onChangeMain() { 26258 this.ui.$secondary.hide(); 26259 $('#' + this.ui.$main.attr('id') + '-' + this.ui.$main.val()).show(); 26260 } 26261}; 26262module.exports = showAccount; 26263 26264},{}],62:[function(require,module,exports){ 26265"use strict"; 26266 26267var showSearch = { 26268 ui: {}, 26269 init: function init() { 26270 this.bindUI(); 26271 this.bindEvents(); 26272 }, 26273 bindUI: function bindUI() { 26274 this.ui.$document = $(document); 26275 this.ui.$reset = $('.js-search-reset'); 26276 this.ui.$trigger = $('.js-search-trigger'); 26277 this.ui.$close = $('.js-search-close'); 26278 this.ui.$search = $('.js-search'); 26279 this.ui.$form = $('.js-search-form'); 26280 this.ui.$input = $('.js-search-input'); 26281 this.ui.$submit = $('.js-search-submit'); 26282 }, 26283 bindEvents: function bindEvents() { 26284 var _this = this; 26285 this.ui.$trigger.on('click', function (e) { 26286 return _this.onClick(e); 26287 }); 26288 this.ui.$close.on('click', function (e) { 26289 return _this.onClick(e); 26290 }); 26291 this.ui.$reset.on('click', function (e) { 26292 return _this.onReset(e); 26293 }); 26294 this.ui.$input.on('keyup', function (e) { 26295 return _this.onChange(e); 26296 }); 26297 }, 26298 onClick: function onClick(e) { 26299 e.preventDefault(); 26300 var $el = this.ui.$trigger; 26301 $el.toggleClass('active'); 26302 this.ui.$search.toggleClass('is-open'); 26303 if ($el.hasClass('active')) { 26304 this.ui.$input.focus(); 26305 } 26306 }, 26307 onReset: function onReset(e) { 26308 e.preventDefault(); 26309 this.ui.$input.val(''); 26310 this.ui.$submit.prop('disabled', true); 26311 }, 26312 onChange: function onChange(e) { 26313 e.preventDefault(); 26314 var $el = $(e.currentTarget), 26315 val = $el.val(); 26316 if (val.length > 1) { 26317 this.ui.$submit.prop('disabled', false); 26318 } else { 26319 this.ui.$submit.prop('disabled', true); 26320 } 26321 } 26322}; 26323module.exports = showSearch; 26324 26325},{}],63:[function(require,module,exports){ 26326"use strict"; 26327 26328function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 26329function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 26330function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 26331function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 26332function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 26333function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 26334var ShowSubnav = /*#__PURE__*/function () { 26335 function ShowSubnav(el) { 26336 _classCallCheck(this, ShowSubnav); 26337 this.el = el; 26338 this.$el = $(el); 26339 this.$target = $('#' + this.$el.data('subnav')); 26340 this.bind(); 26341 } 26342 return _createClass(ShowSubnav, [{ 26343 key: "bind", 26344 value: function bind() { 26345 var self = this; 26346 this.$el.click(function (e) { 26347 e.preventDefault(); 26348 self.$target.toggleClass('is-opened'); 26349 }); 26350 this.$target.find('.js-nav-close').click(function (e) { 26351 e.preventDefault(); 26352 self.$target.removeClass('is-opened'); 26353 }); 26354 } 26355 }]); 26356}(); 26357var showSubnav = {
26358 init: function init() { 26359 $('.js-show-subnav').each(function () { 26360 new ShowSubnav(this); 26361 }); 26362 } 26363}; 26364module.exports = showSubnav; 26365 26366},{}],64:[function(require,module,exports){ 26367"use strict"; 26368 26369function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 26370function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 26371function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 26372function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 26373function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 26374function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 26375function isMobile() { 26376 return $('.mobile-header:visible').length > 0; 26377} 26378var Sticky = /*#__PURE__*/function () { 26379 function Sticky(el) { 26380 _classCallCheck(this, Sticky); 26381 this.ui = {}; 26382 this.ui.$wrapper = $(el); 26383 this.ui.$window = $(window); 26384 this.ui.$document = $(document); 26385 this.name = this.ui.$wrapper.data('name'); 26386 this.initSticky(); 26387 } 26388 return _createClass(Sticky, [{ 26389 key: "initSticky", 26390 value: function initSticky() { 26391 this.ui.$clone = $('<div class="js-sticky-clone"></div>'); 26392 this.ui.$clone.insertBefore(this.ui.$wrapper); 26393 if (this.name) { 26394 this.ui.$clone.addClass(this.name); 26395 } 26396 } 26397 }, { 26398 key: "handlePosition", 26399 value: function handlePosition(offset) { 26400 var offsetTop = this.ui.$clone.offset().top - offset; 26401 if (this.ui.$document.scrollTop() >= offsetTop) { 26402 var h = this.ui.$wrapper.outerHeight(true); 26403 this.ui.$clone.height(h); 26404 this.ui.$wrapper.addClass('is-sticky').css('top', offset); 26405 window.nexansConfig.stickySize += this.ui.$wrapper.outerHeight(false); 26406 return this.ui.$wrapper.outerHeight(); 26407 } else { 26408 this.ui.$wrapper.removeClass('is-sticky').css('top', 0); 26409 this.ui.$clone.height(0); 26410 return 0; 26411 } 26412 } 26413 }]); 26414}(); 26415; 26416var sticky = { 26417 init: function init() { 26418 var stickies = []; 26419 var $mobileHeader = $('.mobile-header'); 26420 $('.js-sticky').each(function () { 26421 stickies.push(new Sticky(this)); 26422 }); 26423 var checkSticky = function checkSticky() { 26424 var top = 0; 26425 window.nexansConfig.stickySize = 0; 26426 var isMobileLayout = isMobile(); 26427 if (isMobileLayout) { 26428 top = $mobileHeader.outerHeight(); 26429 window.nexansConfig.stickySize = top; 26430 } 26431 for (var i = 0; i < stickies.length; i++) { 26432 if (!isMobileLayout || stickies[i].name !== 'sticky-main-menu') { 26433 top += stickies[i].handlePosition(top); 26434 } 26435 } 26436 }; 26437 $(window).on('scroll', checkSticky); 26438 checkSticky(); 26439 } 26440}; 26441module.exports = sticky; 26442 26443},{}],65:[function(require,module,exports){ 26444"use strict"; 26445 26446function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 26447function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 26448function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 26449function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 26450function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 26451function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 26452var Storage = /*#__PURE__*/function () {
26453 function Storage(key) { 26454 _classCallCheck(this, Storage); 26455 this.key = key; 26456 this.data = { 26457 familyIds: [], 26458 productIds: [] 26459 }; 26460 this.count = 0; 26461 this.notStored = false; 26462 this.load(); 26463 } 26464 return _createClass(Storage, [{ 26465 key: "load", 26466 value: function load() { 26467 var data = JSON.parse(window.sessionStorage.getItem(this.key)); 26468 if (!data) this.notStored = true; 26469 this.data = data || this.data; 26470 this.count = this.data.familyIds.length + this.data.productIds.length; 26471 return this.data; 26472 } 26473 }, { 26474 key: "delete", 26475 value: function _delete(familyId, productId) { 26476 if (productId) { 26477 var index = this.data.productIds.indexOf(productId); 26478 if (index > -1) this.data.productIds.splice(index, 1); 26479 } else { 26480 var _index = this.data.familyIds.indexOf(familyId); 26481 if (_index > -1) this.data.familyIds.splice(_index, 1); 26482 } 26483 this.persist(); 26484 } 26485 }, { 26486 key: "add", 26487 value: function add(familyId, productId) { 26488 if (productId) { 26489 this.data.productIds.push(productId); 26490 } else { 26491 this.data.familyIds.push(familyId); 26492 } 26493 ; 26494 this.persist(); 26495 } 26496 }, { 26497 key: "exists", 26498 value: function exists(familyId, productId) { 26499 if (productId) { 26500 return this.data.productIds.indexOf(productId) !== -1; 26501 } 26502 return this.data.familyIds.indexOf(familyId) !== -1; 26503 } 26504 }, { 26505 key: "persist", 26506 value: function persist() { 26507 window.sessionStorage.setItem(this.key, JSON.stringify(this.data)); 26508 this.count = this.data.familyIds.length + this.data.productIds.length; 26509 } 26510 }, { 26511 key: "refresh", 26512 value: function refresh(data) { 26513 this.data = { 26514 familyIds: data.familyIds || [], 26515 productIds: data.productIds || [] 26516 }; 26517 if ('productIds' in data) { 26518 this.data.productIds = data.productIds; 26519 } 26520 this.persist(); 26521 } 26522 }]); 26523}(); 26524var storage = { 26525 comparator: new Storage('nexans-comparator-families'), 26526 favorites: new Storage('nexans-favourites-list') 26527}; 26528module.exports = storage; 26529 26530},{}],66:[function(require,module,exports){ 26531"use strict"; 26532 26533var subscribeNewsletter = { 26534 ui: {}, 26535 newsJSON: {}, 26536 tags: [], 26537 init: function init() { 26538 this.bindUI(); 26539 this.bindEvents(); 26540 }, 26541 bindUI: function bindUI() { 26542 this.ui.$win = $(window); 26543 this.ui.$body = $('body'); 26544 this.ui.$selectAll = $('.js-select-all'); 26545 this.ui.$select = $('.js-select'); 26546 this.ui.$tagsWrapper = $('.js-tags-wrapper'); 26547 this.ui.$btnNext = $('.js-nl-next'); 26548 this.ui.$btnPrevious = $('.js-nl-previous'); 26549 this.ui.$email = $('.js-nl-email'); 26550 this.ui.$validate = $('.js-nl-validate'); 26551 }, 26552 bindEvents: function bindEvents() { 26553 this.ui.$selectAll.on('click', $.proxy(this.selectAll, this)); 26554 this.ui.$select.on('change', $.proxy(this.select, this)); 26555 this.ui.$btnNext.on('click', $.proxy(this.nextPage, this)); 26556 this.ui.$btnPrevious.on('click', $.proxy(this.previousPage, this)); 26557 this.ui.$validate.on('click', $.proxy(this.lastPage, this)); 26558 this.ui.$email.on('keyup', $.proxy(this.checkmail, this)); 26559 }, 26560 selectAll: function selectAll(e) { 26561 e.preventDefault(); 26562 var self = this; 26563 var arrayItems = []; 26564 26565 // Cibling parent. 26566 var $parent = $(e.currentTarget).closest('.js-select-all-wrapper'); 26567 26568 // Disable select all. 26569 $(e.currentTarget).addClass('is-disable'); 26570 26571 // Enable btn next. 26572 this.ui.$btnNext.removeClass('is-disable'); 26573 26574 // Check all checkbox of this part. 26575 $parent.find(':checkbox').prop("checked", true); 26576 $.each($parent.find(':checkbox'), function () { 26577 var id = $(this).attr('id'); 26578 26579 // add tags. 26580 self.appendTag(id); 26581 26582 // add item on array tags. 26583 self.tags.push(parseInt(id)); 26584 }); 26585 }, 26586 select: function select(e) { 26587 var self = this; 26588 var $parent = $(e.currentTarget).closest('.js-select-all-wrapper'); 26589 var $btn = $parent.find('.js-select-all'); 26590 var id = $(e.currentTarget).find(':checkbox').attr('id'); 26591 26592 // check class disable or not. 26593 if ($btn.hasClass('is-disable')) { 26594 $btn.removeClass('is-disable'); 26595 } 26596 26597 // Tags list 26598 if (self.tags.includes(parseInt(id))) { 26599 // remove item from array tags. 26600 this.removeTag(id); 26601 } else { 26602 // add item on array tags. 26603 self.tags.push(parseInt(id)); 26604 this.appendTag(id); 26605 } 26606 26607 // Show or hide btn next step. 26608 if (self.tags.length > 0) { 26609 this.ui.$btnNext.removeClass('is-disable'); 26610 } else { 26611 this.ui.$btnNext.addClass('is-disable'); 26612 } 26613 }, 26614 appendTag: function appendTag(id) { 26615 // Get name by id. 26616 var $el = $('#' + id); 26617 var name = $($el).next().children('.js-checkbox-name').html(); 26618 26619 // Construct item. 26620 var html = '<a href="" class="panel-newsletter__tag js-tag-remove tag" data-nlid="' + id + '">
26620 ' + name + '<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-close" viewBox="0 0 20 20">' + '<path fill="#DB3331" fill-rule="evenodd" d="M10,8.58578644 L4.34314575,2.92893219 L2.92893219,4.34314575 L8.58578644,10 L2.92893219,15.6568542 L4.34314575,17.0710678 L10,11.4142136 L15.6568542,17.0710678 L17.0710678,15.6568542 L11.4142136,10 L17.0710678,4.34314575 L15.6568542,2.92893219 L10,8.58578644 Z"/>' + '</svg> </a>'; 26621 $('.js-tags-wrapper').append(html); 26622 26623 // Bind events. 26624 this.ui.$removeTag = $('.js-tag-remove'); 26625 this.ui.$removeTag.on('click', $.proxy(this.removeTagByItem, this)); 26626 }, 26627 removeTag: function removeTag(id) { 26628 var self = this; 26629 26630 // find item by data attr. 26631 var $item = $('*[data-nlid="' + id + '"]'); 26632 26633 // remove item. 26634 $item.remove(); 26635 }, 26636 removeTagByItem: function removeTagByItem(e) { 26637 e.preventDefault(); 26638 var self = this; 26639 var id = $(e.currentTarget).data('nlid'); 26640 var $item = $('*[data-nlid="' + id + '"]'); 26641 26642 // remove check. 26643 $('#' + id).prop('checked', false); 26644 var index = self.tags.indexOf(id); 26645 if (index !== -1) self.tags.splice(index, 1); 26646 26647 // remove item. 26648 $item.remove(); 26649 }, 26650 nextPage: function nextPage(e) { 26651 e.preventDefault(); 26652 $('.js-newsletter-1').hide(); 26653 $('.js-newsletter-2').show(); 26654 }, 26655 previousPage: function previousPage(e) { 26656 e.preventDefault(); 26657 $('.js-newsletter-1').show(); 26658 $('.js-newsletter-2').hide(); 26659 }, 26660 lastPage: function lastPage(e) { 26661 e.preventDefault(); 26662 var self = this; 26663 var email = this.ui.$email.val(), 26664 itemsArray = self.tags; 26665 $.ajax({ 26666 url: 'TODO UPDATE URL', 26667 type: 'POST', 26668 data: 'email=' + email + '&items=' + itemsArray, 26669 dataType: 'html', 26670 success: function success(html, statut) { 26671 $('.js-newsletter-success').show(); 26672 console.log('success'); 26673 }, 26674 error: function error(result, statut, erreur) { 26675 $('.js-newsletter-error').show(); 26676 console.log('erreur'); 26677 } 26678 }); 26679 $('.js-newsletter-1').hide(); 26680 $('.js-newsletter-2').hide(); 26681 $('.js-nl-header').hide(); 26682 $('.js-newsletter-3').show(); 26683 }, 26684 checkmail: function checkmail() { 26685 var self = this; 26686 var val = $('.js-nl-email').val(); 26687 var filter = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/; 26688 if (!filter.test(val)) { 26689 $('.js-nl-validate').addClass('is-disable'); 26690 } else { 26691 $('.js-nl-validate').removeClass('is-disable'); 26692 } 26693 console.log(self.tags); 26694 } 26695}; 26696module.exports = subscribeNewsletter; 26697 26698},{}],67:[function(require,module,exports){ 26699"use strict"; 26700 26701function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 26702function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 26703function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 26704function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 26705function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 26706function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 26707var TableSelect = /*#__PURE__*/function () { 26708 function TableSelect(el) { 26709 _classCallCheck(this, TableSelect); 26710 this.$el = $(el); 26711 this.data = this.$el.data(); 26712 this.paginator = this.$el.data('paginator'); 26713 this.bindUi(); 26714 if (this.paginator) { 26715 this.itemsByPage = this.ui.$selectNbItems.length ? parseInt(this.ui.$selectNbItems.val(), 10) : 10; 26716 this.activePage = 0; 26717 this.pages = 0; 26718 } 26719 if (this.ui.$form.length > 0) { 26720 this.baseAction = this.ui.$form.attr('action'); 26721 } 26722 this.sortActive = null; 26723 this.bind(); 26724 this.initSort(); 26725 this.refreshItems(); 26726 this.selectChange(); 26727 } 26728 return _createClass(TableSelect, [{ 26729 key: "bindUi", 26730 value: function bindUi() { 26731 this.ui = {}; 26732 this.ui.sortBtns = []; 26733 this.ui.$form = this.$el.parents('form'); 26734 this.ui.$sortSelect = this.$el.find('.tableselect-sort-select'); 26735 this.ui.$inputSelectAll = this.$el.find('.tableselect-selectall'); 26736 this.ui.$count = this.$el.find('.tableselect-count'); 26737 this.ui.$countTotal = this.$el.find('.tableselect-count-total'); 26738 this.ui.$actions = this.$el.find('.tableselect-action'); 26739 if (this.paginator) { 26740 this.ui.$pagerWrapper = this.$el.find('.tableselect-pager'); 26741 this.ui.$pager = this.ui.$pagerWrapper.find('.pager__list'); 26742 this.ui.$selectNbItems = 'itemsbypage' in this.data ? $(this.data.itemsbypage) : this.$el.find('.tableselect-itemsbypage'); 26743 } 26744 this.bindRows(); 26745 } 26746 }, { 26747 key: "bindRows", 26748 value: function bindRows(noEvent) {
26749 this.ui.$inputs = this.$el.find('.tableselect-select'); 26750 if (!noEvent) this.ui.$inputs.on('change', this.selectChange.bind(this)); 26751 } 26752 }, { 26753 key: "bind", 26754 value: function bind() { 26755 if (this.paginator) { 26756 this.ui.$pagerWrapper.on('click', 'a', this.pagerNav.bind(this)); 26757 if (this.ui.$selectNbItems.length) this.ui.$selectNbItems.on('change', function () { 26758 this.itemsByPage = parseInt(this.ui.$selectNbItems.val(), 10); 26759 this.activePage = 0; 26760 this.refreshItems(); 26761 }.bind(this)); 26762 } 26763 this.ui.$inputSelectAll.on('change', this.selectAllChange.bind(this)); 26764 var self = this; 26765 this.ui.$actions.each(function () { 26766 var $action = $(this); 26767 if (this.hasAttribute('data-url')) { 26768 $action.on('click', function (e) { 26769 self.ui.$form.attr('action', $action.data('url')); 26770 }); 26771 } else { 26772 $action.on('click', function (e) { 26773 self.ui.$form.attr('action', self.baseAction); 26774 }); 26775 } 26776 }); 26777 } 26778 }, { 26779 key: "initSort", 26780 value: function initSort() { 26781 var self = this; 26782 this.$el.find('.tableselect-sort').each(function () { 26783 var $this = $(this); 26784 var $bt = $('<button type="button"></button>'); 26785 var sortBy = $this.data('sortby'); 26786 var sortType = $this.data('sorttype') || 'string'; 26787 var defaultDir = $this.data('direction'); 26788 $bt.on('click', function () { 26789 var $thisbt = $(this); 26790 var direction = $thisbt.data('direction'); 26791 if (!direction && defaultDir) { 26792 direction = defaultDir; 26793 if (direction == 'desc') { 26794 $thisbt.addClass('desc'); 26795 } 26796 } else if (!$thisbt.hasClass('is-active') && direction) {} else if (!direction || direction == 'desc' || !$thisbt.hasClass('is-active')) { 26797 direction = 'asc'; 26798 $thisbt.removeClass('desc'); 26799 } else { 26800 direction = 'desc'; 26801 $thisbt.addClass('desc'); 26802 } 26803 $thisbt.data('direction', direction); 26804 self.$el.find('.tableselect-sort button').removeClass('is-active'); 26805 self.sort(parseInt($this.data('col'), 10) - 1, sortBy, direction, sortType); 26806 $thisbt.addClass('is-active'); 26807 if (self.ui.$sortSelect.length) { 26808 self.ui.$sortSelect.find('option:first-child').prop('selected', true); 26809 } 26810 }); 26811 self.ui.sortBtns.push($bt); 26812 if ($this.hasClass('is-active')) { 26813 $this.removeClass('is-active'); 26814 $bt.trigger('click'); 26815 } 26816 $this.wrapInner($bt); 26817 }); 26818 if (this.ui.$sortSelect.length) { 26819 this.ui.$sortSelect.on('change', function (e) { 26820 var $option = $(this).find('option:selected'); 26821 if ($option[0].hasAttribute('data-col')) { 26822 var sortBy = $option.data('sortby'); 26823 var sortType = $option.data('sorttype') || 'string'; 26824 self.sort(parseInt($option.data('col'), 10) - 1, sortBy, $option.data('direction'), sortType); 26825 self.$el.find('.tableselect-sort button').removeClass('is-active'); 26826 } 26827 }); 26828 } 26829 } 26830 }, { 26831 key: "sort", 26832 value: function sort(col, sortBy, direction, sortType) { 26833 this.sortActive = { 26834 col: col, 26835 sortBy: sortBy, 26836 direction: direction 26837 }; 26838 var getCellValue = function getCellValue(row) { 26839 var val; 26840 if (sortBy) { 26841 val = $(row).children('td').eq(col).attr(sortBy); 26842 } else { 26843 val = $(row).children('td').eq(col).text(); 26844 } 26845 if (sortType == 'number') val = Number(val); 26846 return val; 26847 }; 26848 var rows = this.$el.find('tbody tr').not('.no-sort').toArray().sort(function (a, b) { 26849 var valA = getCellValue(a), 26850 valB = getCellValue(b); 26851 return sortType == 'number' ? valA > valB : valA.toString().localeCompare(valB); 26852 }); 26853 // this.asc = !this.asc 26854 if (direction == 'desc') { 26855 rows = rows.reverse(); 26856 } 26857 var tbody = this.$el.find('tbody'); 26858 for (var i = 0; i < rows.length; i++) { 26859 tbody.append(rows[i]); 26860 } 26861 this.refreshItems(); 26862 } 26863 }, { 26864 key: "refreshItems", 26865 value: function refreshItems() { 26866 var $elements = this.$el.find('tbody tr:not(.no-pagination)'); 26867 this.ui.$countTotal.text($elements.length); 26868 if (this.paginator) { 26869 $elements.hide(); 26870 if ($elements.length > this.itemsByPage) { 26871 this.ui.$pagerWrapper.show(); 26872 this.populatePager($elements.length); 26873 var start = this.activePage * this.itemsByPage; 26874 $elements = $elements.slice(start, start + this.itemsByPage); 26875 } else { 26876 this.ui.$pagerWrapper.hide(); 26877 } 26878 $elements.show(); 26879 } 26880 this.selectChange(); 26881 } 26882 }, { 26883 key: "pagerNav", 26884 value: function pagerNav(e) { 26885 e.preventDefault(); 26886 var $link = $(e.currentTarget); 26887 if ($link.parent().hasClass('pager__list-item')) { 26888 this.activePage = parseInt($link.attr('href').substring(1), 10); 26889 } else {
26890 if ($link.hasClass('pager__round--left')) { 26891 this.activePage = Math.max(0, this.activePage - 1); 26892 } else if ($link.hasClass('pager__round--right')) { 26893 this.activePage = Math.min(this.pages - 1, this.activePage + 1); 26894 } 26895 } 26896 this.refreshItems(); 26897 } 26898 }, { 26899 key: "populatePager", 26900 value: function populatePager(total) { 26901 this.pages = Math.ceil(total / this.itemsByPage); 26902 var items = ''; 26903 var start = Math.max(0, this.activePage - 2); 26904 if (start == 1) start = 0; 26905 var end = Math.min(this.pages - 1, this.activePage + 2); 26906 if (end == this.pages - 2) end = this.pages - 1; 26907 if (start > 0) { 26908 items += '<li class="pager__list-item"><a href="#0">1</a></li>'; 26909 items += '<li class="pager__list-item"><span>...</span></li>'; 26910 } 26911 for (var i = start; i <= end; i++) { 26912 items += '<li class="pager__list-item"><a ' + (i == this.activePage ? 'class="is-active" ' : '') + 'href="#' + i + '">' + (i + 1) + '</a></li>'; 26913 } 26914 if (end < this.pages - 2) { 26915 items += '<li class="pager__list-item"><span>...</span></li>'; 26916 items += '<li class="pager__list-item"><a href="#' + (this.pages - 1) + '">' + this.pages + '</a></li>'; 26917 } 26918 this.ui.$pager.html(items); 26919 } 26920 }, { 26921 key: "selectAllChange", 26922 value: function selectAllChange() { 26923 var selected = this.ui.$inputSelectAll.prop('checked'); 26924 var $els = this.ui.$inputs; 26925 if (this.paginator) { 26926 var start = this.activePage * this.itemsByPage; 26927 $els = $els.slice(start, start + this.itemsByPage); 26928 } 26929 $els.each(function () { 26930 $(this).prop('checked', selected); 26931 }); 26932 this.selectChange(); 26933 } 26934 }, { 26935 key: "selectChange", 26936 value: function selectChange() { 26937 if (this.paginator) { 26938 var start = this.activePage * this.itemsByPage; 26939 var $els = this.ui.$inputs.slice(start, start + this.itemsByPage); 26940 var selected = true; 26941 $els.each(function () { 26942 selected = selected && $(this).prop('checked'); 26943 }); 26944 this.ui.$inputSelectAll.prop('checked', selected); 26945 } 26946 var total = this.count(); 26947 if (total > 0) { 26948 this.ui.$actions.removeClass('button--disabled'); 26949 this.ui.$actions.prop('disabled', false); 26950 } else { 26951 this.ui.$actions.addClass('button--disabled'); 26952 this.ui.$actions.prop('disabled', true); 26953 } 26954 } 26955 }, { 26956 key: "count", 26957 value: function count() { 26958 var total = 0; 26959 this.ui.$inputs.each(function () { 26960 if ($(this).prop('checked')) total++; 26961 }); 26962 this.ui.$count.text(total); 26963 return total; 26964 } 26965 }]); 26966}(); 26967var ts = { 26968 init: function init() { 26969 $('.js-tableselect').each(function () { 26970 $(this).data('tableselect', new TableSelect(this)); 26971 }); 26972 } 26973}; 26974module.exports = ts; 26975 26976},{}],68:[function(require,module,exports){ 26977"use strict"; 26978 26979var tabs = { 26980 ui: {}, 26981 init: function init() { 26982 this.bindUI(); 26983 this.bindEvents(); 26984 }, 26985 bindUI: function bindUI() { 26986 this.ui.$win = $(window); 26987 this.ui.$body = $('body'); 26988 this.ui.$tabs = $('.js-tabs'); 26989 }, 26990 bindEvents: function bindEvents() { 26991 this.ui.$tabs.on('click', $.proxy(this.showTab, this)); 26992 }, 26993 showTab: function showTab(e) { 26994 e.preventDefault(); 26995 var dest = $(e.target).attr('href'); 26996 $(e.target).closest('.js-tabs').find('.js-tabs-item').removeClass('is-active'); 26997 $(e.target).parent().addClass('is-active'); 26998 26999 // hide active tabs. 27000 $(e.target).closest('.js-tabs').find('.js-tabs-content').removeClass('is-active'); 27001 27002 // show active tabs. 27003 $(e.target).closest('.js-tabs').find(dest).addClass('is-active'); 27004 } 27005}; 27006module.exports = tabs; 27007 27008},{}],69:[function(require,module,exports){ 27009"use strict"; 27010 27011function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } 27012function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } 27013function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } 27014function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } 27015function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } 27016function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function");
27016 t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } 27017function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } 27018function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } 27019function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } 27020function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } 27021function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } 27022function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } 27023function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } 27024var btns = []; 27025var BtnOpen = /*#__PURE__*/function () { 27026 function BtnOpen($el, storage) { 27027 _classCallCheck(this, BtnOpen); 27028 this.storage = storage; 27029 this.counter = $el; 27030 this.count = 0; 27031 this.btn = $el.parents('.button--icon'); 27032 this.btns = []; 27033 } 27034 return _createClass(BtnOpen, [{ 27035 key: "initCount", 27036 value: function initCount() { 27037 this.setCounter(this.storage.count); 27038 } 27039 }, { 27040 key: "setCounter", 27041 value: function setCounter(count) { 27042 if (count < 1) { 27043 this.counter.hide(); 27044 } else { 27045 this.counter.show(); 27046 } 27047 this.count = count; 27048 this.counter.text(count); 27049 this.onUpdate(); 27050 } 27051 }, { 27052 key: "refreshAll", 27053 value: function refreshAll() { 27054 this.btns.forEach(function (btn) { 27055 return btn.refresh(); 27056 }); 27057 } 27058 }, { 27059 key: "onUpdate", 27060 value: function onUpdate() {} 27061 }]); 27062}(); 27063var CompBtn = /*#__PURE__*/function (_BtnOpen) { 27064 function CompBtn() { 27065 _classCallCheck(this, CompBtn); 27066 return _callSuper(this, CompBtn, arguments); 27067 } 27068 _inherits(CompBtn, _BtnOpen); 27069 return _createClass(CompBtn, [{ 27070 key: "onUpdate", 27071 value: function onUpdate() { 27072 if (this.count < 2) { 27073 this.btn.addClass('is-disabled'); 27074 } else { 27075 this.btn.removeClass('is-disabled'); 27076 } 27077 if (this.count > 3) { 27078 this.btns.forEach(function (btn) { 27079 return btn.disable(); 27080 }); 27081 } else { 27082 this.btns.forEach(function (btn) { 27083 return btn.enable(); 27084 }); 27085 } 27086 } 27087 }]); 27088}(BtnOpen); 27089var FavBtn = /*#__PURE__*/function (_BtnOpen2) { 27090 function FavBtn() { 27091 _classCallCheck(this, FavBtn); 27092 return _callSuper(this, FavBtn, arguments); 27093 } 27094 _inherits(FavBtn, _BtnOpen2); 27095 return _createClass(FavBtn, [{ 27096 key: "onUpdate", 27097 value: function onUpdate() { 27098 if (this.count < 1) { 27099 this.btn.addClass('is-disabled'); 27100 } else { 27101 this.btn.removeClass('is-disabled'); 27102 } 27103 } 27104 }]); 27105}(BtnOpen); 27106var ToggleBtn = /*#__PURE__*/function () { 27107 function ToggleBtn(el) { 27108 _classCallCheck(this, ToggleBtn); 27109 this.el = el; 27110 this.$el = $(el); 27111 this.$title = this.$el.find('.title'); 27112 this.txtActive = this.$title.data('active'); 27113 this.txtInactive = this.$title.data('inactive'); 27114 try { 27115 this.data = this.$el.data('data'); 27116 } catch (e) { 27117 return; 27118 } 27119 this.disabled = false; 27120 this.type = this.data.type; 27121 this.familyId = 'familyId' in this.data ? parseInt(this.data.familyId, 10) : 0; 27122 this.productId = 'productId' in this.data ? parseInt(this.data.productId, 10) : 0; 27123 this.counter = null; 27124 this.storage = null; 27125 this.bindEvents(); 27126 } 27127 return _createClass(ToggleBtn, [{ 27128 key: "init",
27129 value: function init() { 27130 this.active = this.storage.exists(this.familyId, this.productId); 27131 this.setActive(this.active); 27132 this.setTitle(); 27133 } 27134 }, { 27135 key: "bindEvents", 27136 value: function bindEvents() { 27137 this.$el.on('click', this.toggleIcon.bind(this)); 27138 } 27139 }, { 27140 key: "toggleIcon", 27141 value: function toggleIcon(e) { 27142 e.preventDefault(); 27143 if (this.disabled) { 27144 return; 27145 } 27146 if (this.active) { 27147 this.$el.removeClass('is-selected'); 27148 } else { 27149 this.$el.addClass('is-selected'); 27150 } 27151 if (this.active) { 27152 this.storage.delete(this.familyId, this.productId); 27153 } else { 27154 this.storage.add(this.familyId, this.productId); 27155 } 27156 this.active = !this.active; 27157 if (this.data.type == 'comparator') { 27158 this.comparatorToggled(); 27159 } else { 27160 this.favoritesToggled(); 27161 } 27162 this.$el.blur(); 27163 this.setTitle(); 27164 } 27165 }, { 27166 key: "refresh", 27167 value: function refresh() { 27168 var active = this.storage.exists(this.familyId, this.productId); 27169 if (active !== this.active) { 27170 this.active = active; 27171 this.setActive(active); 27172 } 27173 } 27174 }, { 27175 key: "comparatorToggled", 27176 value: function comparatorToggled() { 27177 this.counter.setCounter(this.storage.count); 27178 } 27179 }, { 27180 key: "favoritesToggled", 27181 value: function favoritesToggled() { 27182 var _this = this; 27183 var data = { 27184 familyIds: [], 27185 productIds: [] 27186 }; 27187 if (this.productId) { 27188 data.productIds.push(this.productId); 27189 } else { 27190 data.familyIds.push(this.familyId); 27191 } 27192 $.ajax({ 27193 url: window.nexansConfig.favoritesServiceUrl.replace('{action}', this.active ? 'add' : 'remove'), 27194 type: 'POST', 27195 contentType: "application/json; charset=utf-8", 27196 data: JSON.stringify(data) 27197 }).done(function (data) { 27198 _this.storage.refresh(data); 27199 _this.counter.setCounter(data.nbItems); 27200 }); 27201 } 27202 }, { 27203 key: "setTitle", 27204 value: function setTitle() { 27205 this.$title.text(this.active ? this.txtActive : this.txtInactive); 27206 } 27207 }, { 27208 key: "setActive", 27209 value: function setActive(active) { 27210 if (active) { 27211 this.$el.addClass('is-selected'); 27212 this.enable(); 27213 } else { 27214 this.$el.removeClass('is-selected'); 27215 } 27216 } 27217 }, { 27218 key: "enable", 27219 value: function enable() { 27220 this.disabled = false; 27221 this.$el.removeClass('is-disabled'); 27222 } 27223 }, { 27224 key: "disable", 27225 value: function disable() { 27226 if (!this.active) { 27227 this.disabled = true; 27228 this.$el.addClass('is-disabled'); 27229 } 27230 } 27231 }]); 27232}(); 27233var toggleIcon = { 27234 init: function init(storage, elements) { 27235 var firstLoad = false; 27236 var favBtn, compBtn; 27237 if (!elements) { 27238 elements = $('.js-toggle-icon'); 27239 firstLoad = true; 27240 } 27241 if (firstLoad && $('.js-favorite-count').length) { 27242 favBtn = new FavBtn($('.js-favorite-count'), storage.favorites); 27243 favBtn.initCount(); 27244 var resetCount = function resetCount() { 27245 $.ajax({ 27246 url: window.nexansConfig.favoritesServiceUrl.replace('{action}', 'count'), 27247 type: 'GET' 27248 }).done(function (data) { 27249 storage.favorites.refresh(data); 27250 favBtn.setCounter(data.nbItems); 27251 favBtn.refreshAll(); 27252 }); 27253 }; 27254 if (storage.favorites.notStored) { 27255 resetCount(); 27256 } else { 27257 favBtn.initCount(); 27258 } 27259 $('body').on('favourites_update', function (e, count) { 27260 if (typeof count !== 'undefined') { 27261 favBtn.setCounter(count); 27262 } else { 27263 resetCount(); 27264 } 27265 }); 27266 } 27267 if (firstLoad && $('.js-comparator-count').length) { 27268 compBtn = new CompBtn($('.js-comparator-count'), storage.comparator); 27269 compBtn.initCount(); 27270 $('body').on('comparator_update', function (e, count, refresh) { 27271 compBtn.setCounter(count); 27272 if (refresh) compBtn.refreshAll(); 27273 }); 27274 } 27275 elements.each(function () { 27276 var bt = new ToggleBtn(this); 27277 if (bt.type === 'comparator') { 27278 bt.counter = compBtn; 27279 bt.storage = storage.comparator;
27280 compBtn.btns.push(bt); 27281 } else { 27282 bt.counter = favBtn; 27283 bt.storage = storage.favorites; 27284 favBtn.btns.push(bt); 27285 } 27286 bt.init(); 27287 }); 27288 } 27289}; 27290module.exports = toggleIcon; 27291 27292},{}],70:[function(require,module,exports){ 27293"use strict"; 27294 27295var toggleVideo = { 27296 ui: {}, 27297 init: function init() { 27298 this.bindUI(); 27299 this.bindEvents(); 27300 }, 27301 bindUI: function bindUI() { 27302 this.ui.$window = $(window); 27303 this.ui.$toggle = $('.js-toggle-video'); 27304 }, 27305 bindEvents: function bindEvents() { 27306 this.ui.$toggle.on('click', this.showVideo); 27307 }, 27308 showVideo: function showVideo(e) { 27309 $(e.currentTarget).addClass('is-play'); 27310 var $self = $(this), 27311 $overlay = $self.closest('.js-video-overlay'); 27312 $overlay.addClass('is-invisible'); 27313 } 27314}; 27315module.exports = toggleVideo; 27316 27317},{}],71:[function(require,module,exports){ 27318"use strict"; 27319 27320var truncate = { 27321 ui: {}, 27322 truncateHeight: 245, 27323 init: function init() { 27324 this.bindUI(); 27325 this.bindEvents(); 27326 }, 27327 bindUI: function bindUI() { 27328 this.ui.$win = $(window); 27329 this.ui.$mobileIndicator = $('.js-is-mobile'); 27330 this.ui.$wrapper = $('.js-truncate'); 27331 this.ui.$content = $('.js-truncate-content'); 27332 this.ui.$trigger = $('.js-truncate-trigger'); 27333 }, 27334 bindEvents: function bindEvents() { 27335 var _this = this; 27336 this.ui.$trigger.on('click', $.proxy(this.showMore, this)); 27337 this.ui.$win.on('load', function () { 27338 return _this.heightHandler(); 27339 }); 27340 this.ui.$win.on('resize', function () { 27341 return _this.heightHandler(); 27342 }); 27343 }, 27344 heightHandler: function heightHandler() { 27345 if (this.ui.$content.prop('scrollHeight') >= this.truncateHeight) { 27346 this.ui.$wrapper.addClass('is-truncated'); 27347 } else { 27348 this.ui.$wrapper.removeClass('is-truncated'); 27349 } 27350 }, 27351 showMore: function showMore(e) { 27352 e.preventDefault(); 27353 this.ui.$content.stop().show(); 27354 this.ui.$wrapper.toggleClass('is-open'); 27355 } 27356}; 27357module.exports = truncate; 27358 27359},{}],72:[function(require,module,exports){ 27360"use strict"; 27361 27362var utils = { 27363 ui: {}, 27364 init: function init() { 27365 this.bindUI(); 27366 this.bindEvents(); 27367 }, 27368 bindUI: function bindUI() { 27369 this.ui.$win = $(window); 27370 this.ui.$body = $('body'); 27371 }, 27372 bindEvents: function bindEvents() { 27373 var self = this; 27374 27375 // Events for scroll. 27376 this.ui.$win.on('scroll', this.throttle(function (event) { 27377 self.ui.$body.trigger('page:scrollDebounced', self.ui.$win.scrollTop()); 27378 }, 10)); 27379 this.ui.$win.on('scroll', function (event) { 27380 self.ui.$body.trigger('page:scroll', self.ui.$win.scrollTop()); 27381 }); 27382 }, 27383 throttle: function throttle(callback, limit) { 27384 var wait = false; // Initially, we're not waiting 27385 return function () { 27386 // We return a 27387 if (!wait) { 27388 callback.call(); // Execute users function 27389 wait = true; // Prevent future invocations 27390 setTimeout(function () { 27391 // After a period of time 27392 wait = false; // And allow future invocations 27393 }, limit); 27394 } 27395 }; 27396 } 27397}; 27398module.exports = utils; 27399 27400},{}],73:[function(require,module,exports){ 27401"use strict"; 27402 27403var viewMore = { 27404 ui: {}, 27405 init: function init() { 27406 this.bindUI(); 27407 this.bindEvents(); 27408 this.ui.$moreWrapper.each(function () { 27409 var $this = $(this); 27410 if ($this.hasClass('is-opened')) { 27411 $this.find('.js-view-more').trigger('click'); 27412 } 27413 }); 27414 }, 27415 bindUI: function bindUI() { 27416 this.ui.$win = $(window); 27417 this.ui.$body = $('body'); 27418 this.ui.$btnMore = $('.js-view-more'); 27419 this.ui.$btnMoreList = $('.js-view-more-list'); 27420 this.ui.$btnMoreButton = $('.js-view-more-button'); 27421 this.ui.$moreWrapper = $('.js-view-more-wrapper'); 27422 this.ui.$moreContent = $('.js-view-more-content'); 27423 }, 27424 bindEvents: function bindEvents() { 27425 this.ui.$btnMore.on('click', $.proxy(this.showMore, this)); 27426 this.ui.$btnMoreButton.on('click', $.proxy(this.showMoreButton, this)); 27427 this.ui.$btnMoreList.on('click', $.proxy(this.showMoreList, this)); 27428 }, 27429 showMore: function showMore(e) { 27430 e.preventDefault(); 27431 var $item = $(e.currentTarget).closest('.js-view-more-wrapper'); 27432 var $items = $item.find(this.ui.$moreContent); 27433 if (!$(e.currentTarget).hasClass('is-less')) { 27434 $($items).fadeIn(); 27435 $item.addClass('is-opened'); 27436 } else { 27437 $($items).hide(); 27438 $item.removeClass('is-opened'); 27439 } 27440 $(e.currentTarget).toggleClass('is-less'); 27441 }, 27442 showMoreButton: function showMoreButton(e) { 27443 e.preventDefault(); 27444 var $item = $(e.currentTarget).closest('.js-view-more-wrapper'); 27445 var $this = $item.find(this.ui.$moreContent); 27446 $($this).fadeIn(); 27447 $(e.currentTarget).addClass('is-hidden'); 27448 }, 27449 showMoreList: function showMoreList(e) { 27450 e.preventDefault(); 27451 var $item = $(e.currentTarget).closest('.js-view-more-wrapper'); 27452 var $items = $item.find(this.ui.$moreContent); 27453 if (!$(e.currentTarget).hasClass('is-less')) { 27454 $($items).fadeIn(); 27455 } else { 27456 $($items).hide(); 27457 } 27458 27459 //$(e.currentTarget).addClass('is-hidden'); 27460 27461 $(e.currentTarget).toggleClass('is-less'); 27462 } 27463}; 27464module.exports = viewMore; 27465 27466},{}],74:[function(require,module,exports){ 27467"use strict"; 27468 27469// Plugin Carousel. 27470 27471(function ($) { 27472 $.fn.carouselFinance = function (options) { 27473 // Create defaults parameters in case we don't pass any argument. 27474 var defaults = {}; 27475 27476 // Merge the defaults and the options arguments. 27477 var options = $.extend(defaults, options); 27478 27479 // Launch the carousel function. 27480 return this.each(function (index, element) { 27481 var carousel = { 27482 ui: {}, 27483 itemActive: 0, 27484 slidesLength: 0, 27485 counterCurrent: 0, 27486 currentCaption: "", 27487 touchVariables: { 27488 "posXStart": 0, 27489 "posAlreadyScrolled": 0, 27490 "posXMove": 0, 27491 "toScrollTouch": 0, 27492 "delta": 0, 27493 "goTranslate": 0 27494 },
27495 init: function init() { 27496 this.bindUI(); 27497 this.bindEvents(); 27498 this.initSlider(); 27499 }, 27500 bindUI: function bindUI() { 27501 this.ui.$win = $(window); 27502 this.ui.$container = element; 27503 this.ui.$slider = $('.js-carousel-finance-slider', this.ui.$container); 27504 this.ui.$wrapper = $('.js-carousel-finance-wrapper', this.ui.$container); 27505 this.ui.$slide = $('.js-carousel-finance-slide', this.ui.$container); 27506 this.ui.$captions = $('.js-carousel-finance-captions li', this.ui.$container); 27507 this.ui.$counter = $('.js-carousel-finance-counter', this.ui.$container); 27508 this.ui.$total = $('.js-carousel-finance-total', this.ui.$container); 27509 this.ui.$cover = $('.js-carousel-finance-cover', this.ui.$container); 27510 this.ui.$prev = $('.js-carousel-finance-prev', this.ui.$container); 27511 this.ui.$next = $('.js-carousel-finance-next', this.ui.$container); 27512 }, 27513 bindEvents: function bindEvents() { 27514 this.ui.$next.on('click', $.proxy(this.onNext, this)); 27515 this.ui.$prev.on('click', $.proxy(this.onPrev, this)); 27516 this.ui.$slide.on('touchstart', $.proxy(this.dragStart, this)); 27517 this.ui.$slide.on('touchmove', $.proxy(this.dragMove, this)); 27518 this.ui.$slide.on('touchend', $.proxy(this.dragEnd, this)); 27519 this.ui.$win.on('resize', $.proxy(this.setSize, this)); 27520 }, 27521 initSlider: function initSlider() { 27522 // Setting up the slides length 27523 this.slidesLength = this.ui.$slide.length; 27524 27525 //Build Counter 27526 this.updateCounter(); 27527 27528 // Hide prev button on load 27529 this.fadeBtn(); 27530 this.showCover(this.itemActive + 1); 27531 this.setSize(); 27532 }, 27533 setSize: function setSize() { 27534 var widthTotal = 0; 27535 var widthItem = 0; 27536 widthItem = $('.carousel-finance__item-wrapper').outerWidth() - 40; 27537 $.each(this.ui.$slide, function () { 27538 widthTotal += $('.js-carousel-finance-slide').outerWidth(); 27539 }); 27540 $('.js-carousel-finance-slide').width(widthItem); 27541 $('.js-carousel-finance-wrapper').width(widthTotal); 27542 this.translateTo(); 27543 }, 27544 updateCounter: function buildCounter() { 27545 // Setting up the counter to match the current active slide 27546 this.ui.$counter.text(this.itemActive + 1); 27547 27548 // Setting up the counter total to match the slides length 27549 this.ui.$total.text(this.slidesLength); 27550 }, 27551 translateTo: function translateTo() { 27552 var translate = 0; 27553 for (var i = 0; i < this.itemActive; i++) { 27554 translate -= Math.round($(this.ui.$slide[i]).outerWidth()); 27555 } 27556 this.ui.$wrapper.css({ 27557 "transform": "translateX(" + translate + "px)" 27558 }); 27559 this.fadeBtn(); 27560 }, 27561 showCover: function showCover(id) { 27562 $('.js-carousel-finance-cover').removeClass('is-active'); 27563 var $currentList = $('.js-carousel-finance').find('.js-carousel-finance-cover[data-cover=' + id + ']'); 27564 $currentList.addClass('is-active'); 27565 }, 27566 onNext: function onNext(e) { 27567 if (this.itemActive == this.slidesLength - 1) { 27568 return; 27569 } 27570 this.itemActive++; 27571 this.updateCounter(); 27572 this.translateTo(); 27573 this.showCover(this.itemActive + 1); 27574 }, 27575 onPrev: function onPrev(e) { 27576 if (this.itemActive == 0) { 27577 return; 27578 } 27579 this.itemActive--; 27580 this.updateCounter(); 27581 this.translateTo(); 27582 this.showCover(this.itemActive + 1); 27583 }, 27584 dragStart: function dragStart(e) { 27585 this.touchVariables.posXStart = e.originalEvent.touches[0].pageX; 27586 }, 27587 dragMove: function dragMove(e) { 27588 this.touchVariables.posXMove = e.originalEvent.touches[0].pageX; 27589 this.touchVariables.delta = this.touchVariables.posXMove - this.touchVariables.posXStart; 27590 }, 27591 dragEnd: function dragEnd() { 27592 if (this.touchVariables.delta > 0) { 27593 this.onPrev(); 27594 } else if (this.touchVariables.delta < 0) { 27595 this.onNext(); 27596 } 27597 this.touchVariables.delta = 0; 27598 }, 27599 fadeBtn: function fadeBtn() { 27600 if (this.itemActive == 0) { 27601 this.ui.$next.removeClass('is-fade'); 27602 this.ui.$prev.addClass('is-fade'); 27603 } else if (this.ui.$slide.length - 1 == this.itemActive) { 27604 this.ui.$next.addClass('is-fade'); 27605 this.ui.$prev.removeClass('is-fade'); 27606 } else { 27607 this.ui.$next.removeClass('is-fade'); 27608 this.ui.$prev.removeClass('is-fade'); 27609 } 27610 } 27611 }; 27612 27613 // Intialize the carousel. 27614 carousel.init(); 27615 }); 27616 }; 27617})(jQuery); 27618 27619},{}],75:[function(require,module,exports){ 27620"use strict"; 27621 27622// Plugin Carousel. 27623 27624(function ($) { 27625 $.fn.carouselGallery = function (options) { 27626 // Create defaults parameters in case we don't pass any argument. 27627 var defaults = {}; 27628 27629 // Merge the defaults and the options arguments. 27630 var options = $.extend(defaults, options); 27631 27632 // Launch the carousel function. 27633 return this.each(function (index, element) { 27634 var carousel = { 27635 ui: {}, 27636 itemActive: 0, 27637 slidesLength: 0, 27638 counterCurrent: 0, 27639 currentCaption: "", 27640 touchVariables: { 27641 "posXStart": 0, 27642 "posAlreadyScrolled": 0, 27643 "posXMove": 0, 27644 "toScrollTouch": 0, 27645 "delta": 0, 27646 "goTranslate": 0 27647 },
27648 init: function init() { 27649 this.bindUI(); 27650 this.bindEvents(); 27651 this.initSlider(); 27652 }, 27653 bindUI: function bindUI() { 27654 this.ui.$win = $(window); 27655 this.ui.$container = element; 27656 this.ui.$slider = $('.js-carousel-gallery-slider', this.ui.$container); 27657 this.ui.$wrapper = $('.js-carousel-gallery-wrapper', this.ui.$container); 27658 this.ui.$slide = $('.js-carousel-gallery-slide', this.ui.$container); 27659 this.ui.$captions = $('.js-carousel-gallery-legend', this.ui.$container); 27660 this.ui.$counter = $('.js-carousel-gallery-captions .slide-id', this.ui.$container); 27661 this.ui.$total = $('.js-carousel-gallery-captions .slide-total', this.ui.$container); 27662 this.ui.$prev = $('.js-carousel-gallery-prev', this.ui.$container); 27663 this.ui.$next = $('.js-carousel-gallery-next', this.ui.$container); 27664 this.ui.$galleryItem = $('.js-gallery-item'); 27665 this.ui.$gallertModal = $('.js-modal'); 27666 this.ui.$closeModal = $('.js-modal .js-modal-close'); 27667 }, 27668 bindEvents: function bindEvents() { 27669 this.ui.$next.on('click', $.proxy(this.onNext, this)); 27670 this.ui.$prev.on('click', $.proxy(this.onPrev, this)); 27671 this.ui.$slide.on('touchstart', $.proxy(this.dragStart, this)); 27672 this.ui.$slide.on('touchmove', $.proxy(this.dragMove, this)); 27673 this.ui.$slide.on('touchend', $.proxy(this.dragEnd, this)); 27674 this.ui.$galleryItem.on('click', $.proxy(this.loadSlider, this)); 27675 this.ui.$closeModal.on('click', $.proxy(this.resetSlider, this)); 27676 }, 27677 initSlider: function initSlider() { 27678 // Setting up the slides length 27679 this.slidesLength = this.ui.$slide.length; 27680 27681 //Build Counter 27682 this.updateCounter(); 27683 27684 //Build Captions 27685 this.updateCaptions(); 27686 27687 // Hide prev button on load 27688 this.fadeBtn(); 27689 }, 27690 updateCounter: function buildCounter() { 27691 // Setting up the counter to match the current active slide 27692 this.ui.$counter.text(this.itemActive + 1); 27693 27694 // Setting up the counter total to match the slides length 27695 this.ui.$total.text(this.slidesLength); 27696 }, 27697 updateCaptions: function buildCaptions() { 27698 // Retrieve the active slide's data-caption and set the correct caption 27699 this.currentCaption = this.ui.$wrapper.find('.js-carousel-gallery-slide').eq(this.itemActive).data('caption'); 27700 this.ui.$captions.text(this.currentCaption); 27701 }, 27702 translateTo: function translateTo() { 27703 var translate = 0; 27704 for (var i = 0; i < this.itemActive; i++) { 27705 translate -= Math.round($(this.ui.$slide[i]).outerWidth()); 27706 } 27707 this.ui.$wrapper.css({ 27708 "transform": "translateX(" + translate + "px)" 27709 }); 27710 this.fadeBtn(); 27711 }, 27712 onNext: function onNext(e) { 27713 if (this.itemActive == this.slidesLength - 1) { 27714 return; 27715 } 27716 this.itemActive++; 27717 this.updateCounter(); 27718 this.updateCaptions(); 27719 this.translateTo(); 27720 }, 27721 onPrev: function onPrev(e) { 27722 if (this.itemActive == 0) { 27723 return; 27724 } 27725 this.itemActive--; 27726 this.updateCounter(); 27727 this.updateCaptions(); 27728 this.translateTo(); 27729 }, 27730 dragStart: function dragStart(e) { 27731 this.touchVariables.posXStart = e.originalEvent.touches[0].pageX; 27732 }, 27733 dragMove: function dragMove(e) { 27734 this.touchVariables.posXMove = e.originalEvent.touches[0].pageX; 27735 this.touchVariables.delta = this.touchVariables.posXMove - this.touchVariables.posXStart; 27736 }, 27737 dragEnd: function dragEnd() { 27738 if (this.touchVariables.delta > 0) { 27739 this.onPrev(); 27740 } else if (this.touchVariables.delta < 0) { 27741 this.onNext(); 27742 } 27743 this.touchVariables.delta = 0; 27744 }, 27745 fadeBtn: function fadeBtn() { 27746 if (this.itemActive == 0) { 27747 this.ui.$next.removeClass('is-fade'); 27748 this.ui.$prev.addClass('is-fade'); 27749 } else if (this.ui.$slide.length - 1 == this.itemActive) { 27750 this.ui.$next.addClass('is-fade'); 27751 this.ui.$prev.removeClass('is-fade'); 27752 } else { 27753 this.ui.$next.removeClass('is-fade'); 27754 this.ui.$prev.removeClass('is-fade'); 27755 } 27756 }, 27757 loadSlider: function loadSlider(e) { 27758 var $el = $(e.currentTarget), 27759 ref = $el.data('ref'), 27760 modal = $el.data('modal'), 27761 index = 0; 27762 27763 // find modal active. 27764 $.each(this.ui.$gallertModal, function () { 27765 if (modal = $(this).data('modal')) { 27766 // find list of slide. 27767 var wrapper = $(this).find('.js-carousel-gallery-wrapper'); 27768 27769 // get index of slide. 27770 var itemByRef = $(this).find("[data-ref='" + ref + "']"); 27771 index = itemByRef.index() + 1; 27772 } 27773 }); 27774 27775 // test if item sup 1 27776 if (index > 1) { 27777 for (var i = 1; i < index; i++) { 27778 this.ui.$next.trigger("click"); 27779 } 27780 } else if (index = 1) {} 27781 }, 27782 resetSlider: function resetSlider(e) { 27783 e.preventDefault(); 27784 setTimeout(function () { 27785 var translate = 0; 27786 $('.js-carousel-gallery-wrapper').css({
27787 "transform": "translateX(" + translate + "px)" 27788 }); 27789 this.itemActive = 0; 27790 this.counterCurrent = 0; 27791 this.currentCaption = ""; 27792 }, 200); 27793 } 27794 }; 27795 27796 // Intialize the carousel. 27797 carousel.init(); 27798 }); 27799 }; 27800})(jQuery); 27801 27802},{}],76:[function(require,module,exports){ 27803"use strict"; 27804 27805// Plugin Carousel. 27806 27807(function ($) { 27808 $.fn.carouselOverlay = function (options) { 27809 // Create defaults parameters in case we don't pass any argument. 27810 var defaults = {}; 27811 27812 // Merge the defaults and the options arguments. 27813 var options = $.extend(defaults, options); 27814 27815 // Launch the carousel function. 27816 return this.each(function (index, element) { 27817 var carousel = { 27818 ui: {}, 27819 itemActive: 0, 27820 slidesLength: 0, 27821 counterCurrent: 0, 27822 currentCaption: "", 27823 touchVariables: { 27824 "posXStart": 0, 27825 "posAlreadyScrolled": 0, 27826 "posXMove": 0, 27827 "toScrollTouch": 0, 27828 "delta": 0, 27829 "goTranslate": 0 27830 }, 27831 init: function init() { 27832 this.bindUI(); 27833 this.bindEvents(); 27834 this.initSlider(); 27835 }, 27836 bindUI: function bindUI() { 27837 this.ui.$win = $(window); 27838 this.ui.$body = $('body'); 27839 this.ui.$container = element; 27840 this.ui.$slider = $('.js-carousel-overlay-slider', this.ui.$container); 27841 this.ui.$wrapper = $('.js-carousel-overlay-wrapper', this.ui.$container); 27842 this.ui.$slide = $('.js-carousel-overlay-slide', this.ui.$container); 27843 this.ui.$captions = $('.js-carousel-overlay-legend', this.ui.$container); 27844 this.ui.$counter = $('.js-carousel-overlay-captions .slide-id', this.ui.$container); 27845 this.ui.$total = $('.js-carousel-overlay-captions .slide-total', this.ui.$container); 27846 this.ui.$prev = $('.js-carousel-overlay-prev', this.ui.$container); 27847 this.ui.$next = $('.js-carousel-overlay-next', this.ui.$container); 27848 this.ui.$btnOpen = $('.js-carousel-open'); 27849 this.ui.$btnClose = $('.js-close-panel'); 27850 this.ui.container = $('.js-carousel-overlay'); 27851 }, 27852 bindEvents: function bindEvents() { 27853 this.ui.$next.on('click', $.proxy(this.onNext, this)); 27854 this.ui.$prev.on('click', $.proxy(this.onPrev, this)); 27855 this.ui.$slide.on('touchstart', $.proxy(this.dragStart, this)); 27856 this.ui.$slide.on('touchmove', $.proxy(this.dragMove, this)); 27857 this.ui.$slide.on('touchend', $.proxy(this.dragEnd, this)); 27858 this.ui.$btnOpen.on('click', $.proxy(this.openCarousel, this)); 27859 this.ui.$btnClose.on('click', $.proxy(this.closeCarousel, this)); 27860 $(document).on('keyup', $.proxy(this.closeCarousel, this)); 27861 }, 27862 initSlider: function initSlider() { 27863 // Setting up the slides length 27864 this.slidesLength = this.ui.$slide.length; 27865 27866 //Build Counter 27867 this.updateCounter(); 27868 27869 //Build Captions 27870 this.updateCaptions(); 27871 27872 // Hide prev button on load 27873 this.fadeBtn(); 27874 }, 27875 updateCounter: function buildCounter() { 27876 // Setting up the counter to match the current active slide 27877 this.ui.$counter.text(this.itemActive + 1); 27878 27879 // Setting up the counter total to match the slides length 27880 this.ui.$total.text(this.slidesLength); 27881 }, 27882 updateCaptions: function buildCaptions() { 27883 // Retrieve the active slide's data-caption and set the correct caption 27884 this.currentCaption = this.ui.$wrapper.find('.js-carousel-overlay-slide').eq(this.itemActive).data('caption'); 27885 this.ui.$captions.text(this.currentCaption); 27886 }, 27887 translateTo: function translateTo() { 27888 var translate = 0; 27889 for (var i = 0; i < this.itemActive; i++) { 27890 translate -= Math.round($(this.ui.$slide[i]).outerWidth()); 27891 } 27892 this.ui.$wrapper.css({ 27893 "-webkit-transform": "translateX(" + translate + "px)",
27894 "-moz-transform": "translateX(" + translate + "px)", 27895 "-ms-transform": "translateX(" + translate + "px)", 27896 "-o-transform": "translateX(" + translate + "px)", 27897 "transform": "translateX(" + translate + "px)" 27898 }); 27899 this.fadeBtn(); 27900 }, 27901 translateToItem: function translateToItem(itemId) { 27902 console.log(itemId); 27903 }, 27904 onNext: function onNext(e) { 27905 if (this.itemActive == this.slidesLength - 1) { 27906 return; 27907 } 27908 this.itemActive++; 27909 this.updateCounter(); 27910 this.updateCaptions(); 27911 this.translateTo(); 27912 }, 27913 onPrev: function onPrev(e) { 27914 if (this.itemActive == 0) { 27915 return; 27916 } 27917 this.itemActive--; 27918 this.updateCounter(); 27919 this.updateCaptions(); 27920 this.translateTo(); 27921 }, 27922 dragStart: function dragStart(e) { 27923 this.touchVariables.posXStart = e.originalEvent.touches[0].pageX; 27924 }, 27925 dragMove: function dragMove(e) { 27926 this.touchVariables.posXMove = e.originalEvent.touches[0].pageX; 27927 this.touchVariables.delta = this.touchVariables.posXMove - this.touchVariables.posXStart; 27928 }, 27929 dragEnd: function dragEnd() { 27930 if (this.touchVariables.delta > 0) { 27931 this.onPrev(); 27932 } else if (this.touchVariables.delta < 0) { 27933 this.onNext(); 27934 } 27935 this.touchVariables.delta = 0; 27936 }, 27937 fadeBtn: function fadeBtn() { 27938 if (this.itemActive == 0) { 27939 this.ui.$next.removeClass('is-fade'); 27940 this.ui.$prev.addClass('is-fade'); 27941 } else if (this.ui.$slide.length - 1 == this.itemActive) { 27942 this.ui.$next.addClass('is-fade'); 27943 this.ui.$prev.removeClass('is-fade'); 27944 } else { 27945 this.ui.$next.removeClass('is-fade'); 27946 this.ui.$prev.removeClass('is-fade'); 27947 } 27948 }, 27949 openCarousel: function openCarousel(e) { 27950 // open modale. 27951 this.ui.$body.addClass('is-locked'); 27952 this.ui.container.addClass('is-open'); 27953 27954 // Get ref Id click 27955 var dataImage = $(e.currentTarget).find('img').data('ref'); 27956 this.translateToItem(dataImage); 27957 }, 27958 closeCarousel: function closeCarousel(e) { 27959 e.preventDefault(); 27960 27961 // close modale. 27962 this.ui.$body.removeClass('is-locked'); 27963 this.ui.container.removeClass('is-open'); 27964 27965 // close modal with keyboard esc. 27966 if (e.keyCode == 27) { 27967 this.ui.$body.removeClass('is-locked'); 27968 this.ui.container.removeClass('is-open'); 27969 } 27970 } 27971 }; 27972 27973 // Intialize the carousel. 27974 carousel.init(); 27975 }); 27976 }; 27977})(jQuery); 27978 27979},{}],77:[function(require,module,exports){ 27980"use strict"; 27981 27982// Plugin Carousel. 27983 27984(function ($) { 27985 $.fn.carouselSimple = function (options) { 27986 // Create defaults parameters in case we don't pass any argument. 27987 var defaults = {}; 27988 27989 // Merge the defaults and the options arguments. 27990 var options = $.extend(defaults, options); 27991 27992 // Launch the carousel function. 27993 return this.each(function (index, element) { 27994 var carousel = { 27995 ui: {}, 27996 itemActive: 0, 27997 slidesLength: 0, 27998 counterCurrent: 0, 27999 currentCaption: "", 28000 touchVariables: { 28001 "posXStart": 0, 28002 "posAlreadyScrolled": 0, 28003 "posXMove": 0, 28004 "toScrollTouch": 0, 28005 "delta": 0, 28006 "goTranslate": 0 28007 }, 28008 init: function init() { 28009 this.bindUI(); 28010 this.bindEvents(); 28011 this.initSlider(); 28012 }, 28013 bindUI: function bindUI() { 28014 this.ui.$win = $(window); 28015 this.ui.$container = element; 28016 this.ui.$slider = $('.js-carousel-simple-slider', this.ui.$container); 28017 this.ui.$wrapper = $('.js-carousel-simple-wrapper', this.ui.$container); 28018 this.ui.$slide = $('.js-carousel-simple-slide', this.ui.$container); 28019 this.ui.$captions = $('.js-carousel-simple-captions li', this.ui.$container); 28020 this.ui.$counter = $('.js-carousel-simple-captions .slide-id', this.ui.$container); 28021 this.ui.$total = $('.js-carousel-simple-captions .slide-total', this.ui.$container); 28022 this.ui.$prev = $('.js-carousel-simple-prev', this.ui.$container); 28023 this.ui.$next = $('.js-carousel-simple-next', this.ui.$container); 28024 }, 28025 bindEvents: function bindEvents() { 28026 this.ui.$next.on('click', $.proxy(this.onNext, this)); 28027 this.ui.$prev.on('click', $.proxy(this.onPrev, this)); 28028 this.ui.$slide.on('touchstart', $.proxy(this.dragStart, this)); 28029 this.ui.$slide.on('touchmove', $.proxy(this.dragMove, this)); 28030 this.ui.$slide.on('touchend', $.proxy(this.dragEnd, this)); 28031 }, 28032 initSlider: function initSlider() { 28033 // Setting up the slides length 28034 this.slidesLength = this.ui.$slide.length; 28035 28036 //Build Counter 28037 this.updateCounter(); 28038 28039 //Build Captions 28040 this.updateCaptions(); 28041 28042 // Hide prev button on load 28043 this.fadeBtn(); 28044 }, 28045 updateCounter: function buildCounter() { 28046 // Setting up the counter to match the current active slide 28047 this.ui.$counter.text(this.itemActive + 1); 28048 28049 // Setting up the counter total to match the slides length 28050 this.ui.$total.text(this.slidesLength); 28051 }, 28052 updateCaptions: function buildCaptions() { 28053 // Retrieve the active slide's data-caption and set the correct caption 28054 this.currentCaption = this.ui.$wrapper.find('.js-carousel-simple-slide').eq(this.itemActive).data('caption'); 28055 this.ui.$captions.text(this.currentCaption); 28056 }, 28057 translateTo: function translateTo() { 28058 var translate = 0; 28059 for (var i = 0; i < this.itemActive; i++) { 28060 translate -= Math.round($(this.ui.$slide[i]).outerWidth()); 28061 } 28062 this.ui.$wrapper.css({
28063 "-webkit-transform": "translateX(" + translate + "px)", 28064 "-moz-transform": "translateX(" + translate + "px)", 28065 "-ms-transform": "translateX(" + translate + "px)", 28066 "-o-transform": "translateX(" + translate + "px)", 28067 "transform": "translateX(" + translate + "px)" 28068 }); 28069 this.fadeBtn(); 28070 }, 28071 onNext: function onNext(e) { 28072 if (this.itemActive == this.slidesLength - 1) { 28073 return; 28074 } 28075 this.itemActive++; 28076 this.updateCounter(); 28077 this.updateCaptions(); 28078 this.translateTo(); 28079 }, 28080 onPrev: function onPrev(e) { 28081 if (this.itemActive == 0) { 28082 return; 28083 } 28084 this.itemActive--; 28085 this.updateCounter(); 28086 this.updateCaptions(); 28087 this.translateTo(); 28088 }, 28089 dragStart: function dragStart(e) { 28090 this.touchVariables.posXStart = e.originalEvent.touches[0].pageX; 28091 }, 28092 dragMove: function dragMove(e) { 28093 this.touchVariables.posXMove = e.originalEvent.touches[0].pageX; 28094 this.touchVariables.delta = this.touchVariables.posXMove - this.touchVariables.posXStart; 28095 }, 28096 dragEnd: function dragEnd() { 28097 if (this.touchVariables.delta > 0) { 28098 this.onPrev(); 28099 } else if (this.touchVariables.delta < 0) { 28100 this.onNext(); 28101 } 28102 this.touchVariables.delta = 0; 28103 }, 28104 fadeBtn: function fadeBtn() { 28105 if (this.itemActive == 0) { 28106 this.ui.$next.removeClass('is-fade'); 28107 this.ui.$prev.addClass('is-fade'); 28108 } else if (this.ui.$slide.length - 1 == this.itemActive) { 28109 this.ui.$next.addClass('is-fade'); 28110 this.ui.$prev.removeClass('is-fade'); 28111 } else { 28112 this.ui.$next.removeClass('is-fade'); 28113 this.ui.$prev.removeClass('is-fade'); 28114 } 28115 } 28116 }; 28117 28118 // Intialize the carousel. 28119 carousel.init(); 28120 }); 28121 }; 28122})(jQuery); 28123 28124},{}]},{},[9]);
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.