vendor: 5,009 bytes, lines 1-198
1/*! 2 * @overview es6-promise - a tiny implementation of Promises/A+. 3 * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald) 4 * @license Licensed under MIT license 5 * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE 6 * @version v4.2.8+1e68dce6 7 */ 8 9(function (global, factory) { 10 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 11 typeof define === 'function' && define.amd ? define(factory) : 12 (global.ES6Promise = factory()); 13}(this, (function () { 'use strict'; 14 15function objectOrFunction(x) { 16 var type = typeof x; 17 return x !== null && (type === 'object' || type === 'function'); 18} 19 20function isFunction(x) { 21 return typeof x === 'function'; 22} 23 24 25 26var _isArray = void 0; 27if (Array.isArray) { 28 _isArray = Array.isArray; 29} else { 30 _isArray = function (x) { 31 return Object.prototype.toString.call(x) === '[object Array]'; 32 }; 33} 34 35var isArray = _isArray; 36 37var len = 0; 38var vertxNext = void 0; 39var customSchedulerFn = void 0; 40 41var asap = function asap(callback, arg) { 42 queue[len] = callback; 43 queue[len + 1] = arg; 44 len += 2; 45 if (len === 2) { 46 // If len is 2, that means that we need to schedule an async flush. 47 // If additional callbacks are queued before the queue is flushed, they 48 // will be processed by this flush that we are scheduling. 49 if (customSchedulerFn) { 50 customSchedulerFn(flush); 51 } else { 52 scheduleFlush(); 53 } 54 } 55}; 56 57function setScheduler(scheduleFn) { 58 customSchedulerFn = scheduleFn; 59} 60 61function setAsap(asapFn) { 62 asap = asapFn; 63} 64 65var browserWindow = typeof window !== 'undefined' ? window : undefined; 66var browserGlobal = browserWindow || {}; 67var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; 68var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && {}.toString.call(process) === '[object process]'; 69 70// test for web worker but not in IE10 71var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined'; 72 73// node 74function useNextTick() { 75 // node version 0.10.x displays a deprecation warning when nextTick is used recursively 76 // see https://github.com/cujojs/when/issues/410 for details 77 return function () { 78 return process.nextTick(flush); 79 }; 80} 81 82// vertx 83function useVertxTimer() { 84 if (typeof vertxNext !== 'undefined') { 85 return function () { 86 vertxNext(flush); 87 }; 88 } 89 90 return useSetTimeout(); 91} 92 93function useMutationObserver() { 94 var iterations = 0; 95 var observer = new BrowserMutationObserver(flush); 96 var node = document.createTextNode(''); 97 observer.observe(node, { characterData: true }); 98 99 return function () { 100 node.data = iterations = ++iterations % 2; 101 }; 102} 103 104// web worker 105function useMessageChannel() { 106 var channel = new MessageChannel(); 107 channel.port1.onmessage = flush; 108 return function () { 109 return channel.port2.postMessage(0); 110 }; 111} 112 113function useSetTimeout() { 114 // Store setTimeout reference so es6-promise will be unaffected by 115 // other code modifying setTimeout (like sinon.useFakeTimers()) 116 var globalSetTimeout = setTimeout; 117 return function () { 118 return globalSetTimeout(flush, 1); 119 }; 120} 121 122var queue = new Array(1000); 123function flush() { 124 for (var i = 0; i < len; i += 2) { 125 var callback = queue[i]; 126 var arg = queue[i + 1]; 127 128 callback(arg); 129 130 queue[i] = undefined; 131 queue[i + 1] = undefined; 132 } 133 134 len = 0; 135} 136 137function attemptVertx() { 138 try { 139 var vertx = Function('return this')().require('vertx'); 140 vertxNext = vertx.runOnLoop || vertx.runOnContext; 141 return useVertxTimer(); 142 } catch (e) { 143 return useSetTimeout(); 144 } 145} 146 147var scheduleFlush = void 0; 148// Decide what async method to use to triggering processing of queued callbacks: 149if (isNode) { 150 scheduleFlush = useNextTick(); 151} else if (BrowserMutationObserver) { 152 scheduleFlush = useMutationObserver(); 153} else if (isWorker) { 154 scheduleFlush = useMessageChannel(); 155} else if (browserWindow === undefined && typeof require === 'function') { 156 scheduleFlush = attemptVertx(); 157} else { 158 scheduleFlush = useSetTimeout(); 159} 160 161function then(onFulfillment, onRejection) { 162 var parent = this; 163 164 var child = new this.constructor(noop); 165 166 if (child[PROMISE_ID] === undefined) { 167 makePromise(child); 168 } 169 170 var _state = parent._state; 171 172 173 if (_state) { 174 var callback = arguments[_state - 1]; 175 asap(function () { 176 return invokeCallback(_state, child, callback, parent._result); 177 }); 178 } else { 179 subscribe(parent, child, onFulfillment, onRejection); 180 } 181 182 return child; 183} 184 185/** 186 `Promise.resolve` returns a promise that will become resolved with the 187 passed `value`. It is shorthand for the following: 188 189 ```javascript 190 let promise = new Promise(function(resolve, reject){ 191 resolve(1); 192 }); 193 194 promise.then(function(value){ 195 // value === 1 196 }); 197 ``` 198
vendor: 7,394 bytes, lines 199-519
199 Instead of writing the above, your code now simply becomes the following: 200 201 ```javascript 202 let promise = Promise.resolve(1); 203 204 promise.then(function(value){ 205 // value === 1 206 }); 207 ``` 208 209 @method resolve 210 @static 211 @param {Any} value value that the returned promise will be resolved with 212 Useful for tooling. 213 @return {Promise} a promise that will become fulfilled with the given 214 `value` 215*/ 216function resolve$1(object) { 217 /*jshint validthis:true */ 218 var Constructor = this; 219 220 if (object && typeof object === 'object' && object.constructor === Constructor) { 221 return object; 222 } 223 224 var promise = new Constructor(noop); 225 resolve(promise, object); 226 return promise; 227} 228 229var PROMISE_ID = Math.random().toString(36).substring(2); 230 231function noop() {} 232 233var PENDING = void 0; 234var FULFILLED = 1; 235var REJECTED = 2; 236 237function selfFulfillment() { 238 return new TypeError("You cannot resolve a promise with itself"); 239} 240 241function cannotReturnOwn() { 242 return new TypeError('A promises callback cannot return that same promise.'); 243} 244 245function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) { 246 try { 247 then$$1.call(value, fulfillmentHandler, rejectionHandler); 248 } catch (e) { 249 return e; 250 } 251} 252 253function handleForeignThenable(promise, thenable, then$$1) { 254 asap(function (promise) { 255 var sealed = false; 256 var error = tryThen(then$$1, thenable, function (value) { 257 if (sealed) { 258 return; 259 } 260 sealed = true; 261 if (thenable !== value) { 262 resolve(promise, value); 263 } else { 264 fulfill(promise, value); 265 } 266 }, function (reason) { 267 if (sealed) { 268 return; 269 } 270 sealed = true; 271 272 reject(promise, reason); 273 }, 'Settle: ' + (promise._label || ' unknown promise')); 274 275 if (!sealed && error) { 276 sealed = true; 277 reject(promise, error); 278 } 279 }, promise); 280} 281 282function handleOwnThenable(promise, thenable) { 283 if (thenable._state === FULFILLED) { 284 fulfill(promise, thenable._result); 285 } else if (thenable._state === REJECTED) { 286 reject(promise, thenable._result); 287 } else { 288 subscribe(thenable, undefined, function (value) { 289 return resolve(promise, value); 290 }, function (reason) { 291 return reject(promise, reason); 292 }); 293 } 294} 295 296function handleMaybeThenable(promise, maybeThenable, then$$1) { 297 if (maybeThenable.constructor === promise.constructor && then$$1 === then && maybeThenable.constructor.resolve === resolve$1) { 298 handleOwnThenable(promise, maybeThenable); 299 } else { 300 if (then$$1 === undefined) { 301 fulfill(promise, maybeThenable); 302 } else if (isFunction(then$$1)) { 303 handleForeignThenable(promise, maybeThenable, then$$1); 304 } else { 305 fulfill(promise, maybeThenable); 306 } 307 } 308} 309 310function resolve(promise, value) { 311 if (promise === value) { 312 reject(promise, selfFulfillment()); 313 } else if (objectOrFunction(value)) { 314 var then$$1 = void 0; 315 try { 316 then$$1 = value.then; 317 } catch (error) { 318 reject(promise, error); 319 return; 320 } 321 handleMaybeThenable(promise, value, then$$1); 322 } else { 323 fulfill(promise, value); 324 } 325} 326 327function publishRejection(promise) { 328 if (promise._onerror) { 329 promise._onerror(promise._result); 330 } 331 332 publish(promise); 333} 334 335function fulfill(promise, value) { 336 if (promise._state !== PENDING) { 337 return; 338 } 339 340 promise._result = value; 341 promise._state = FULFILLED; 342 343 if (promise._subscribers.length !== 0) { 344 asap(publish, promise); 345 } 346} 347 348function reject(promise, reason) { 349 if (promise._state !== PENDING) { 350 return; 351 } 352 promise._state = REJECTED; 353 promise._result = reason; 354 355 asap(publishRejection, promise); 356} 357 358function subscribe(parent, child, onFulfillment, onRejection) { 359 var _subscribers = parent._subscribers; 360 var length = _subscribers.length; 361 362 363 parent._onerror = null; 364 365 _subscribers[length] = child; 366 _subscribers[length + FULFILLED] = onFulfillment; 367 _subscribers[length + REJECTED] = onRejection; 368 369 if (length === 0 && parent._state) { 370 asap(publish, parent); 371 } 372} 373 374function publish(promise) { 375 var subscribers = promise._subscribers; 376 var settled = promise._state; 377 378 if (subscribers.length === 0) { 379 return; 380 } 381 382 var child = void 0, 383 callback = void 0, 384 detail = promise._result; 385 386 for (var i = 0; i < subscribers.length; i += 3) { 387 child = subscribers[i]; 388 callback = subscribers[i + settled]; 389 390 if (child) { 391 invokeCallback(settled, child, callback, detail); 392 } else { 393 callback(detail); 394 } 395 } 396 397 promise._subscribers.length = 0; 398} 399 400function invokeCallback(settled, promise, callback, detail) { 401 var hasCallback = isFunction(callback), 402 value = void 0, 403 error = void 0, 404 succeeded = true; 405 406 if (hasCallback) { 407 try { 408 value = callback(detail); 409 } catch (e) { 410 succeeded = false; 411 error = e; 412 } 413 414 if (promise === value) { 415 reject(promise, cannotReturnOwn()); 416 return; 417 } 418 } else { 419 value = detail; 420 } 421 422 if (promise._state !== PENDING) { 423 // noop 424 } else if (hasCallback && succeeded) { 425 resolve(promise, value); 426 } else if (succeeded === false) { 427 reject(promise, error); 428 } else if (settled === FULFILLED) { 429 fulfill(promise, value); 430 } else if (settled === REJECTED) { 431 reject(promise, value); 432 } 433} 434 435function initializePromise(promise, resolver) { 436 try { 437 resolver(function resolvePromise(value) { 438 resolve(promise, value); 439 }, function rejectPromise(reason) { 440 reject(promise, reason); 441 }); 442 } catch (e) { 443 reject(promise, e); 444 } 445} 446 447var id = 0; 448function nextId() { 449 return id++; 450} 451 452function makePromise(promise) { 453 promise[PROMISE_ID] = id++; 454 promise._state = undefined; 455 promise._result = undefined; 456 promise._subscribers = []; 457} 458 459function validationError() { 460 return new Error('Array Methods must be provided an Array'); 461} 462 463var Enumerator = function () { 464 function Enumerator(Constructor, input) { 465 this._instanceConstructor = Constructor; 466 this.promise = new Constructor(noop); 467 468 if (!this.promise[PROMISE_ID]) { 469 makePromise(this.promise); 470 } 471 472 if (isArray(input)) { 473 this.length = input.length; 474 this._remaining = input.length; 475 476 this._result = new Array(this.length); 477 478 if (this.length === 0) { 479 fulfill(this.promise, this._result); 480 } else { 481 this.length = this.length || 0; 482 this._enumerate(input); 483 if (this._remaining === 0) { 484 fulfill(this.promise, this._result); 485 } 486 } 487 } else { 488 reject(this.promise, validationError()); 489 } 490 } 491 492 Enumerator.prototype._enumerate = function _enumerate(input) { 493 for (var i = 0; this._state === PENDING && i < input.length; i++) { 494 this._eachEntry(input[i], i); 495 } 496 }; 497 498 Enumerator.prototype._eachEntry = function _eachEntry(entry, i) { 499 var c = this._instanceConstructor; 500 var resolve$$1 = c.resolve; 501 502 503 if (resolve$$1 === resolve$1) { 504 var _then = void 0; 505 var error = void 0; 506 var didError = false; 507 try { 508 _then = entry.then; 509 } catch (e) { 510 didError = true; 511 error = e; 512 } 513 514 if (_then === then && entry._state !== PENDING) { 515 this._settledAt(entry._state, i, entry._result); 516 } else if (typeof _then !== 'function') { 517 this._remaining--; 518 this._result[i] = entry; 519 } else if (c === Promise$2
vendor: 9,193 bytes, lines 519-857
519) { 520 var promise = new c(noop); 521 if (didError) { 522 reject(promise, error); 523 } else { 524 handleMaybeThenable(promise, entry, _then); 525 } 526 this._willSettleAt(promise, i); 527 } else { 528 this._willSettleAt(new c(function (resolve$$1) { 529 return resolve$$1(entry); 530 }), i); 531 } 532 } else { 533 this._willSettleAt(resolve$$1(entry), i); 534 } 535 }; 536 537 Enumerator.prototype._settledAt = function _settledAt(state, i, value) { 538 var promise = this.promise; 539 540 541 if (promise._state === PENDING) { 542 this._remaining--; 543 544 if (state === REJECTED) { 545 reject(promise, value); 546 } else { 547 this._result[i] = value; 548 } 549 } 550 551 if (this._remaining === 0) { 552 fulfill(promise, this._result); 553 } 554 }; 555 556 Enumerator.prototype._willSettleAt = function _willSettleAt(promise, i) { 557 var enumerator = this; 558 559 subscribe(promise, undefined, function (value) { 560 return enumerator._settledAt(FULFILLED, i, value); 561 }, function (reason) { 562 return enumerator._settledAt(REJECTED, i, reason); 563 }); 564 }; 565 566 return Enumerator; 567}(); 568 569/** 570 `Promise.all` accepts an array of promises, and returns a new promise which 571 is fulfilled with an array of fulfillment values for the passed promises, or 572 rejected with the reason of the first passed promise to be rejected. It casts all 573 elements of the passed iterable to promises as it runs this algorithm. 574 575 Example: 576 577 ```javascript 578 let promise1 = resolve(1); 579 let promise2 = resolve(2); 580 let promise3 = resolve(3); 581 let promises = [ promise1, promise2, promise3 ]; 582 583 Promise.all(promises).then(function(array){ 584 // The array here would be [ 1, 2, 3 ]; 585 }); 586 ``` 587 588 If any of the `promises` given to `all` are rejected, the first promise 589 that is rejected will be given as an argument to the returned promises's 590 rejection handler. For example: 591 592 Example: 593 594 ```javascript 595 let promise1 = resolve(1); 596 let promise2 = reject(new Error("2")); 597 let promise3 = reject(new Error("3")); 598 let promises = [ promise1, promise2, promise3 ]; 599 600 Promise.all(promises).then(function(array){ 601 // Code here never runs because there are rejected promises! 602 }, function(error) { 603 // error.message === "2" 604 }); 605 ``` 606 607 @method all 608 @static 609 @param {Array} entries array of promises 610 @param {String} label optional string for labeling the promise. 611 Useful for tooling. 612 @return {Promise} promise that is fulfilled when all `promises` have been 613 fulfilled, or rejected if any of them become rejected. 614 @static 615*/ 616function all(entries) { 617 return new Enumerator(this, entries).promise; 618} 619 620/** 621 `Promise.race` returns a new promise which is settled in the same way as the 622 first passed promise to settle. 623 624 Example: 625 626 ```javascript 627 let promise1 = new Promise(function(resolve, reject){ 628 setTimeout(function(){ 629 resolve('promise 1'); 630 }, 200); 631 }); 632 633 let promise2 = new Promise(function(resolve, reject){ 634 setTimeout(function(){ 635 resolve('promise 2'); 636 }, 100); 637 }); 638 639 Promise.race([promise1, promise2]).then(function(result){ 640 // result === 'promise 2' because it was resolved before promise1 641 // was resolved. 642 }); 643 ``` 644 645 `Promise.race` is deterministic in that only the state of the first 646 settled promise matters. For example, even if other promises given to the 647 `promises` array argument are resolved, but the first settled promise has 648 become rejected before the other promises became fulfilled, the returned 649 promise will become rejected: 650 651 ```javascript 652 let promise1 = new Promise(function(resolve, reject){ 653 setTimeout(function(){ 654 resolve('promise 1'); 655 }, 200); 656 }); 657 658 let promise2 = new Promise(function(resolve, reject){ 659 setTimeout(function(){ 660 reject(new Error('promise 2')); 661 }, 100); 662 }); 663 664 Promise.race([promise1, promise2]).then(function(result){ 665 // Code here never runs 666 }, function(reason){ 667 // reason.message === 'promise 2' because promise 2 became rejected before 668 // promise 1 became fulfilled 669 }); 670 ``` 671 672 An example real-world use case is implementing timeouts: 673 674 ```javascript 675 Promise.race([ajax('foo.json'), timeout(5000)]) 676 ``` 677 678 @method race 679 @static 680 @param {Array} promises array of promises to observe 681 Useful for tooling. 682 @return {Promise} a promise which settles in the same way as the first passed 683 promise to settle. 684*/ 685function race(entries) { 686 /*jshint validthis:true */ 687 var Constructor = this; 688 689 if (!isArray(entries)) { 690 return new Constructor(function (_, reject) { 691 return reject(new TypeError('You must pass an array to race.')); 692 }); 693 } else { 694 return new Constructor(function (resolve, reject) { 695 var length = entries.length; 696 for (var i = 0; i < length; i++) { 697 Constructor.resolve(entries[i]).then(resolve, reject); 698 } 699 }); 700 } 701} 702 703/** 704 `Promise.reject` returns a promise rejected with the passed `reason`. 705 It is shorthand for the following: 706 707 ```javascript 708 let promise = new Promise(function(resolve, reject){ 709 reject(new Error('WHOOPS')); 710 }); 711 712 promise.then(function(value){ 713 // Code here doesn't run because the promise is rejected! 714 }, function(reason){ 715 // reason.message === 'WHOOPS' 716 }); 717 ``` 718 719 Instead of writing the above, your code now simply becomes the following: 720 721 ```javascript 722 let promise = Promise.reject(new Error('WHOOPS')); 723 724 promise.then(function(value){ 725 // Code here doesn't run because the promise is rejected! 726 }, function(reason){ 727 // reason.message === 'WHOOPS' 728 }); 729 ``` 730 731 @method reject 732 @static 733 @param {Any} reason value that the returned promise will be rejected with. 734 Useful for tooling. 735 @return {Promise} a promise rejected with the given `reason`. 736*/ 737function reject$1(reason) { 738 /*jshint validthis:true */ 739 var Constructor = this; 740 var promise = new Constructor(noop); 741 reject(promise, reason); 742 return promise; 743} 744 745function needsResolver() { 746 throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); 747} 748 749function needsNew() { 750 throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); 751} 752 753/** 754 Promise objects represent the eventual result of an asynchronous operation. The 755 primary way of interacting with a promise is through its `then` method, which 756 registers callbacks to receive either a promise's eventual value or the reason 757 why the promise cannot be fulfilled. 758 759 Terminology 760 ----------- 761 762 - `promise` is an object or function with a `then` method whose behavior conforms to this specification. 763 - `thenable` is an object or function that defines a `then` method. 764 - `value` is any legal JavaScript value (including undefined, a thenable, or a promise). 765 - `exception` is a value that is thrown using the throw statement. 766 - `reason` is a value that indicates why a promise was rejected. 767 - `settled` the final resting state of a promise, fulfilled or rejected. 768 769 A promise can be in one of three states: pending, fulfilled, or rejected. 770 771 Promises that are fulfilled have a fulfillment value and are in the fulfilled 772 state. Promises that are rejected have a rejection reason and are in the 773 rejected state. A fulfillment value is never a thenable. 774 775 Promises can also be said to *resolve* a value. If this value is also a 776 promise, then the original promise's settled state will match the value's 777 settled state. So a promise that *resolves* a promise that rejects will 778 itself reject, and a promise that *resolves* a promise that fulfills will 779 itself fulfill. 780 781 782 Basic Usage: 783 ------------ 784 785 ```js 786 let promise = new Promise(function(resolve, reject) { 787 // on success 788 resolve(value); 789 790 // on failure 791 reject(reason); 792 }); 793 794 promise.then(function(value) { 795 // on fulfillment 796 }, function(reason) { 797 // on rejection 798 }); 799 ``` 800 801 Advanced Usage: 802 --------------- 803 804 Promises shine when abstracting away asynchronous interactions such as 805 `XMLHttpRequest`s. 806 807 ```js 808 function getJSON(url) { 809 return new Promise(function(resolve, reject){ 810 let xhr = new XMLHttpRequest(); 811 812 xhr.open('GET', url); 813 xhr.onreadystatechange = handler; 814 xhr.responseType = 'json'; 815 xhr.setRequestHeader('Accept', 'application/json'); 816 xhr.send(); 817 818 function handler() { 819 if (this.readyState === this.DONE) { 820 if (this.status === 200) { 821 resolve(this.response); 822 } else { 823 reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']')); 824 } 825 } 826 }; 827 }); 828 } 829 830 getJSON('/posts.json').then(function(json) { 831 // on fulfillment 832 }, function(reason) { 833 // on rejection 834 }); 835 ``` 836 837 Unlike callbacks, promises are great composable primitives. 838 839 ```js 840 Promise.all([ 841 getJSON('/posts'), 842 getJSON('/comments') 843 ]).then(function(values){ 844 values[0] // => postsJSON 845 values[1] // => commentsJSON 846 847 return values; 848 }); 849 ``` 850 851 @class Promise 852 @param {Function} resolver 853 Useful for tooling. 854 @constructor 855*/ 856 857var Promise$
8572 = function () { 858 function Promise(resolver) { 859 this[PROMISE_ID] = nextId(); 860 this._result = this._state = undefined; 861 this._subscribers = []; 862 863 if (noop !== resolver) { 864 typeof resolver !== 'function' && needsResolver(); 865 this instanceof Promise ? initializePromise(this, resolver) : needsNew(); 866 } 867 } 868 869 /** 870 The primary way of interacting with a promise is through its `then` method, 871 which registers callbacks to receive either a promise's eventual value or the 872 reason why the promise cannot be fulfilled. 873 ```js 874 findUser().then(function(user){ 875 // user is available 876 }, function(reason){ 877 // user is unavailable, and you are given the reason why 878 }); 879 ``` 880 Chaining 881 -------- 882 The return value of `then` is itself a promise. This second, 'downstream' 883 promise is resolved with the return value of the first promise's fulfillment 884 or rejection handler, or rejected if the handler throws an exception. 885 ```js 886 findUser().then(function (user) { 887 return user.name; 888 }, function (reason) { 889 return 'default name'; 890 }).then(function (userName) { 891 // If `findUser` fulfilled, `userName` will be the user's name, otherwise it 892 // will be `'default name'` 893 }); 894 findUser().then(function (user) { 895 throw new Error('Found user, but still unhappy'); 896 }, function (reason) { 897 throw new Error('`findUser` rejected and we're unhappy'); 898 }).then(function (value) { 899 // never reached 900 }, function (reason) { 901 // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'. 902 // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'. 903 }); 904 ``` 905 If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream. 906 ```js 907 findUser().then(function (user) { 908 throw new PedagogicalException('Upstream error'); 909 }).then(function (value) { 910 // never reached 911 }).then(function (value) { 912 // never reached 913 }, function (reason) { 914 // The `PedgagocialException` is propagated all the way down to here 915 }); 916 ``` 917 Assimilation 918 ------------ 919 Sometimes the value you want to propagate to a downstream promise can only be 920 retrieved asynchronously. This can be achieved by returning a promise in the 921 fulfillment or rejection handler. The downstream promise will then be pending 922 until the returned promise is settled. This is called *assimilation*. 923 ```js 924 findUser().then(function (user) { 925 return findCommentsByAuthor(user); 926 }).then(function (comments) { 927 // The user's comments are now available 928 }); 929 ``` 930 If the assimliated promise rejects, then the downstream promise will also reject. 931 ```js 932 findUser().then(function (user) { 933 return findCommentsByAuthor(user); 934 }).then(function (comments) { 935 // If `findCommentsByAuthor` fulfills, we'll have the value here 936 }, function (reason) { 937 // If `findCommentsByAuthor` rejects, we'll have the reason here 938 }); 939 ```
940 Simple Example 941 -------------- 942 Synchronous Example 943 ```javascript 944 let result; 945 try { 946 result = findResult(); 947 // success 948 } catch(reason) { 949 // failure 950 } 951 ``` 952 Errback Example 953 ```js 954 findResult(function(result, err){ 955 if (err) { 956 // failure 957 } else { 958 // success 959 } 960 }); 961 ``` 962 Promise Example; 963 ```javascript 964 findResult().then(function(result){ 965 // success 966 }, function(reason){ 967 // failure 968 }); 969 ``` 970 Advanced Example 971 -------------- 972 Synchronous Example 973 ```javascript 974 let author, books; 975 try { 976 author = findAuthor(); 977 books = findBooksByAuthor(author); 978 // success 979 } catch(reason) { 980 // failure 981 } 982 ``` 983 Errback Example 984 ```js 985 function foundBooks(books) { 986 } 987 function failure(reason) { 988 } 989 findAuthor(function(author, err){ 990 if (err) { 991 failure(err); 992 // failure 993 } else { 994 try { 995 findBoooksByAuthor(author, function(books, err) { 996 if (err) { 997 failure(err); 998 } else { 999 try { 1000 foundBooks(books); 1001 } catch(reason) { 1002 failure(reason); 1003 } 1004 } 1005 }); 1006 } catch(error) { 1007 failure(err); 1008 } 1009 // success 1010 } 1011 }); 1012 ``` 1013 Promise Example; 1014 ```javascript 1015 findAuthor(). 1016 then(findBooksByAuthor). 1017 then(function(books){ 1018 // found books 1019 }).catch(function(reason){ 1020 // something went wrong 1021 }); 1022 ``` 1023 @method then 1024 @param {Function} onFulfilled 1025 @param {Function} onRejected 1026 Useful for tooling. 1027 @return {Promise} 1028 */ 1029 1030 /** 1031 `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same 1032 as the catch block of a try/catch statement. 1033 ```js 1034 function findAuthor(){ 1035 throw new Error('couldn't find that author'); 1036 } 1037 // synchronous 1038 try { 1039 findAuthor(); 1040 } catch(reason) { 1041 // something went wrong 1042 } 1043 // async with promises 1044 findAuthor().catch(function(reason){ 1045 // something went wrong 1046 }); 1047 ``` 1048 @method catch 1049 @param {Function} onRejection 1050 Useful for tooling. 1051 @return {Promise} 1052 */ 1053 1054 1055 Promise.prototype.catch = function _catch(onRejection) { 1056 return this.then(null, onRejection); 1057 }; 1058 1059 /** 1060 `finally` will be invoked regardless of the promise's fate just as native 1061 try/catch/finally behaves 1062 1063 Synchronous example: 1064 1065 ```js 1066 findAuthor() { 1067 if (Math.random() > 0.5) { 1068 throw new Error(); 1069 } 1070 return new Author(); 1071 } 1072 1073 try { 1074 return findAuthor(); // succeed or fail 1075 } catch(error) { 1076 return findOtherAuther(); 1077 } finally { 1078 // always runs 1079 // doesn't affect the return value 1080 } 1081 ``` 1082 1083 Asynchronous example: 1084 1085 ```js 1086 findAuthor().catch(function(reason){ 1087 return findOtherAuther(); 1088 }).finally(function(){ 1089 // author was either found, or not 1090 }); 1091 ``` 1092 1093 @method finally 1094 @param {Function} callback 1095 @return {Promise} 1096 */ 1097 1098 1099 Promise.prototype.finally = function _finally(callback) { 1100 var promise = this; 1101 var constructor = promise.constructor; 1102 1103 if (isFunction(callback)) { 1104 return promise.then(function (value) { 1105 return constructor.resolve(callback()).then(function () { 1106 return value; 1107 }); 1108 }, function (reason) { 1109 return constructor.resolve(callback()).then(function () { 1110 throw reason; 1111 }); 1112 }); 1113 } 1114 1115 return promise.then(callback, callback); 1116 }; 1117 1118 return Promise; 1119}(); 1120 1121Promise$2.prototype.then = then; 1122Promise$2.all = all; 1123Promise$2.race = race; 1124Promise$2.resolve = resolve$1; 1125Promise$2.reject = reject$1; 1126Promise$2._setScheduler = setScheduler; 1127Promise$2._setAsap = setAsap; 1128Promise$2._asap = asap; 1129 1130/*global self*/ 1131function polyfill() { 1132 var local = void 0; 1133 1134 if (typeof global !== 'undefined') { 1135 local = global; 1136 } else if (typeof self !== 'undefined') { 1137 local = self; 1138 } else { 1139 try { 1140 local = Function('return this')(); 1141 } catch (e) { 1142 throw new Error('polyfill failed because global object is unavailable in this environment'); 1143 } 1144 } 1145 1146 var P = local.Promise; 1147 1148 if (P) { 1149 var promiseToString = null; 1150 try { 1151 promiseToString = Object.prototype.toString.call(P.resolve()); 1152 } catch (e) { 1153 // silently ignored 1154 } 1155 1156 if (promiseToString === '[object Promise]' && !P.cast) { 1157 return; 1158 } 1159 } 1160 1161 local.Promise = Promise$2; 1162} 1163 1164// Strange compat.. 1165Promise$2.polyfill = polyfill; 1166Promise$2.Promise = Promise$2; 1167 1168Promise$2.polyfill(); 1169 1170return Promise$2; 1171 1172}))); 1173/* ======================================================================== 1174 * Bootstrap: collapse.js v3.3.7 1175 * http://getbootstrap.com/javascript/#collapse 1176 * ======================================================================== 1177 * Copyright 2011-2016 Twitter, Inc. 1178 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 1179 * ======================================================================== */ 1180
vendor: 12,140 bytes, lines 1181-1611
1181/* jshint latedef: false */ 1182 1183+function ($) { 1184 'use strict'; 1185 1186 // COLLAPSE PUBLIC CLASS DEFINITION 1187 // ================================ 1188 1189 var Collapse = function (element, options) { 1190 this.$element = $(element) 1191 this.options = $.extend({}, Collapse.DEFAULTS, options) 1192 this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + 1193 '[data-toggle="collapse"][data-target="#' + element.id + '"]') 1194 this.transitioning = null 1195 1196 if (this.options.parent) { 1197 this.$parent = this.getParent() 1198 } else { 1199 this.addAriaAndCollapsedClass(this.$element, this.$trigger) 1200 } 1201 1202 if (this.options.toggle) this.toggle() 1203 } 1204 1205 Collapse.VERSION = '3.3.7' 1206 1207 Collapse.TRANSITION_DURATION = 350 1208 1209 Collapse.DEFAULTS = { 1210 toggle: true 1211 } 1212 1213 Collapse.prototype.dimension = function () { 1214 var hasWidth = this.$element.hasClass('width') 1215 return hasWidth ? 'width' : 'height' 1216 } 1217 1218 Collapse.prototype.show = function () { 1219 if (this.transitioning || this.$element.hasClass('in')) return 1220 1221 var activesData 1222 var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') 1223 1224 if (actives && actives.length) { 1225 activesData = actives.data('bs.collapse') 1226 if (activesData && activesData.transitioning) return 1227 } 1228 1229 var startEvent = $.Event('show.bs.collapse') 1230 this.$element.trigger(startEvent) 1231 if (startEvent.isDefaultPrevented()) return 1232 1233 if (actives && actives.length) { 1234 Plugin.call(actives, 'hide') 1235 activesData || actives.data('bs.collapse', null) 1236 } 1237 1238 var dimension = this.dimension() 1239 1240 this.$element 1241 .removeClass('collapse') 1242 .addClass('collapsing')[dimension](0) 1243 .attr('aria-expanded', true) 1244 1245 this.$trigger 1246 .removeClass('collapsed') 1247 .attr('aria-expanded', true) 1248 1249 this.transitioning = 1 1250 1251 var complete = function () { 1252 this.$element 1253 .removeClass('collapsing') 1254 .addClass('collapse in')[dimension]('') 1255 this.transitioning = 0 1256 this.$element 1257 .trigger('shown.bs.collapse') 1258 } 1259 1260 if (!$.support.transition) return complete.call(this) 1261 1262 var scrollSize = $.camelCase(['scroll', dimension].join('-')) 1263 1264 this.$element 1265 .one('bsTransitionEnd', $.proxy(complete, this)) 1266 .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) 1267 } 1268 1269 Collapse.prototype.hide = function () { 1270 if (this.transitioning || !this.$element.hasClass('in')) return 1271 1272 var startEvent = $.Event('hide.bs.collapse') 1273 this.$element.trigger(startEvent) 1274 if (startEvent.isDefaultPrevented()) return 1275 1276 var dimension = this.dimension() 1277 1278 this.$element[dimension](this.$element[dimension]())[0].offsetHeight 1279 1280 this.$element 1281 .addClass('collapsing') 1282 .removeClass('collapse in') 1283 .attr('aria-expanded', false) 1284 1285 this.$trigger 1286 .addClass('collapsed') 1287 .attr('aria-expanded', false) 1288 1289 this.transitioning = 1 1290 1291 var complete = function () { 1292 this.transitioning = 0 1293 this.$element 1294 .removeClass('collapsing') 1295 .addClass('collapse') 1296 .trigger('hidden.bs.collapse') 1297 } 1298 1299 if (!$.support.transition) return complete.call(this) 1300 1301 this.$element 1302 [dimension](0) 1303 .one('bsTransitionEnd', $.proxy(complete, this)) 1304 .emulateTransitionEnd(Collapse.TRANSITION_DURATION) 1305 } 1306 1307 Collapse.prototype.toggle = function () { 1308 this[this.$element.hasClass('in') ? 'hide' : 'show']() 1309 } 1310 1311 Collapse.prototype.getParent = function () { 1312 return $(this.options.parent) 1313 .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') 1314 .each($.proxy(function (i, element) { 1315 var $element = $(element) 1316 this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) 1317 }, this)) 1318 .end() 1319 } 1320 1321 Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { 1322 var isOpen = $element.hasClass('in') 1323 1324 $element.attr('aria-expanded', isOpen) 1325 $trigger 1326 .toggleClass('collapsed', !isOpen) 1327 .attr('aria-expanded', isOpen) 1328 } 1329 1330 function getTargetFromTrigger($trigger) { 1331 var href 1332 var target = $trigger.attr('data-target') 1333 || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 1334 1335 return $(target) 1336 } 1337 1338 1339 // COLLAPSE PLUGIN DEFINITION 1340 // ========================== 1341 1342 function Plugin(option) { 1343 return this.each(function () { 1344 var $this = $(this) 1345 var data = $this.data('bs.collapse') 1346 var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) 1347 1348 if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false 1349 if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) 1350 if (typeof option == 'string') data[option]() 1351 }) 1352 } 1353 1354 var old = $.fn.collapse 1355 1356 $.fn.collapse = Plugin 1357 $.fn.collapse.Constructor = Collapse 1358 1359 1360 // COLLAPSE NO CONFLICT 1361 // ==================== 1362 1363 $.fn.collapse.noConflict = function () { 1364 $.fn.collapse = old 1365 return this 1366 } 1367 1368 1369 // COLLAPSE DATA-API 1370 // ================= 1371 1372 $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { 1373 var $this = $(this) 1374 1375 if (!$this.attr('data-target')) e.preventDefault() 1376 1377 var $target = getTargetFromTrigger($this) 1378 var data = $target.data('bs.collapse') 1379 var option = data ? 'toggle' : $this.data() 1380 1381 Plugin.call($target, option) 1382 }) 1383 1384}(jQuery); 1385 1386/* ======================================================================== 1387 * Bootstrap: dropdown.js v3.3.7 1388 * http://getbootstrap.com/javascript/#dropdowns 1389 * ======================================================================== 1390 * Copyright 2011-2016 Twitter, Inc. 1391 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 1392 * ======================================================================== */ 1393 1394 1395+function ($) { 1396 'use strict'; 1397 1398 // DROPDOWN CLASS DEFINITION 1399 // ========================= 1400 1401 var backdrop = '.dropdown-backdrop' 1402 var toggle = '[data-toggle="dropdown"]' 1403 var Dropdown = function (element) { 1404 $(element).on('click.bs.dropdown', this.toggle) 1405 } 1406 1407 Dropdown.VERSION = '3.3.7' 1408 1409 function getParent($this) { 1410 var selector = $this.attr('data-target') 1411 1412 if (!selector) { 1413 selector = $this.attr('href') 1414 selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 1415 } 1416 1417 var $parent = selector && $(selector) 1418 1419 return $parent && $parent.length ? $parent : $this.parent() 1420 } 1421 1422 function clearMenus(e) { 1423 if (e && e.which === 3) return 1424 $(backdrop).remove() 1425 $(toggle).each(function () { 1426 var $this = $(this) 1427 var $parent = getParent($this) 1428 var relatedTarget = { relatedTarget: this } 1429 1430 if (!$parent.hasClass('open')) return 1431 1432 if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return 1433 1434 $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) 1435 1436 if (e.isDefaultPrevented()) return 1437 1438 $this.attr('aria-expanded', 'false') 1439 $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget)) 1440 }) 1441 } 1442 1443 Dropdown.prototype.toggle = function (e) { 1444 var $this = $(this) 1445 1446 if ($this.is('.disabled, :disabled')) return 1447 1448 var $parent = getParent($this) 1449 var isActive = $parent.hasClass('open') 1450 1451 clearMenus() 1452 1453 if (!isActive) { 1454 if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { 1455 // if mobile we use a backdrop because click events don't delegate 1456 $(document.createElement('div')) 1457 .addClass('dropdown-backdrop') 1458 .insertAfter($(this)) 1459 .on('click', clearMenus) 1460 } 1461 1462 var relatedTarget = { relatedTarget: this } 1463 $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget)) 1464 1465 if (e.isDefaultPrevented()) return 1466 1467 $this 1468 .trigger('focus') 1469 .attr('aria-expanded', 'true') 1470 1471 $parent 1472 .toggleClass('open') 1473 .trigger($.Event('shown.bs.dropdown', relatedTarget)) 1474 } 1475 1476 return false 1477 } 1478 1479 Dropdown.prototype.keydown = function (e) { 1480 if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return 1481 1482 var $this = $(this) 1483 1484 e.preventDefault() 1485 e.stopPropagation() 1486 1487 if ($this.is('.disabled, :disabled')) return 1488 1489 var $parent = getParent($this) 1490 var isActive = $parent.hasClass('open') 1491 1492 if (!isActive && e.which != 27 || isActive && e.which == 27) { 1493 if (e.which == 27) $parent.find(toggle).trigger('focus') 1494 return $this.trigger('click') 1495 } 1496 1497 var desc = ' li:not(.disabled):visible a' 1498 var $items = $parent.find('.dropdown-menu' + desc) 1499 1500 if (!$items.length) return 1501 1502 var index = $items.index(e.target) 1503 1504 if (e.which == 38 && index > 0) index-- // up 1505 if (e.which == 40 && index < $items.length - 1) index++ // down 1506 if (!~index) index = 0 1507 1508 $items.eq(index).trigger('focus') 1509 } 1510 1511 1512 // DROPDOWN PLUGIN DEFINITION 1513 // ========================== 1514 1515 function Plugin(option) { 1516 return this.each(function () { 1517 var $this = $(this) 1518 var data = $this.data('bs.dropdown') 1519 1520 if (!data) $this.data('bs.dropdown', (data = new Dropdown(this))) 1521 if (typeof option == 'string') data[option].call($this) 1522 }) 1523 } 1524 1525 var old = $.fn.dropdown 1526 1527 $.fn.dropdown = Plugin 1528 $.fn.dropdown.Constructor = Dropdown 1529 1530 1531 // DROPDOWN NO CONFLICT 1532 // ==================== 1533 1534 $.fn.dropdown.noConflict = function () { 1535 $.fn.dropdown = old 1536 return this 1537 } 1538 1539 1540 // APPLY TO STANDARD DROPDOWN ELEMENTS 1541 // =================================== 1542 1543 $(document) 1544 .on('click.bs.dropdown.data-api', clearMenus) 1545 .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) 1546 .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) 1547 .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) 1548 .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) 1549 1550}(jQuery); 1551 1552/* ======================================================================== 1553 * Bootstrap: transition.js v3.3.7 1554 * http://getbootstrap.com/javascript/#transitions 1555 * ======================================================================== 1556 * Copyright 2011-2016 Twitter, Inc. 1557 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 1558 * ======================================================================== */ 1559 1560 1561+function ($) { 1562 'use strict'; 1563 1564 // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) 1565 // ============================================================ 1566 1567 function transitionEnd() { 1568 var el = document.createElement('bootstrap') 1569 1570 var transEndEventNames = { 1571 WebkitTransition : 'webkitTransitionEnd', 1572 MozTransition : 'transitionend', 1573 OTransition : 'oTransitionEnd otransitionend', 1574 transition : 'transitionend' 1575 } 1576 1577 for (var name in transEndEventNames) { 1578 if (el.style[name] !== undefined) { 1579 return { end: transEndEventNames[name] } 1580 } 1581 } 1582 1583 return false // explicit for ie8 ( ._.) 1584 } 1585 1586 // http://blog.alexmaccaw.com/css-transitions 1587 $.fn.emulateTransitionEnd = function (duration) { 1588 var called = false 1589 var $el = this 1590 $(this).one('bsTransitionEnd', function () { called = true }) 1591 var callback = function () { if (!called) $($el).trigger($.support.transition.end) } 1592 setTimeout(callback, duration) 1593 return this 1594 } 1595 1596 $(function () { 1597 $.support.transition = transitionEnd() 1598 1599 if (!$.support.transition) return 1600 1601 $.event.special.bsTransitionEnd = { 1602 bindType: $.support.transition.end, 1603 delegateType: $.support.transition.end, 1604 handle: function (e) { 1605 if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments) 1606 } 1607 } 1608 }) 1609 1610}(jQuery); 1611
vendor: 12,637 bytes, lines 1612-1926
1612/** 1613 * @license 1614 * Lodash <https://lodash.com/> 1615 * Copyright OpenJS Foundation and other contributors <https://openjsf.org/> 1616 * Released under MIT license <https://lodash.com/license> 1617 * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE> 1618 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 1619 */ 1620;(function() { 1621 1622 /** Used as a safe reference for `undefined` in pre-ES5 environments. */ 1623 var undefined; 1624 1625 /** Used as the semantic version number. */ 1626 var VERSION = '4.17.21'; 1627 1628 /** Used as the size to enable large array optimizations. */ 1629 var LARGE_ARRAY_SIZE = 200; 1630 1631 /** Error message constants. */ 1632 var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.', 1633 FUNC_ERROR_TEXT = 'Expected a function', 1634 INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`'; 1635 1636 /** Used to stand-in for `undefined` hash values. */ 1637 var HASH_UNDEFINED = '__lodash_hash_undefined__'; 1638 1639 /** Used as the maximum memoize cache size. */ 1640 var MAX_MEMOIZE_SIZE = 500; 1641 1642 /** Used as the internal argument placeholder. */ 1643 var PLACEHOLDER = '__lodash_placeholder__'; 1644 1645 /** Used to compose bitmasks for cloning. */ 1646 var CLONE_DEEP_FLAG = 1, 1647 CLONE_FLAT_FLAG = 2, 1648 CLONE_SYMBOLS_FLAG = 4; 1649 1650 /** Used to compose bitmasks for value comparisons. */ 1651 var COMPARE_PARTIAL_FLAG = 1, 1652 COMPARE_UNORDERED_FLAG = 2; 1653 1654 /** Used to compose bitmasks for function metadata. */ 1655 var WRAP_BIND_FLAG = 1, 1656 WRAP_BIND_KEY_FLAG = 2, 1657 WRAP_CURRY_BOUND_FLAG = 4, 1658 WRAP_CURRY_FLAG = 8, 1659 WRAP_CURRY_RIGHT_FLAG = 16, 1660 WRAP_PARTIAL_FLAG = 32, 1661 WRAP_PARTIAL_RIGHT_FLAG = 64, 1662 WRAP_ARY_FLAG = 128, 1663 WRAP_REARG_FLAG = 256, 1664 WRAP_FLIP_FLAG = 512; 1665 1666 /** Used as default options for `_.truncate`. */ 1667 var DEFAULT_TRUNC_LENGTH = 30, 1668 DEFAULT_TRUNC_OMISSION = '...'; 1669 1670 /** Used to detect hot functions by number of calls within a span of milliseconds. */ 1671 var HOT_COUNT = 800, 1672 HOT_SPAN = 16; 1673 1674 /** Used to indicate the type of lazy iteratees. */ 1675 var LAZY_FILTER_FLAG = 1, 1676 LAZY_MAP_FLAG = 2, 1677 LAZY_WHILE_FLAG = 3; 1678 1679 /** Used as references for various `Number` constants. */ 1680 var INFINITY = 1 / 0, 1681 MAX_SAFE_INTEGER = 9007199254740991, 1682 MAX_INTEGER = 1.7976931348623157e+308, 1683 NAN = 0 / 0; 1684 1685 /** Used as references for the maximum length and index of an array. */ 1686 var MAX_ARRAY_LENGTH = 4294967295, 1687 MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, 1688 HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; 1689 1690 /** Used to associate wrap methods with their bit flags. */ 1691 var wrapFlags = [ 1692 ['ary', WRAP_ARY_FLAG], 1693 ['bind', WRAP_BIND_FLAG], 1694 ['bindKey', WRAP_BIND_KEY_FLAG], 1695 ['curry', WRAP_CURRY_FLAG], 1696 ['curryRight', WRAP_CURRY_RIGHT_FLAG], 1697 ['flip', WRAP_FLIP_FLAG], 1698 ['partial', WRAP_PARTIAL_FLAG], 1699 ['partialRight', WRAP_PARTIAL_RIGHT_FLAG], 1700 ['rearg', WRAP_REARG_FLAG] 1701 ]; 1702 1703 /** `Object#toString` result references. */ 1704 var argsTag = '[object Arguments]', 1705 arrayTag = '[object Array]', 1706 asyncTag = '[object AsyncFunction]', 1707 boolTag = '[object Boolean]', 1708 dateTag = '[object Date]', 1709 domExcTag = '[object DOMException]', 1710 errorTag = '[object Error]', 1711 funcTag = '[object Function]', 1712 genTag = '[object GeneratorFunction]', 1713 mapTag = '[object Map]', 1714 numberTag = '[object Number]', 1715 nullTag = '[object Null]', 1716 objectTag = '[object Object]', 1717 promiseTag = '[object Promise]', 1718 proxyTag = '[object Proxy]', 1719 regexpTag = '[object RegExp]', 1720 setTag = '[object Set]', 1721 stringTag = '[object String]', 1722 symbolTag = '[object Symbol]', 1723 undefinedTag = '[object Undefined]', 1724 weakMapTag = '[object WeakMap]', 1725 weakSetTag = '[object WeakSet]'; 1726 1727 var arrayBufferTag = '[object ArrayBuffer]', 1728 dataViewTag = '[object DataView]', 1729 float32Tag = '[object Float32Array]', 1730 float64Tag = '[object Float64Array]', 1731 int8Tag = '[object Int8Array]', 1732 int16Tag = '[object Int16Array]', 1733 int32Tag = '[object Int32Array]', 1734 uint8Tag = '[object Uint8Array]', 1735 uint8ClampedTag = '[object Uint8ClampedArray]', 1736 uint16Tag = '[object Uint16Array]', 1737 uint32Tag = '[object Uint32Array]'; 1738 1739 /** Used to match empty string literals in compiled template source. */ 1740 var reEmptyStringLeading = /\b__p \+= '';/g, 1741 reEmptyStringMiddle = /\b(__p \+=) '' \+/g, 1742 reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; 1743 1744 /** Used to match HTML entities and HTML characters. */ 1745 var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, 1746 reUnescapedHtml = /[&<>"']/g, 1747 reHasEscapedHtml = RegExp(reEscapedHtml.source), 1748 reHasUnescapedHtml = RegExp(reUnescapedHtml.source); 1749 1750 /** Used to match template delimiters. */ 1751 var reEscape = /<%-([\s\S]+?)%>/g, 1752 reEvaluate = /<%([\s\S]+?)%>/g, 1753 reInterpolate = /<%=([\s\S]+?)%>/g; 1754 1755 /** Used to match property names within property paths. */ 1756 var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, 1757 reIsPlainProp = /^\w*$/, 1758 rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; 1759 1760 /** 1761 * Used to match `RegExp` 1762 * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). 1763 */ 1764 var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, 1765 reHasRegExpChar = RegExp(reRegExpChar.source); 1766 1767 /** Used to match leading whitespace. */ 1768 var reTrimStart = /^\s+/; 1769 1770 /** Used to match a single whitespace character. */ 1771 var reWhitespace = /\s/; 1772 1773 /** Used to match wrap detail comments. */ 1774 var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, 1775 reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, 1776 reSplitDetails = /,? & /; 1777 1778 /** Used to match words composed of alphanumeric characters. */ 1779 var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; 1780 1781 /** 1782 * Used to validate the `validate` option in `_.template` variable. 1783 * 1784 * Forbids characters which could potentially change the meaning of the function argument definition: 1785 * - "()," (modification of function parameters) 1786 * - "=" (default value) 1787 * - "[]{}" (destructuring of function parameters) 1788 * - "/" (beginning of a comment) 1789 * - whitespace 1790 */ 1791 var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/; 1792 1793 /** Used to match backslashes in property paths. */ 1794 var reEscapeChar = /\\(\\)?/g; 1795 1796 /** 1797 * Used to match 1798 * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components). 1799 */ 1800 var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; 1801 1802 /** Used to match `RegExp` flags from their coerced string values. */ 1803 var reFlags = /\w*$/; 1804 1805 /** Used to detect bad signed hexadecimal string values. */ 1806 var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; 1807 1808 /** Used to detect binary string values. */ 1809 var reIsBinary = /^0b[01]+$/i; 1810 1811 /** Used to detect host constructors (Safari). */ 1812 var reIsHostCtor = /^\[object .+?Constructor\]$/; 1813 1814 /** Used to detect octal string values. */ 1815 var reIsOctal = /^0o[0-7]+$/i; 1816 1817 /** Used to detect unsigned integer values. */ 1818 var reIsUint = /^(?:0|[1-9]\d*)$/; 1819 1820 /** Used to match Latin Unicode letters (excluding mathematical operators). */ 1821 var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; 1822 1823 /** Used to ensure capturing order of template delimiters. */ 1824 var reNoMatch = /($^)/; 1825 1826 /** Used to match unescaped characters in compiled string literals. */ 1827 var reUnescapedString = /['\n\r\u2028\u2029\\]/g; 1828 1829 /** Used to compose unicode character classes. */ 1830 var rsAstralRange = '\\ud800-\\udfff', 1831 rsComboMarksRange = '\\u0300-\\u036f', 1832 reComboHalfMarksRange = '\\ufe20-\\ufe2f', 1833 rsComboSymbolsRange = '\\u20d0-\\u20ff', 1834 rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, 1835 rsDingbatRange = '\\u2700-\\u27bf', 1836 rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', 1837 rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', 1838 rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', 1839 rsPunctuationRange = '\\u2000-\\u206f', 1840 rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', 1841 rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', 1842 rsVarRange = '\\ufe0e\\ufe0f', 1843 rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; 1844 1845 /** Used to compose unicode capture groups. */ 1846 var rsApos = "['\u2019]", 1847 rsAstral = '[' + rsAstralRange + ']', 1848 rsBreak = '[' + rsBreakRange + ']', 1849 rsCombo = '[' + rsComboRange + ']', 1850 rsDigits = '\\d+', 1851 rsDingbat = '[' + rsDingbatRange + ']', 1852 rsLower = '[' + rsLowerRange + ']', 1853 rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', 1854 rsFitz = '\\ud83c[\\udffb-\\udfff]', 1855 rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', 1856 rsNonAstral = '[^' + rsAstralRange + ']', 1857 rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', 1858 rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', 1859 rsUpper = '[' + rsUpperRange + ']', 1860 rsZWJ = '\\u200d'; 1861 1862 /** Used to compose unicode regexes. */ 1863 var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')', 1864 rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')', 1865 rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?', 1866 rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?', 1867 reOptMod = rsModifier + '?', 1868 rsOptVar = '[' + rsVarRange + ']?', 1869 rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', 1870 rsOrdLower = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])', 1871 rsOrdUpper = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])', 1872 rsSeq = rsOptVar + reOptMod + rsOptJoin, 1873 rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq, 1874 rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; 1875 1876 /** Used to match apostrophes. */ 1877 var reApos = RegExp(rsApos, 'g'); 1878 1879 /** 1880 * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and 1881 * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). 1882 */ 1883 var reComboMark = RegExp(rsCombo, 'g'); 1884 1885 /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ 1886 var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); 1887 1888 /** Used to match complex or compound words. */ 1889 var reUnicodeWord = RegExp([ 1890 rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', 1891 rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')', 1892 rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower, 1893 rsUpper + '+' + rsOptContrUpper, 1894 rsOrdUpper, 1895 rsOrdLower, 1896 rsDigits, 1897 rsEmoji 1898 ].join('|'), 'g'); 1899 1900 /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ 1901 var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); 1902 1903 /** Used to detect strings that need a more robust regexp to match words. */ 1904 var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; 1905 1906 /** Used to assign default `context` object properties. */ 1907 var contextProps = [ 1908 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array', 1909 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object', 1910 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array', 1911 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', 1912 '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout' 1913 ]; 1914 1915 /** Used to make template sourceURLs easier to identify. */ 1916 var templateCounter = -1; 1917 1918 /** Used to identify `toStringTag` values of typed arrays. */ 1919 var typedArrayTags = {}; 1920 typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = 1921 typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = 1922 typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = 1923 typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = 1924 typedArrayTags[uint32Tag] = true; 1925 typedArrayTags[argsTag] = typedArrayTags[arrayTag] = 1926 typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
vendor: 5,923 bytes, lines 1927-2061
1927 typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = 1928 typedArrayTags[errorTag] = typedArrayTags[funcTag] = 1929 typedArrayTags[mapTag] = typedArrayTags[numberTag] = 1930 typedArrayTags[objectTag] = typedArrayTags[regexpTag] = 1931 typedArrayTags[setTag] = typedArrayTags[stringTag] = 1932 typedArrayTags[weakMapTag] = false; 1933 1934 /** Used to identify `toStringTag` values supported by `_.clone`. */ 1935 var cloneableTags = {}; 1936 cloneableTags[argsTag] = cloneableTags[arrayTag] = 1937 cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = 1938 cloneableTags[boolTag] = cloneableTags[dateTag] = 1939 cloneableTags[float32Tag] = cloneableTags[float64Tag] = 1940 cloneableTags[int8Tag] = cloneableTags[int16Tag] = 1941 cloneableTags[int32Tag] = cloneableTags[mapTag] = 1942 cloneableTags[numberTag] = cloneableTags[objectTag] = 1943 cloneableTags[regexpTag] = cloneableTags[setTag] = 1944 cloneableTags[stringTag] = cloneableTags[symbolTag] = 1945 cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = 1946 cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; 1947 cloneableTags[errorTag] = cloneableTags[funcTag] = 1948 cloneableTags[weakMapTag] = false; 1949 1950 /** Used to map Latin Unicode letters to basic Latin letters. */ 1951 var deburredLetters = { 1952 // Latin-1 Supplement block. 1953 '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', 1954 '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', 1955 '\xc7': 'C', '\xe7': 'c', 1956 '\xd0': 'D', '\xf0': 'd', 1957 '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', 1958 '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', 1959 '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', 1960 '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', 1961 '\xd1': 'N', '\xf1': 'n', 1962 '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', 1963 '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', 1964 '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', 1965 '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', 1966 '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', 1967 '\xc6': 'Ae', '\xe6': 'ae', 1968 '\xde': 'Th', '\xfe': 'th', 1969 '\xdf': 'ss', 1970 // Latin Extended-A block. 1971 '\u0100': 'A', '\u0102': 'A', '\u0104': 'A', 1972 '\u0101': 'a', '\u0103': 'a', '\u0105': 'a', 1973 '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C', 1974 '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c', 1975 '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd', 1976 '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E', 1977 '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e', 1978 '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G', 1979 '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g', 1980 '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h', 1981 '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I', 1982 '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i', 1983 '\u0134': 'J', '\u0135': 'j', 1984 '\u0136': 'K', '\u0137': 'k', '\u0138': 'k', 1985 '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L', 1986 '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l', 1987 '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N', 1988 '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n', 1989 '\u014c': 'O', '\u014e': 'O', '\u0150': 'O', 1990 '\u014d': 'o', '\u014f': 'o', '\u0151': 'o', 1991 '\u0154': 'R', '\u0156': 'R', '\u0158': 'R', 1992 '\u0155': 'r', '\u0157': 'r', '\u0159': 'r', 1993 '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S', 1994 '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's', 1995 '\u0162': 'T', '\u0164': 'T', '\u0166': 'T', 1996 '\u0163': 't', '\u0165': 't', '\u0167': 't', 1997 '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U', 1998 '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u', 1999 '\u0174': 'W', '\u0175': 'w', 2000 '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y', 2001 '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z', 2002 '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', 2003 '\u0132': 'IJ', '\u0133': 'ij', 2004 '\u0152': 'Oe', '\u0153': 'oe', 2005 '\u0149': "'n", '\u017f': 's' 2006 }; 2007 2008 /** Used to map characters to HTML entities. */ 2009 var htmlEscapes = { 2010 '&': '&', 2011 '<': '<', 2012 '>': '>', 2013 '"': '"', 2014 "'": ''' 2015 }; 2016 2017 /** Used to map HTML entities to characters. */ 2018 var htmlUnescapes = { 2019 '&': '&', 2020 '<': '<', 2021 '>': '>', 2022 '"': '"', 2023 ''': "'" 2024 }; 2025 2026 /** Used to escape characters for inclusion in compiled string literals. */ 2027 var stringEscapes = { 2028 '\\': '\\', 2029 "'": "'", 2030 '\n': 'n', 2031 '\r': 'r', 2032 '\u2028': 'u2028', 2033 '\u2029': 'u2029' 2034 }; 2035 2036 /** Built-in method references without a dependency on `root`. */ 2037 var freeParseFloat = parseFloat, 2038 freeParseInt = parseInt; 2039 2040 /** Detect free variable `global` from Node.js. */ 2041 var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; 2042 2043 /** Detect free variable `self`. */ 2044 var freeSelf = typeof self == 'object' && self && self.Object === Object && self; 2045 2046 /** Used as a reference to the global object. */ 2047 var root = freeGlobal || freeSelf || Function('return this')(); 2048 2049 /** Detect free variable `exports`. */ 2050 var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; 2051 2052 /** Detect free variable `module`. */ 2053 var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; 2054 2055 /** Detect the popular CommonJS extension `module.exports`. */ 2056 var moduleExports = freeModule && freeModule.exports === freeExports; 2057 2058 /** Detect free variable `process` from Node.js. */ 2059 var freeProcess = moduleExports && freeGlobal.process; 2060 2061 /** Used to access faster Node.js helpers. */
vendor: 8,860 bytes, lines 2062-2355
2062 var nodeUtil = (function() { 2063 try { 2064 // Use `util.types` for Node.js 10+. 2065 var types = freeModule && freeModule.require && freeModule.require('util').types; 2066 2067 if (types) { 2068 return types; 2069 } 2070 2071 // Legacy `process.binding('util')` for Node.js < 10. 2072 return freeProcess && freeProcess.binding && freeProcess.binding('util'); 2073 } catch (e) {} 2074 }()); 2075 2076 /* Node.js helper references. */ 2077 var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer, 2078 nodeIsDate = nodeUtil && nodeUtil.isDate, 2079 nodeIsMap = nodeUtil && nodeUtil.isMap, 2080 nodeIsRegExp = nodeUtil && nodeUtil.isRegExp, 2081 nodeIsSet = nodeUtil && nodeUtil.isSet, 2082 nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; 2083 2084 /*--------------------------------------------------------------------------*/ 2085 2086 /** 2087 * A faster alternative to `Function#apply`, this function invokes `func` 2088 * with the `this` binding of `thisArg` and the arguments of `args`. 2089 * 2090 * @private 2091 * @param {Function} func The function to invoke. 2092 * @param {*} thisArg The `this` binding of `func`. 2093 * @param {Array} args The arguments to invoke `func` with. 2094 * @returns {*} Returns the result of `func`. 2095 */ 2096 function apply(func, thisArg, args) { 2097 switch (args.length) { 2098 case 0: return func.call(thisArg); 2099 case 1: return func.call(thisArg, args[0]); 2100 case 2: return func.call(thisArg, args[0], args[1]); 2101 case 3: return func.call(thisArg, args[0], args[1], args[2]); 2102 } 2103 return func.apply(thisArg, args); 2104 } 2105 2106 /** 2107 * A specialized version of `baseAggregator` for arrays. 2108 * 2109 * @private 2110 * @param {Array} [array] The array to iterate over. 2111 * @param {Function} setter The function to set `accumulator` values. 2112 * @param {Function} iteratee The iteratee to transform keys. 2113 * @param {Object} accumulator The initial aggregated object. 2114 * @returns {Function} Returns `accumulator`. 2115 */ 2116 function arrayAggregator(array, setter, iteratee, accumulator) { 2117 var index = -1, 2118 length = array == null ? 0 : array.length; 2119 2120 while (++index < length) { 2121 var value = array[index]; 2122 setter(accumulator, value, iteratee(value), array); 2123 } 2124 return accumulator; 2125 } 2126 2127 /** 2128 * A specialized version of `_.forEach` for arrays without support for 2129 * iteratee shorthands. 2130 * 2131 * @private 2132 * @param {Array} [array] The array to iterate over. 2133 * @param {Function} iteratee The function invoked per iteration. 2134 * @returns {Array} Returns `array`. 2135 */ 2136 function arrayEach(array, iteratee) { 2137 var index = -1, 2138 length = array == null ? 0 : array.length; 2139 2140 while (++index < length) { 2141 if (iteratee(array[index], index, array) === false) { 2142 break; 2143 } 2144 } 2145 return array; 2146 } 2147 2148 /** 2149 * A specialized version of `_.forEachRight` for arrays without support for 2150 * iteratee shorthands. 2151 * 2152 * @private 2153 * @param {Array} [array] The array to iterate over. 2154 * @param {Function} iteratee The function invoked per iteration. 2155 * @returns {Array} Returns `array`. 2156 */ 2157 function arrayEachRight(array, iteratee) { 2158 var length = array == null ? 0 : array.length; 2159 2160 while (length--) { 2161 if (iteratee(array[length], length, array) === false) { 2162 break; 2163 } 2164 } 2165 return array; 2166 } 2167 2168 /** 2169 * A specialized version of `_.every` for arrays without support for 2170 * iteratee shorthands. 2171 * 2172 * @private 2173 * @param {Array} [array] The array to iterate over. 2174 * @param {Function} predicate The function invoked per iteration. 2175 * @returns {boolean} Returns `true` if all elements pass the predicate check, 2176 * else `false`. 2177 */ 2178 function arrayEvery(array, predicate) { 2179 var index = -1, 2180 length = array == null ? 0 : array.length; 2181 2182 while (++index < length) { 2183 if (!predicate(array[index], index, array)) { 2184 return false; 2185 } 2186 } 2187 return true; 2188 } 2189 2190 /** 2191 * A specialized version of `_.filter` for arrays without support for 2192 * iteratee shorthands. 2193 * 2194 * @private 2195 * @param {Array} [array] The array to iterate over. 2196 * @param {Function} predicate The function invoked per iteration. 2197 * @returns {Array} Returns the new filtered array. 2198 */ 2199 function arrayFilter(array, predicate) { 2200 var index = -1, 2201 length = array == null ? 0 : array.length, 2202 resIndex = 0, 2203 result = []; 2204 2205 while (++index < length) { 2206 var value = array[index]; 2207 if (predicate(value, index, array)) { 2208 result[resIndex++] = value; 2209 } 2210 } 2211 return result; 2212 } 2213 2214 /** 2215 * A specialized version of `_.includes` for arrays without support for 2216 * specifying an index to search from. 2217 * 2218 * @private 2219 * @param {Array} [array] The array to inspect. 2220 * @param {*} target The value to search for. 2221 * @returns {boolean} Returns `true` if `target` is found, else `false`. 2222 */ 2223 function arrayIncludes(array, value) { 2224 var length = array == null ? 0 : array.length; 2225 return !!length && baseIndexOf(array, value, 0) > -1; 2226 } 2227 2228 /** 2229 * This function is like `arrayIncludes` except that it accepts a comparator. 2230 * 2231 * @private 2232 * @param {Array} [array] The array to inspect. 2233 * @param {*} target The value to search for. 2234 * @param {Function} comparator The comparator invoked per element. 2235 * @returns {boolean} Returns `true` if `target` is found, else `false`. 2236 */ 2237 function arrayIncludesWith(array, value, comparator) { 2238 var index = -1, 2239 length = array == null ? 0 : array.length; 2240 2241 while (++index < length) { 2242 if (comparator(value, array[index])) { 2243 return true; 2244 } 2245 } 2246 return false; 2247 } 2248 2249 /** 2250 * A specialized version of `_.map` for arrays without support for iteratee 2251 * shorthands. 2252 * 2253 * @private 2254 * @param {Array} [array] The array to iterate over. 2255 * @param {Function} iteratee The function invoked per iteration. 2256 * @returns {Array} Returns the new mapped array. 2257 */ 2258 function arrayMap(array, iteratee) { 2259 var index = -1, 2260 length = array == null ? 0 : array.length, 2261 result = Array(length); 2262 2263 while (++index < length) { 2264 result[index] = iteratee(array[index], index, array); 2265 } 2266 return result; 2267 } 2268 2269 /** 2270 * Appends the elements of `values` to `array`. 2271 * 2272 * @private 2273 * @param {Array} array The array to modify. 2274 * @param {Array} values The values to append. 2275 * @returns {Array} Returns `array`. 2276 */ 2277 function arrayPush(array, values) { 2278 var index = -1, 2279 length = values.length, 2280 offset = array.length; 2281 2282 while (++index < length) { 2283 array[offset + index] = values[index]; 2284 } 2285 return array; 2286 } 2287 2288 /** 2289 * A specialized version of `_.reduce` for arrays without support for 2290 * iteratee shorthands. 2291 * 2292 * @private 2293 * @param {Array} [array] The array to iterate over. 2294 * @param {Function} iteratee The function invoked per iteration. 2295 * @param {*} [accumulator] The initial value. 2296 * @param {boolean} [initAccum] Specify using the first element of `array` as 2297 * the initial value. 2298 * @returns {*} Returns the accumulated value. 2299 */ 2300 function arrayReduce(array, iteratee, accumulator, initAccum) { 2301 var index = -1, 2302 length = array == null ? 0 : array.length; 2303 2304 if (initAccum && length) { 2305 accumulator = array[++index]; 2306 } 2307 while (++index < length) { 2308 accumulator = iteratee(accumulator, array[index], index, array); 2309 } 2310 return accumulator; 2311 } 2312 2313 /** 2314 * A specialized version of `_.reduceRight` for arrays without support for 2315 * iteratee shorthands. 2316 * 2317 * @private 2318 * @param {Array} [array] The array to iterate over. 2319 * @param {Function} iteratee The function invoked per iteration. 2320 * @param {*} [accumulator] The initial value. 2321 * @param {boolean} [initAccum] Specify using the last element of `array` as 2322 * the initial value. 2323 * @returns {*} Returns the accumulated value. 2324 */ 2325 function arrayReduceRight(array, iteratee, accumulator, initAccum) { 2326 var length = array == null ? 0 : array.length; 2327 if (initAccum && length) { 2328 accumulator = array[--length]; 2329 } 2330 while (length--) { 2331 accumulator = iteratee(accumulator, array[length], length, array); 2332 } 2333 return accumulator; 2334 } 2335 2336 /** 2337 * A specialized version of `_.some` for arrays without support for iteratee 2338 * shorthands. 2339 * 2340 * @private 2341 * @param {Array} [array] The array to iterate over. 2342 * @param {Function} predicate The function invoked per iteration. 2343 * @returns {boolean} Returns `true` if any element passes the predicate check, 2344 * else `false`. 2345 */ 2346 function arraySome(array, predicate) { 2347 var index = -1, 2348 length = array == null ? 0 : array.length; 2349 2350 while (++index < length) { 2351 if (predicate(array[index], index, array)) { 2352 return true; 2353 } 2354 } 2355 return false;
vendor: 12,899 bytes, lines 2356-2793
2356 } 2357 2358 /** 2359 * Gets the size of an ASCII `string`. 2360 * 2361 * @private 2362 * @param {string} string The string inspect. 2363 * @returns {number} Returns the string size. 2364 */ 2365 var asciiSize = baseProperty('length'); 2366 2367 /** 2368 * Converts an ASCII `string` to an array. 2369 * 2370 * @private 2371 * @param {string} string The string to convert. 2372 * @returns {Array} Returns the converted array. 2373 */ 2374 function asciiToArray(string) { 2375 return string.split(''); 2376 } 2377 2378 /** 2379 * Splits an ASCII `string` into an array of its words. 2380 * 2381 * @private 2382 * @param {string} The string to inspect. 2383 * @returns {Array} Returns the words of `string`. 2384 */ 2385 function asciiWords(string) { 2386 return string.match(reAsciiWord) || []; 2387 } 2388 2389 /** 2390 * The base implementation of methods like `_.findKey` and `_.findLastKey`, 2391 * without support for iteratee shorthands, which iterates over `collection` 2392 * using `eachFunc`. 2393 * 2394 * @private 2395 * @param {Array|Object} collection The collection to inspect. 2396 * @param {Function} predicate The function invoked per iteration. 2397 * @param {Function} eachFunc The function to iterate over `collection`. 2398 * @returns {*} Returns the found element or its key, else `undefined`. 2399 */ 2400 function baseFindKey(collection, predicate, eachFunc) { 2401 var result; 2402 eachFunc(collection, function(value, key, collection) { 2403 if (predicate(value, key, collection)) { 2404 result = key; 2405 return false; 2406 } 2407 }); 2408 return result; 2409 } 2410 2411 /** 2412 * The base implementation of `_.findIndex` and `_.findLastIndex` without 2413 * support for iteratee shorthands. 2414 * 2415 * @private 2416 * @param {Array} array The array to inspect. 2417 * @param {Function} predicate The function invoked per iteration. 2418 * @param {number} fromIndex The index to search from. 2419 * @param {boolean} [fromRight] Specify iterating from right to left. 2420 * @returns {number} Returns the index of the matched value, else `-1`. 2421 */ 2422 function baseFindIndex(array, predicate, fromIndex, fromRight) { 2423 var length = array.length, 2424 index = fromIndex + (fromRight ? 1 : -1); 2425 2426 while ((fromRight ? index-- : ++index < length)) { 2427 if (predicate(array[index], index, array)) { 2428 return index; 2429 } 2430 } 2431 return -1; 2432 } 2433 2434 /** 2435 * The base implementation of `_.indexOf` without `fromIndex` bounds checks. 2436 * 2437 * @private 2438 * @param {Array} array The array to inspect. 2439 * @param {*} value The value to search for. 2440 * @param {number} fromIndex The index to search from. 2441 * @returns {number} Returns the index of the matched value, else `-1`. 2442 */ 2443 function baseIndexOf(array, value, fromIndex) { 2444 return value === value 2445 ? strictIndexOf(array, value, fromIndex) 2446 : baseFindIndex(array, baseIsNaN, fromIndex); 2447 } 2448 2449 /** 2450 * This function is like `baseIndexOf` except that it accepts a comparator. 2451 * 2452 * @private 2453 * @param {Array} array The array to inspect. 2454 * @param {*} value The value to search for. 2455 * @param {number} fromIndex The index to search from. 2456 * @param {Function} comparator The comparator invoked per element. 2457 * @returns {number} Returns the index of the matched value, else `-1`. 2458 */ 2459 function baseIndexOfWith(array, value, fromIndex, comparator) { 2460 var index = fromIndex - 1, 2461 length = array.length; 2462 2463 while (++index < length) { 2464 if (comparator(array[index], value)) { 2465 return index; 2466 } 2467 } 2468 return -1; 2469 } 2470 2471 /** 2472 * The base implementation of `_.isNaN` without support for number objects. 2473 * 2474 * @private 2475 * @param {*} value The value to check. 2476 * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. 2477 */ 2478 function baseIsNaN(value) { 2479 return value !== value; 2480 } 2481 2482 /** 2483 * The base implementation of `_.mean` and `_.meanBy` without support for 2484 * iteratee shorthands. 2485 * 2486 * @private 2487 * @param {Array} array The array to iterate over. 2488 * @param {Function} iteratee The function invoked per iteration. 2489 * @returns {number} Returns the mean. 2490 */ 2491 function baseMean(array, iteratee) { 2492 var length = array == null ? 0 : array.length; 2493 return length ? (baseSum(array, iteratee) / length) : NAN; 2494 } 2495 2496 /** 2497 * The base implementation of `_.property` without support for deep paths. 2498 * 2499 * @private 2500 * @param {string} key The key of the property to get. 2501 * @returns {Function} Returns the new accessor function. 2502 */ 2503 function baseProperty(key) { 2504 return function(object) { 2505 return object == null ? undefined : object[key]; 2506 }; 2507 } 2508 2509 /** 2510 * The base implementation of `_.propertyOf` without support for deep paths. 2511 * 2512 * @private 2513 * @param {Object} object The object to query. 2514 * @returns {Function} Returns the new accessor function. 2515 */ 2516 function basePropertyOf(object) { 2517 return function(key) { 2518 return object == null ? undefined : object[key]; 2519 }; 2520 } 2521 2522 /** 2523 * The base implementation of `_.reduce` and `_.reduceRight`, without support 2524 * for iteratee shorthands, which iterates over `collection` using `eachFunc`. 2525 * 2526 * @private 2527 * @param {Array|Object} collection The collection to iterate over. 2528 * @param {Function} iteratee The function invoked per iteration. 2529 * @param {*} accumulator The initial value. 2530 * @param {boolean} initAccum Specify using the first or last element of 2531 * `collection` as the initial value. 2532 * @param {Function} eachFunc The function to iterate over `collection`. 2533 * @returns {*} Returns the accumulated value. 2534 */ 2535 function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { 2536 eachFunc(collection, function(value, index, collection) { 2537 accumulator = initAccum 2538 ? (initAccum = false, value) 2539 : iteratee(accumulator, value, index, collection); 2540 }); 2541 return accumulator; 2542 } 2543 2544 /** 2545 * The base implementation of `_.sortBy` which uses `comparer` to define the 2546 * sort order of `array` and replaces criteria objects with their corresponding 2547 * values. 2548 * 2549 * @private 2550 * @param {Array} array The array to sort. 2551 * @param {Function} comparer The function to define sort order. 2552 * @returns {Array} Returns `array`. 2553 */ 2554 function baseSortBy(array, comparer) { 2555 var length = array.length; 2556 2557 array.sort(comparer); 2558 while (length--) { 2559 array[length] = array[length].value; 2560 } 2561 return array; 2562 } 2563 2564 /** 2565 * The base implementation of `_.sum` and `_.sumBy` without support for 2566 * iteratee shorthands. 2567 * 2568 * @private 2569 * @param {Array} array The array to iterate over. 2570 * @param {Function} iteratee The function invoked per iteration. 2571 * @returns {number} Returns the sum. 2572 */ 2573 function baseSum(array, iteratee) { 2574 var result, 2575 index = -1, 2576 length = array.length; 2577 2578 while (++index < length) { 2579 var current = iteratee(array[index]); 2580 if (current !== undefined) { 2581 result = result === undefined ? current : (result + current); 2582 } 2583 } 2584 return result; 2585 } 2586 2587 /** 2588 * The base implementation of `_.times` without support for iteratee shorthands 2589 * or max array length checks. 2590 * 2591 * @private 2592 * @param {number} n The number of times to invoke `iteratee`. 2593 * @param {Function} iteratee The function invoked per iteration. 2594 * @returns {Array} Returns the array of results. 2595 */ 2596 function baseTimes(n, iteratee) { 2597 var index = -1, 2598 result = Array(n); 2599 2600 while (++index < n) { 2601 result[index] = iteratee(index); 2602 } 2603 return result; 2604 } 2605 2606 /** 2607 * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array 2608 * of key-value pairs for `object` corresponding to the property names of `props`. 2609 * 2610 * @private 2611 * @param {Object} object The object to query. 2612 * @param {Array} props The property names to get values for. 2613 * @returns {Object} Returns the key-value pairs. 2614 */ 2615 function baseToPairs(object, props) { 2616 return arrayMap(props, function(key) { 2617 return [key, object[key]]; 2618 }); 2619 } 2620 2621 /** 2622 * The base implementation of `_.trim`. 2623 * 2624 * @private 2625 * @param {string} string The string to trim. 2626 * @returns {string} Returns the trimmed string. 2627 */ 2628 function baseTrim(string) { 2629 return string 2630 ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') 2631 : string; 2632 } 2633 2634 /** 2635 * The base implementation of `_.unary` without support for storing metadata. 2636 * 2637 * @private 2638 * @param {Function} func The function to cap arguments for. 2639 * @returns {Function} Returns the new capped function. 2640 */ 2641 function baseUnary(func) { 2642 return function(value) { 2643 return func(value); 2644 }; 2645 } 2646 2647 /** 2648 * The base implementation of `_.values` and `_.valuesIn` which creates an 2649 * array of `object` property values corresponding to the property names 2650 * of `props`. 2651 * 2652 * @private 2653 * @param {Object} object The object to query. 2654 * @param {Array} props The property names to get values for. 2655 * @returns {Object} Returns the array of property values. 2656 */ 2657 function baseValues(object, props) { 2658 return arrayMap(props, function(key) { 2659 return object[key]; 2660 }); 2661 } 2662 2663 /** 2664 * Checks if a `cache` value for `key` exists. 2665 * 2666 * @private 2667 * @param {Object} cache The cache to query. 2668 * @param {string} key The key of the entry to check. 2669 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. 2670 */ 2671 function cacheHas(cache, key) { 2672 return cache.has(key); 2673 } 2674 2675 /** 2676 * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol 2677 * that is not found in the character symbols. 2678 * 2679 * @private 2680 * @param {Array} strSymbols The string symbols to inspect. 2681 * @param {Array} chrSymbols The character symbols to find. 2682 * @returns {number} Returns the index of the first unmatched string symbol. 2683 */ 2684 function charsStartIndex(strSymbols, chrSymbols) { 2685 var index = -1, 2686 length = strSymbols.length; 2687 2688 while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} 2689 return index; 2690 } 2691 2692 /** 2693 * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol 2694 * that is not found in the character symbols. 2695 * 2696 * @private 2697 * @param {Array} strSymbols The string symbols to inspect. 2698 * @param {Array} chrSymbols The character symbols to find. 2699 * @returns {number} Returns the index of the last unmatched string symbol. 2700 */ 2701 function charsEndIndex(strSymbols, chrSymbols) { 2702 var index = strSymbols.length; 2703 2704 while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} 2705 return index; 2706 } 2707 2708 /** 2709 * Gets the number of `placeholder` occurrences in `array`. 2710 * 2711 * @private 2712 * @param {Array} array The array to inspect. 2713 * @param {*} placeholder The placeholder to search for. 2714 * @returns {number} Returns the placeholder count. 2715 */ 2716 function countHolders(array, placeholder) { 2717 var length = array.length, 2718 result = 0; 2719 2720 while (length--) { 2721 if (array[length] === placeholder) { 2722 ++result; 2723 } 2724 } 2725 return result; 2726 } 2727 2728 /** 2729 * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A 2730 * letters to basic Latin letters. 2731 * 2732 * @private 2733 * @param {string} letter The matched letter to deburr. 2734 * @returns {string} Returns the deburred letter. 2735 */ 2736 var deburrLetter = basePropertyOf(deburredLetters); 2737 2738 /** 2739 * Used by `_.escape` to convert characters to HTML entities. 2740 * 2741 * @private 2742 * @param {string} chr The matched character to escape. 2743 * @returns {string} Returns the escaped character. 2744 */ 2745 var escapeHtmlChar = basePropertyOf(htmlEscapes); 2746 2747 /** 2748 * Used by `_.template` to escape characters for inclusion in compiled string literals. 2749 * 2750 * @private 2751 * @param {string} chr The matched character to escape. 2752 * @returns {string} Returns the escaped character. 2753 */ 2754 function escapeStringChar(chr) { 2755 return '\\' + stringEscapes[chr]; 2756 } 2757 2758 /** 2759 * Gets the value at `key` of `object`. 2760 * 2761 * @private 2762 * @param {Object} [object] The object to query. 2763 * @param {string} key The key of the property to get. 2764 * @returns {*} Returns the property value. 2765 */ 2766 function getValue(object, key) { 2767 return object == null ? undefined : object[key]; 2768 } 2769 2770 /** 2771 * Checks if `string` contains Unicode symbols. 2772 * 2773 * @private 2774 * @param {string} string The string to inspect. 2775 * @returns {boolean} Returns `true` if a symbol is found, else `false`. 2776 */ 2777 function hasUnicode(string) { 2778 return reHasUnicode.test(string); 2779 } 2780 2781 /** 2782 * Checks if `string` contains a word composed of Unicode symbols. 2783 * 2784 * @private 2785 * @param {string} string The string to inspect. 2786 * @returns {boolean} Returns `true` if a word is found, else `false`. 2787 */ 2788 function hasUnicodeWord(string) { 2789 return reHasUnicodeWord.test(string); 2790 } 2791 2792 /** 2793 * Converts `iterator` to an array.
vendor: 8,214 bytes, lines 2794-3103
2794 * 2795 * @private 2796 * @param {Object} iterator The iterator to convert. 2797 * @returns {Array} Returns the converted array. 2798 */ 2799 function iteratorToArray(iterator) { 2800 var data, 2801 result = []; 2802 2803 while (!(data = iterator.next()).done) { 2804 result.push(data.value); 2805 } 2806 return result; 2807 } 2808 2809 /** 2810 * Converts `map` to its key-value pairs. 2811 * 2812 * @private 2813 * @param {Object} map The map to convert. 2814 * @returns {Array} Returns the key-value pairs. 2815 */ 2816 function mapToArray(map) { 2817 var index = -1, 2818 result = Array(map.size); 2819 2820 map.forEach(function(value, key) { 2821 result[++index] = [key, value]; 2822 }); 2823 return result; 2824 } 2825 2826 /** 2827 * Creates a unary function that invokes `func` with its argument transformed. 2828 * 2829 * @private 2830 * @param {Function} func The function to wrap. 2831 * @param {Function} transform The argument transform. 2832 * @returns {Function} Returns the new function. 2833 */ 2834 function overArg(func, transform) { 2835 return function(arg) { 2836 return func(transform(arg)); 2837 }; 2838 } 2839 2840 /** 2841 * Replaces all `placeholder` elements in `array` with an internal placeholder 2842 * and returns an array of their indexes. 2843 * 2844 * @private 2845 * @param {Array} array The array to modify. 2846 * @param {*} placeholder The placeholder to replace. 2847 * @returns {Array} Returns the new array of placeholder indexes. 2848 */ 2849 function replaceHolders(array, placeholder) { 2850 var index = -1, 2851 length = array.length, 2852 resIndex = 0, 2853 result = []; 2854 2855 while (++index < length) { 2856 var value = array[index]; 2857 if (value === placeholder || value === PLACEHOLDER) { 2858 array[index] = PLACEHOLDER; 2859 result[resIndex++] = index; 2860 } 2861 } 2862 return result; 2863 } 2864 2865 /** 2866 * Converts `set` to an array of its values. 2867 * 2868 * @private 2869 * @param {Object} set The set to convert. 2870 * @returns {Array} Returns the values. 2871 */ 2872 function setToArray(set) { 2873 var index = -1, 2874 result = Array(set.size); 2875 2876 set.forEach(function(value) { 2877 result[++index] = value; 2878 }); 2879 return result; 2880 } 2881 2882 /** 2883 * Converts `set` to its value-value pairs. 2884 * 2885 * @private 2886 * @param {Object} set The set to convert. 2887 * @returns {Array} Returns the value-value pairs. 2888 */ 2889 function setToPairs(set) { 2890 var index = -1, 2891 result = Array(set.size); 2892 2893 set.forEach(function(value) { 2894 result[++index] = [value, value]; 2895 }); 2896 return result; 2897 } 2898 2899 /** 2900 * A specialized version of `_.indexOf` which performs strict equality 2901 * comparisons of values, i.e. `===`. 2902 * 2903 * @private 2904 * @param {Array} array The array to inspect. 2905 * @param {*} value The value to search for. 2906 * @param {number} fromIndex The index to search from. 2907 * @returns {number} Returns the index of the matched value, else `-1`. 2908 */ 2909 function strictIndexOf(array, value, fromIndex) { 2910 var index = fromIndex - 1, 2911 length = array.length; 2912 2913 while (++index < length) { 2914 if (array[index] === value) { 2915 return index; 2916 } 2917 } 2918 return -1; 2919 } 2920 2921 /** 2922 * A specialized version of `_.lastIndexOf` which performs strict equality 2923 * comparisons of values, i.e. `===`. 2924 * 2925 * @private 2926 * @param {Array} array The array to inspect. 2927 * @param {*} value The value to search for. 2928 * @param {number} fromIndex The index to search from. 2929 * @returns {number} Returns the index of the matched value, else `-1`. 2930 */ 2931 function strictLastIndexOf(array, value, fromIndex) { 2932 var index = fromIndex + 1; 2933 while (index--) { 2934 if (array[index] === value) { 2935 return index; 2936 } 2937 } 2938 return index; 2939 } 2940 2941 /** 2942 * Gets the number of symbols in `string`. 2943 * 2944 * @private 2945 * @param {string} string The string to inspect. 2946 * @returns {number} Returns the string size. 2947 */ 2948 function stringSize(string) { 2949 return hasUnicode(string) 2950 ? unicodeSize(string) 2951 : asciiSize(string); 2952 } 2953 2954 /** 2955 * Converts `string` to an array. 2956 * 2957 * @private 2958 * @param {string} string The string to convert. 2959 * @returns {Array} Returns the converted array. 2960 */ 2961 function stringToArray(string) { 2962 return hasUnicode(string) 2963 ? unicodeToArray(string) 2964 : asciiToArray(string); 2965 } 2966 2967 /** 2968 * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace 2969 * character of `string`. 2970 * 2971 * @private 2972 * @param {string} string The string to inspect. 2973 * @returns {number} Returns the index of the last non-whitespace character. 2974 */ 2975 function trimmedEndIndex(string) { 2976 var index = string.length; 2977 2978 while (index-- && reWhitespace.test(string.charAt(index))) {} 2979 return index; 2980 } 2981 2982 /** 2983 * Used by `_.unescape` to convert HTML entities to characters. 2984 * 2985 * @private 2986 * @param {string} chr The matched character to unescape. 2987 * @returns {string} Returns the unescaped character. 2988 */ 2989 var unescapeHtmlChar = basePropertyOf(htmlUnescapes); 2990 2991 /** 2992 * Gets the size of a Unicode `string`. 2993 * 2994 * @private 2995 * @param {string} string The string inspect. 2996 * @returns {number} Returns the string size. 2997 */ 2998 function unicodeSize(string) { 2999 var result = reUnicode.lastIndex = 0; 3000 while (reUnicode.test(string)) { 3001 ++result; 3002 } 3003 return result; 3004 } 3005 3006 /** 3007 * Converts a Unicode `string` to an array. 3008 * 3009 * @private 3010 * @param {string} string The string to convert. 3011 * @returns {Array} Returns the converted array. 3012 */ 3013 function unicodeToArray(string) { 3014 return string.match(reUnicode) || []; 3015 } 3016 3017 /** 3018 * Splits a Unicode `string` into an array of its words. 3019 * 3020 * @private 3021 * @param {string} The string to inspect. 3022 * @returns {Array} Returns the words of `string`. 3023 */ 3024 function unicodeWords(string) { 3025 return string.match(reUnicodeWord) || []; 3026 } 3027 3028 /*--------------------------------------------------------------------------*/ 3029 3030 /** 3031 * Create a new pristine `lodash` function using the `context` object. 3032 * 3033 * @static 3034 * @memberOf _ 3035 * @since 1.1.0 3036 * @category Util 3037 * @param {Object} [context=root] The context object. 3038 * @returns {Function} Returns a new `lodash` function. 3039 * @example 3040 * 3041 * _.mixin({ 'foo': _.constant('foo') }); 3042 * 3043 * var lodash = _.runInContext(); 3044 * lodash.mixin({ 'bar': lodash.constant('bar') }); 3045 * 3046 * _.isFunction(_.foo); 3047 * // => true 3048 * _.isFunction(_.bar); 3049 * // => false 3050 * 3051 * lodash.isFunction(lodash.foo); 3052 * // => false 3053 * lodash.isFunction(lodash.bar); 3054 * // => true 3055 * 3056 * // Create a suped-up `defer` in Node.js. 3057 * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer; 3058 */ 3059 var runInContext = (function runInContext(context) { 3060 context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps)); 3061 3062 /** Built-in constructor references. */ 3063 var Array = context.Array, 3064 Date = context.Date, 3065 Error = context.Error, 3066 Function = context.Function, 3067 Math = context.Math, 3068 Object = context.Object, 3069 RegExp = context.RegExp, 3070 String = context.String, 3071 TypeError = context.TypeError; 3072 3073 /** Used for built-in method references. */ 3074 var arrayProto = Array.prototype, 3075 funcProto = Function.prototype, 3076 objectProto = Object.prototype; 3077 3078 /** Used to detect overreaching core-js shims. */ 3079 var coreJsData = context['__core-js_shared__']; 3080 3081 /** Used to resolve the decompiled source of functions. */ 3082 var funcToString = funcProto.toString; 3083 3084 /** Used to check objects for own properties. */ 3085 var hasOwnProperty = objectProto.hasOwnProperty; 3086 3087 /** Used to generate unique IDs. */ 3088 var idCounter = 0; 3089 3090 /** Used to detect methods masquerading as native. */ 3091 var maskSrcKey = (function() { 3092 var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); 3093 return uid ? ('Symbol(src)_1.' + uid) : ''; 3094 }()); 3095 3096 /** 3097 * Used to resolve the 3098 * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) 3099 * of values. 3100 */ 3101 var nativeObjectToString = objectProto.toString; 3102 3103 /** Used to infer the `Object` constructor. */
vendor: 25,659 bytes, lines 3104-3901
3104 var objectCtorString = funcToString.call(Object); 3105 3106 /** Used to restore the original `_` reference in `_.noConflict`. */ 3107 var oldDash = root._; 3108 3109 /** Used to detect if a method is native. */ 3110 var reIsNative = RegExp('^' + 3111 funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') 3112 .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' 3113 ); 3114 3115 /** Built-in value references. */ 3116 var Buffer = moduleExports ? context.Buffer : undefined, 3117 Symbol = context.Symbol, 3118 Uint8Array = context.Uint8Array, 3119 allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined, 3120 getPrototype = overArg(Object.getPrototypeOf, Object), 3121 objectCreate = Object.create, 3122 propertyIsEnumerable = objectProto.propertyIsEnumerable, 3123 splice = arrayProto.splice, 3124 spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined, 3125 symIterator = Symbol ? Symbol.iterator : undefined, 3126 symToStringTag = Symbol ? Symbol.toStringTag : undefined; 3127 3128 var defineProperty = (function() { 3129 try { 3130 var func = getNative(Object, 'defineProperty'); 3131 func({}, '', {}); 3132 return func; 3133 } catch (e) {} 3134 }()); 3135 3136 /** Mocked built-ins. */ 3137 var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout, 3138 ctxNow = Date && Date.now !== root.Date.now && Date.now, 3139 ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout; 3140 3141 /* Built-in method references for those with the same name as other `lodash` methods. */ 3142 var nativeCeil = Math.ceil, 3143 nativeFloor = Math.floor, 3144 nativeGetSymbols = Object.getOwnPropertySymbols, 3145 nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined, 3146 nativeIsFinite = context.isFinite, 3147 nativeJoin = arrayProto.join, 3148 nativeKeys = overArg(Object.keys, Object), 3149 nativeMax = Math.max, 3150 nativeMin = Math.min, 3151 nativeNow = Date.now, 3152 nativeParseInt = context.parseInt, 3153 nativeRandom = Math.random, 3154 nativeReverse = arrayProto.reverse; 3155 3156 /* Built-in method references that are verified to be native. */ 3157 var DataView = getNative(context, 'DataView'), 3158 Map = getNative(context, 'Map'), 3159 Promise = getNative(context, 'Promise'), 3160 Set = getNative(context, 'Set'), 3161 WeakMap = getNative(context, 'WeakMap'), 3162 nativeCreate = getNative(Object, 'create'); 3163 3164 /** Used to store function metadata. */ 3165 var metaMap = WeakMap && new WeakMap; 3166 3167 /** Used to lookup unminified function names. */ 3168 var realNames = {}; 3169 3170 /** Used to detect maps, sets, and weakmaps. */ 3171 var dataViewCtorString = toSource(DataView), 3172 mapCtorString = toSource(Map), 3173 promiseCtorString = toSource(Promise), 3174 setCtorString = toSource(Set), 3175 weakMapCtorString = toSource(WeakMap); 3176 3177 /** Used to convert symbols to primitives and strings. */ 3178 var symbolProto = Symbol ? Symbol.prototype : undefined, 3179 symbolValueOf = symbolProto ? symbolProto.valueOf : undefined, 3180 symbolToString = symbolProto ? symbolProto.toString : undefined; 3181 3182 /*------------------------------------------------------------------------*/ 3183 3184 /** 3185 * Creates a `lodash` object which wraps `value` to enable implicit method 3186 * chain sequences. Methods that operate on and return arrays, collections, 3187 * and functions can be chained together. Methods that retrieve a single value 3188 * or may return a primitive value will automatically end the chain sequence 3189 * and return the unwrapped value. Otherwise, the value must be unwrapped 3190 * with `_#value`. 3191 * 3192 * Explicit chain sequences, which must be unwrapped with `_#value`, may be 3193 * enabled using `_.chain`. 3194 * 3195 * The execution of chained methods is lazy, that is, it's deferred until 3196 * `_#value` is implicitly or explicitly called. 3197 * 3198 * Lazy evaluation allows several methods to support shortcut fusion. 3199 * Shortcut fusion is an optimization to merge iteratee calls; this avoids 3200 * the creation of intermediate arrays and can greatly reduce the number of 3201 * iteratee executions. Sections of a chain sequence qualify for shortcut 3202 * fusion if the section is applied to an array and iteratees accept only 3203 * one argument. The heuristic for whether a section qualifies for shortcut 3204 * fusion is subject to change. 3205 * 3206 * Chaining is supported in custom builds as long as the `_#value` method is 3207 * directly or indirectly included in the build. 3208 * 3209 * In addition to lodash methods, wrappers have `Array` and `String` methods. 3210 * 3211 * The wrapper `Array` methods are: 3212 * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` 3213 * 3214 * The wrapper `String` methods are: 3215 * `replace` and `split` 3216 * 3217 * The wrapper methods that support shortcut fusion are: 3218 * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, 3219 * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, 3220 * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` 3221 * 3222 * The chainable wrapper methods are: 3223 * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, 3224 * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, 3225 * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, 3226 * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, 3227 * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, 3228 * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, 3229 * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, 3230 * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, 3231 * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, 3232 * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, 3233 * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, 3234 * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, 3235 * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, 3236 * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, 3237 * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, 3238 * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, 3239 * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, 3240 * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, 3241 * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, 3242 * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, 3243 * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, 3244 * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, 3245 * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, 3246 * `zipObject`, `zipObjectDeep`, and `zipWith` 3247 * 3248 * The wrapper methods that are **not** chainable by default are: 3249 * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, 3250 * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, 3251 * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, 3252 * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, 3253 * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, 3254 * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, 3255 * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, 3256 * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, 3257 * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, 3258 * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, 3259 * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, 3260 * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, 3261 * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, 3262 * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, 3263 * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, 3264 * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, 3265 * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, 3266 * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, 3267 * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, 3268 * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, 3269 * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, 3270 * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, 3271 * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, 3272 * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, 3273 * `upperFirst`, `value`, and `words` 3274 * 3275 * @name _ 3276 * @constructor 3277 * @category Seq 3278 * @param {*} value The value to wrap in a `lodash` instance. 3279 * @returns {Object} Returns the new `lodash` wrapper instance. 3280 * @example 3281 * 3282 * function square(n) { 3283 * return n * n; 3284 * } 3285 * 3286 * var wrapped = _([1, 2, 3]); 3287 * 3288 * // Returns an unwrapped value. 3289 * wrapped.reduce(_.add); 3290 * // => 6 3291 * 3292 * // Returns a wrapped value. 3293 * var squares = wrapped.map(square); 3294 * 3295 * _.isArray(squares); 3296 * // => false 3297 * 3298 * _.isArray(squares.value()); 3299 * // => true 3300 */ 3301 function lodash(value) { 3302 if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { 3303 if (value instanceof LodashWrapper) { 3304 return value; 3305 } 3306 if (hasOwnProperty.call(value, '__wrapped__')) { 3307 return wrapperClone(value); 3308 } 3309 } 3310 return new LodashWrapper(value); 3311 } 3312 3313 /** 3314 * The base implementation of `_.create` without support for assigning 3315 * properties to the created object. 3316 * 3317 * @private 3318 * @param {Object} proto The object to inherit from. 3319 * @returns {Object} Returns the new object. 3320 */ 3321 var baseCreate = (function() { 3322 function object() {} 3323 return function(proto) { 3324 if (!isObject(proto)) { 3325 return {}; 3326 } 3327 if (objectCreate) { 3328 return objectCreate(proto); 3329 } 3330 object.prototype = proto; 3331 var result = new object; 3332 object.prototype = undefined; 3333 return result; 3334 }; 3335 }()); 3336 3337 /** 3338 * The function whose prototype chain sequence wrappers inherit from. 3339 * 3340 * @private 3341 */ 3342 function baseLodash() { 3343 // No operation performed. 3344 } 3345 3346 /** 3347 * The base constructor for creating `lodash` wrapper objects. 3348 * 3349 * @private 3350 * @param {*} value The value to wrap. 3351 * @param {boolean} [chainAll] Enable explicit method chain sequences. 3352 */ 3353 function LodashWrapper(value, chainAll) { 3354 this.__wrapped__ = value; 3355 this.__actions__ = []; 3356 this.__chain__ = !!chainAll; 3357 this.__index__ = 0; 3358 this.__values__ = undefined; 3359 } 3360 3361 /** 3362 * By default, the template delimiters used by lodash are like those in 3363 * embedded Ruby (ERB) as well as ES2015 template strings. Change the 3364 * following template settings to use alternative delimiters. 3365 * 3366 * @static 3367 * @memberOf _ 3368 * @type {Object} 3369 */ 3370 lodash.templateSettings = { 3371 3372 /** 3373 * Used to detect `data` property values to be HTML-escaped. 3374 * 3375 * @memberOf _.templateSettings 3376 * @type {RegExp} 3377 */ 3378 'escape': reEscape, 3379 3380 /** 3381 * Used to detect code to be evaluated. 3382 * 3383 * @memberOf _.templateSettings 3384 * @type {RegExp} 3385 */ 3386 'evaluate': reEvaluate, 3387 3388 /** 3389 * Used to detect `data` property values to inject. 3390 * 3391 * @memberOf _.templateSettings 3392 * @type {RegExp} 3393 */ 3394 'interpolate': reInterpolate, 3395 3396 /** 3397 * Used to reference the data object in the template text. 3398 * 3399 * @memberOf _.templateSettings 3400 * @type {string} 3401 */ 3402 'variable': '', 3403 3404 /** 3405 * Used to import variables into the compiled template. 3406 * 3407 * @memberOf _.templateSettings 3408 * @type {Object} 3409 */ 3410 'imports': { 3411 3412 /** 3413 * A reference to the `lodash` function. 3414 * 3415 * @memberOf _.templateSettings.imports 3416 * @type {Function} 3417 */ 3418 '_': lodash 3419 } 3420 }; 3421 3422 // Ensure wrappers are instances of `baseLodash`. 3423 lodash.prototype = baseLodash.prototype; 3424 lodash.prototype.constructor = lodash; 3425 3426 LodashWrapper.prototype = baseCreate(baseLodash.prototype); 3427 LodashWrapper.prototype.constructor = LodashWrapper; 3428 3429 /*------------------------------------------------------------------------*/ 3430 3431 /** 3432 * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. 3433 * 3434 * @private 3435 * @constructor 3436 * @param {*} value The value to wrap. 3437 */ 3438 function LazyWrapper(value) { 3439 this.__wrapped__ = value; 3440 this.__actions__ = []; 3441 this.__dir__ = 1; 3442 this.__filtered__ = false; 3443 this.__iteratees__ = []; 3444 this.__takeCount__ = MAX_ARRAY_LENGTH; 3445 this.__views__ = []; 3446 } 3447 3448 /** 3449 * Creates a clone of the lazy wrapper object. 3450 * 3451 * @private 3452 * @name clone 3453 * @memberOf LazyWrapper 3454 * @returns {Object} Returns the cloned `LazyWrapper` object. 3455 */ 3456 function lazyClone() { 3457 var result = new LazyWrapper(this.__wrapped__); 3458 result.__actions__ = copyArray(this.__actions__); 3459 result.__dir__ = this.__dir__; 3460 result.__filtered__ = this.__filtered__; 3461 result.__iteratees__ = copyArray(this.__iteratees__); 3462 result.__takeCount__ = this.__takeCount__; 3463 result.__views__ = copyArray(this.__views__); 3464 return result; 3465 } 3466 3467 /** 3468 * Reverses the direction of lazy iteration. 3469 * 3470 * @private 3471 * @name reverse 3472 * @memberOf LazyWrapper 3473 * @returns {Object} Returns the new reversed `LazyWrapper` object. 3474 */ 3475 function lazyReverse() { 3476 if (this.__filtered__) { 3477 var result = new LazyWrapper(this); 3478 result.__dir__ = -1; 3479 result.__filtered__ = true; 3480 } else { 3481 result = this.clone(); 3482 result.__dir__ *= -1; 3483 } 3484 return result; 3485 } 3486 3487 /** 3488 * Extracts the unwrapped value from its lazy wrapper. 3489 * 3490 * @private 3491 * @name value 3492 * @memberOf LazyWrapper 3493 * @returns {*} Returns the unwrapped value. 3494 */ 3495 function lazyValue() { 3496 var array = this.__wrapped__.value(), 3497 dir = this.__dir__, 3498 isArr = isArray(array), 3499 isRight = dir < 0, 3500 arrLength = isArr ? array.length : 0, 3501 view = getView(0, arrLength, this.__views__), 3502 start = view.start, 3503 end = view.end, 3504 length = end - start, 3505 index = isRight ? end : (start - 1), 3506 iteratees = this.__iteratees__, 3507 iterLength = iteratees.length, 3508 resIndex = 0, 3509 takeCount = nativeMin(length, this.__takeCount__); 3510 3511 if (!isArr || (!isRight && arrLength == length && takeCount == length)) { 3512 return baseWrapperValue(array, this.__actions__); 3513 } 3514 var result = []; 3515 3516 outer: 3517 while (length-- && resIndex < takeCount) { 3518 index += dir; 3519 3520 var iterIndex = -1, 3521 value = array[index]; 3522 3523 while (++iterIndex < iterLength) { 3524 var data = iteratees[iterIndex], 3525 iteratee = data.iteratee, 3526 type = data.type, 3527 computed = iteratee(value); 3528 3529 if (type == LAZY_MAP_FLAG) { 3530 value = computed; 3531 } else if (!computed) { 3532 if (type == LAZY_FILTER_FLAG) { 3533 continue outer; 3534 } else { 3535 break outer; 3536 } 3537 } 3538 } 3539 result[resIndex++] = value; 3540 } 3541 return result; 3542 } 3543 3544 // Ensure `LazyWrapper` is an instance of `baseLodash`. 3545 LazyWrapper.prototype = baseCreate(baseLodash.prototype); 3546 LazyWrapper.prototype.constructor = LazyWrapper; 3547 3548 /*------------------------------------------------------------------------*/ 3549 3550 /** 3551 * Creates a hash object. 3552 * 3553 * @private 3554 * @constructor 3555 * @param {Array} [entries] The key-value pairs to cache. 3556 */ 3557 function Hash(entries) { 3558 var index = -1, 3559 length = entries == null ? 0 : entries.length; 3560 3561 this.clear(); 3562 while (++index < length) { 3563 var entry = entries[index]; 3564 this.set(entry[0], entry[1]); 3565 } 3566 } 3567 3568 /** 3569 * Removes all key-value entries from the hash. 3570 * 3571 * @private 3572 * @name clear 3573 * @memberOf Hash 3574 */ 3575 function hashClear() { 3576 this.__data__ = nativeCreate ? nativeCreate(null) : {}; 3577 this.size = 0; 3578 } 3579 3580 /** 3581 * Removes `key` and its value from the hash. 3582 * 3583 * @private 3584 * @name delete 3585 * @memberOf Hash 3586 * @param {Object} hash The hash to modify. 3587 * @param {string} key The key of the value to remove. 3588 * @returns {boolean} Returns `true` if the entry was removed, else `false`. 3589 */ 3590 function hashDelete(key) { 3591 var result = this.has(key) && delete this.__data__[key]; 3592 this.size -= result ? 1 : 0; 3593 return result; 3594 } 3595 3596 /** 3597 * Gets the hash value for `key`. 3598 * 3599 * @private 3600 * @name get 3601 * @memberOf Hash 3602 * @param {string} key The key of the value to get. 3603 * @returns {*} Returns the entry value. 3604 */ 3605 function hashGet(key) { 3606 var data = this.__data__; 3607 if (nativeCreate) { 3608 var result = data[key]; 3609 return result === HASH_UNDEFINED ? undefined : result; 3610 } 3611 return hasOwnProperty.call(data, key) ? data[key] : undefined; 3612 } 3613 3614 /** 3615 * Checks if a hash value for `key` exists. 3616 * 3617 * @private 3618 * @name has 3619 * @memberOf Hash 3620 * @param {string} key The key of the entry to check. 3621 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. 3622 */ 3623 function hashHas(key) { 3624 var data = this.__data__; 3625 return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key); 3626 } 3627 3628 /** 3629 * Sets the hash `key` to `value`. 3630 * 3631 * @private 3632 * @name set 3633 * @memberOf Hash 3634 * @param {string} key The key of the value to set. 3635 * @param {*} value The value to set. 3636 * @returns {Object} Returns the hash instance. 3637 */ 3638 function hashSet(key, value) { 3639 var data = this.__data__; 3640 this.size += this.has(key) ? 0 : 1; 3641 data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; 3642 return this; 3643 } 3644 3645 // Add methods to `Hash`. 3646 Hash.prototype.clear = hashClear; 3647 Hash.prototype['delete'] = hashDelete; 3648 Hash.prototype.get = hashGet; 3649 Hash.prototype.has = hashHas; 3650 Hash.prototype.set = hashSet; 3651 3652 /*------------------------------------------------------------------------*/ 3653 3654 /** 3655 * Creates an list cache object. 3656 * 3657 * @private 3658 * @constructor 3659 * @param {Array} [entries] The key-value pairs to cache. 3660 */ 3661 function ListCache(entries) { 3662 var index = -1, 3663 length = entries == null ? 0 : entries.length; 3664 3665 this.clear(); 3666 while (++index < length) { 3667 var entry = entries[index]; 3668 this.set(entry[0], entry[1]); 3669 } 3670 } 3671 3672 /** 3673 * Removes all key-value entries from the list cache. 3674 * 3675 * @private 3676 * @name clear 3677 * @memberOf ListCache 3678 */ 3679 function listCacheClear() { 3680 this.__data__ = []; 3681 this.size = 0; 3682 } 3683 3684 /** 3685 * Removes `key` and its value from the list cache. 3686 * 3687 * @private 3688 * @name delete 3689 * @memberOf ListCache 3690 * @param {string} key The key of the value to remove. 3691 * @returns {boolean} Returns `true` if the entry was removed, else `false`. 3692 */ 3693 function listCacheDelete(key) { 3694 var data = this.__data__, 3695 index = assocIndexOf(data, key); 3696 3697 if (index < 0) { 3698 return false; 3699 } 3700 var lastIndex = data.length - 1; 3701 if (index == lastIndex) { 3702 data.pop(); 3703 } else { 3704 splice.call(data, index, 1); 3705 } 3706 --this.size; 3707 return true; 3708 } 3709 3710 /** 3711 * Gets the list cache value for `key`. 3712 * 3713 * @private 3714 * @name get 3715 * @memberOf ListCache 3716 * @param {string} key The key of the value to get. 3717 * @returns {*} Returns the entry value. 3718 */ 3719 function listCacheGet(key) { 3720 var data = this.__data__, 3721 index = assocIndexOf(data, key); 3722 3723 return index < 0 ? undefined : data[index][1]; 3724 } 3725 3726 /** 3727 * Checks if a list cache value for `key` exists. 3728 * 3729 * @private 3730 * @name has 3731 * @memberOf ListCache 3732 * @param {string} key The key of the entry to check. 3733 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. 3734 */ 3735 function listCacheHas(key) { 3736 return assocIndexOf(this.__data__, key) > -1; 3737 } 3738 3739 /** 3740 * Sets the list cache `key` to `value`. 3741 * 3742 * @private 3743 * @name set 3744 * @memberOf ListCache 3745 * @param {string} key The key of the value to set. 3746 * @param {*} value The value to set. 3747 * @returns {Object} Returns the list cache instance. 3748 */ 3749 function listCacheSet(key, value) { 3750 var data = this.__data__, 3751 index = assocIndexOf(data, key); 3752 3753 if (index < 0) { 3754 ++this.size; 3755 data.push([key, value]); 3756 } else { 3757 data[index][1] = value; 3758 } 3759 return this; 3760 } 3761 3762 // Add methods to `ListCache`. 3763 ListCache.prototype.clear = listCacheClear; 3764 ListCache.prototype['delete'] = listCacheDelete; 3765 ListCache.prototype.get = listCacheGet; 3766 ListCache.prototype.has = listCacheHas; 3767 ListCache.prototype.set = listCacheSet; 3768 3769 /*------------------------------------------------------------------------*/ 3770 3771 /** 3772 * Creates a map cache object to store key-value pairs. 3773 * 3774 * @private 3775 * @constructor 3776 * @param {Array} [entries] The key-value pairs to cache. 3777 */ 3778 function MapCache(entries) { 3779 var index = -1, 3780 length = entries == null ? 0 : entries.length; 3781 3782 this.clear(); 3783 while (++index < length) { 3784 var entry = entries[index]; 3785 this.set(entry[0], entry[1]); 3786 } 3787 } 3788 3789 /** 3790 * Removes all key-value entries from the map. 3791 * 3792 * @private 3793 * @name clear 3794 * @memberOf MapCache 3795 */ 3796 function mapCacheClear() { 3797 this.size = 0; 3798 this.__data__ = { 3799 'hash': new Hash, 3800 'map': new (Map || ListCache), 3801 'string': new Hash 3802 }; 3803 } 3804 3805 /** 3806 * Removes `key` and its value from the map. 3807 * 3808 * @private 3809 * @name delete 3810 * @memberOf MapCache 3811 * @param {string} key The key of the value to remove. 3812 * @returns {boolean} Returns `true` if the entry was removed, else `false`. 3813 */ 3814 function mapCacheDelete(key) { 3815 var result = getMapData(this, key)['delete'](key); 3816 this.size -= result ? 1 : 0; 3817 return result; 3818 } 3819 3820 /** 3821 * Gets the map value for `key`. 3822 * 3823 * @private 3824 * @name get 3825 * @memberOf MapCache 3826 * @param {string} key The key of the value to get. 3827 * @returns {*} Returns the entry value. 3828 */ 3829 function mapCacheGet(key) { 3830 return getMapData(this, key).get(key); 3831 } 3832 3833 /** 3834 * Checks if a map value for `key` exists. 3835 * 3836 * @private 3837 * @name has 3838 * @memberOf MapCache 3839 * @param {string} key The key of the entry to check. 3840 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. 3841 */ 3842 function mapCacheHas(key) { 3843 return getMapData(this, key).has(key); 3844 } 3845 3846 /** 3847 * Sets the map `key` to `value`. 3848 * 3849 * @private 3850 * @name set 3851 * @memberOf MapCache 3852 * @param {string} key The key of the value to set. 3853 * @param {*} value The value to set. 3854 * @returns {Object} Returns the map cache instance. 3855 */ 3856 function mapCacheSet(key, value) { 3857 var data = getMapData(this, key), 3858 size = data.size; 3859 3860 data.set(key, value); 3861 this.size += data.size == size ? 0 : 1; 3862 return this; 3863 } 3864 3865 // Add methods to `MapCache`. 3866 MapCache.prototype.clear = mapCacheClear; 3867 MapCache.prototype['delete'] = mapCacheDelete; 3868 MapCache.prototype.get = mapCacheGet; 3869 MapCache.prototype.has = mapCacheHas; 3870 MapCache.prototype.set = mapCacheSet; 3871 3872 /*------------------------------------------------------------------------*/ 3873 3874 /** 3875 * 3876 * Creates an array cache object to store unique values. 3877 * 3878 * @private 3879 * @constructor 3880 * @param {Array} [values] The values to cache. 3881 */ 3882 function SetCache(values) { 3883 var index = -1, 3884 length = values == null ? 0 : values.length; 3885 3886 this.__data__ = new MapCache; 3887 while (++index < length) { 3888 this.add(values[index]); 3889 } 3890 } 3891 3892 /** 3893 * Adds `value` to the array cache. 3894 * 3895 * @private 3896 * @name add 3897 * @memberOf SetCache 3898 * @alias push 3899 * @param {*} value The value to cache. 3900 * @returns {Object} Returns the cache instance. 3901 */
vendor: 3,741 bytes, lines 3902-4038
3902 function setCacheAdd(value) { 3903 this.__data__.set(value, HASH_UNDEFINED); 3904 return this; 3905 } 3906 3907 /** 3908 * Checks if `value` is in the array cache. 3909 * 3910 * @private 3911 * @name has 3912 * @memberOf SetCache 3913 * @param {*} value The value to search for. 3914 * @returns {number} Returns `true` if `value` is found, else `false`. 3915 */ 3916 function setCacheHas(value) { 3917 return this.__data__.has(value); 3918 } 3919 3920 // Add methods to `SetCache`. 3921 SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; 3922 SetCache.prototype.has = setCacheHas; 3923 3924 /*------------------------------------------------------------------------*/ 3925 3926 /** 3927 * Creates a stack cache object to store key-value pairs. 3928 * 3929 * @private 3930 * @constructor 3931 * @param {Array} [entries] The key-value pairs to cache. 3932 */ 3933 function Stack(entries) { 3934 var data = this.__data__ = new ListCache(entries); 3935 this.size = data.size; 3936 } 3937 3938 /** 3939 * Removes all key-value entries from the stack. 3940 * 3941 * @private 3942 * @name clear 3943 * @memberOf Stack 3944 */ 3945 function stackClear() { 3946 this.__data__ = new ListCache; 3947 this.size = 0; 3948 } 3949 3950 /** 3951 * Removes `key` and its value from the stack. 3952 * 3953 * @private 3954 * @name delete 3955 * @memberOf Stack 3956 * @param {string} key The key of the value to remove. 3957 * @returns {boolean} Returns `true` if the entry was removed, else `false`. 3958 */ 3959 function stackDelete(key) { 3960 var data = this.__data__, 3961 result = data['delete'](key); 3962 3963 this.size = data.size; 3964 return result; 3965 } 3966 3967 /** 3968 * Gets the stack value for `key`. 3969 * 3970 * @private 3971 * @name get 3972 * @memberOf Stack 3973 * @param {string} key The key of the value to get. 3974 * @returns {*} Returns the entry value. 3975 */ 3976 function stackGet(key) { 3977 return this.__data__.get(key); 3978 } 3979 3980 /** 3981 * Checks if a stack value for `key` exists. 3982 * 3983 * @private 3984 * @name has 3985 * @memberOf Stack 3986 * @param {string} key The key of the entry to check. 3987 * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. 3988 */ 3989 function stackHas(key) { 3990 return this.__data__.has(key); 3991 } 3992 3993 /** 3994 * Sets the stack `key` to `value`. 3995 * 3996 * @private 3997 * @name set 3998 * @memberOf Stack 3999 * @param {string} key The key of the value to set. 4000 * @param {*} value The value to set. 4001 * @returns {Object} Returns the stack cache instance. 4002 */ 4003 function stackSet(key, value) { 4004 var data = this.__data__; 4005 if (data instanceof ListCache) { 4006 var pairs = data.__data__; 4007 if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { 4008 pairs.push([key, value]); 4009 this.size = ++data.size; 4010 return this; 4011 } 4012 data = this.__data__ = new MapCache(pairs); 4013 } 4014 data.set(key, value); 4015 this.size = data.size; 4016 return this; 4017 } 4018 4019 // Add methods to `Stack`. 4020 Stack.prototype.clear = stackClear; 4021 Stack.prototype['delete'] = stackDelete; 4022 Stack.prototype.get = stackGet; 4023 Stack.prototype.has = stackHas; 4024 Stack.prototype.set = stackSet; 4025 4026 /*------------------------------------------------------------------------*/ 4027 4028 /** 4029 * Creates an array of the enumerable property names of the array-like `value`. 4030 * 4031 * @private 4032 * @param {*} value The value to query. 4033 * @param {boolean} inherited Specify returning inherited property names. 4034 * @returns {Array} Returns the array of property names. 4035 */ 4036 function arrayLikeKeys(value, inherited) { 4037 var isArr = isArray(value), 4038 isArg = !isArr && isArguments(value),
vendor: 111,524 bytes, lines 4039-7332
4039 isBuff = !isArr && !isArg && isBuffer(value), 4040 isType = !isArr && !isArg && !isBuff && isTypedArray(value), 4041 skipIndexes = isArr || isArg || isBuff || isType, 4042 result = skipIndexes ? baseTimes(value.length, String) : [], 4043 length = result.length; 4044 4045 for (var key in value) { 4046 if ((inherited || hasOwnProperty.call(value, key)) && 4047 !(skipIndexes && ( 4048 // Safari 9 has enumerable `arguments.length` in strict mode. 4049 key == 'length' || 4050 // Node.js 0.10 has enumerable non-index properties on buffers. 4051 (isBuff && (key == 'offset' || key == 'parent')) || 4052 // PhantomJS 2 has enumerable non-index properties on typed arrays. 4053 (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || 4054 // Skip index properties. 4055 isIndex(key, length) 4056 ))) { 4057 result.push(key); 4058 } 4059 } 4060 return result; 4061 } 4062 4063 /** 4064 * A specialized version of `_.sample` for arrays. 4065 * 4066 * @private 4067 * @param {Array} array The array to sample. 4068 * @returns {*} Returns the random element. 4069 */ 4070 function arraySample(array) { 4071 var length = array.length; 4072 return length ? array[baseRandom(0, length - 1)] : undefined; 4073 } 4074 4075 /** 4076 * A specialized version of `_.sampleSize` for arrays. 4077 * 4078 * @private 4079 * @param {Array} array The array to sample. 4080 * @param {number} n The number of elements to sample. 4081 * @returns {Array} Returns the random elements. 4082 */ 4083 function arraySampleSize(array, n) { 4084 return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length)); 4085 } 4086 4087 /** 4088 * A specialized version of `_.shuffle` for arrays. 4089 * 4090 * @private 4091 * @param {Array} array The array to shuffle. 4092 * @returns {Array} Returns the new shuffled array. 4093 */ 4094 function arrayShuffle(array) { 4095 return shuffleSelf(copyArray(array)); 4096 } 4097 4098 /** 4099 * This function is like `assignValue` except that it doesn't assign 4100 * `undefined` values. 4101 * 4102 * @private 4103 * @param {Object} object The object to modify. 4104 * @param {string} key The key of the property to assign. 4105 * @param {*} value The value to assign. 4106 */ 4107 function assignMergeValue(object, key, value) { 4108 if ((value !== undefined && !eq(object[key], value)) || 4109 (value === undefined && !(key in object))) { 4110 baseAssignValue(object, key, value); 4111 } 4112 } 4113 4114 /** 4115 * Assigns `value` to `key` of `object` if the existing value is not equivalent 4116 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) 4117 * for equality comparisons. 4118 * 4119 * @private 4120 * @param {Object} object The object to modify. 4121 * @param {string} key The key of the property to assign. 4122 * @param {*} value The value to assign. 4123 */ 4124 function assignValue(object, key, value) { 4125 var objValue = object[key]; 4126 if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || 4127 (value === undefined && !(key in object))) { 4128 baseAssignValue(object, key, value); 4129 } 4130 } 4131 4132 /** 4133 * Gets the index at which the `key` is found in `array` of key-value pairs. 4134 * 4135 * @private 4136 * @param {Array} array The array to inspect. 4137 * @param {*} key The key to search for. 4138 * @returns {number} Returns the index of the matched value, else `-1`. 4139 */ 4140 function assocIndexOf(array, key) { 4141 var length = array.length; 4142 while (length--) { 4143 if (eq(array[length][0], key)) { 4144 return length; 4145 } 4146 } 4147 return -1; 4148 } 4149 4150 /** 4151 * Aggregates elements of `collection` on `accumulator` with keys transformed 4152 * by `iteratee` and values set by `setter`. 4153 * 4154 * @private 4155 * @param {Array|Object} collection The collection to iterate over. 4156 * @param {Function} setter The function to set `accumulator` values. 4157 * @param {Function} iteratee The iteratee to transform keys. 4158 * @param {Object} accumulator The initial aggregated object. 4159 * @returns {Function} Returns `accumulator`. 4160 */ 4161 function baseAggregator(collection, setter, iteratee, accumulator) { 4162 baseEach(collection, function(value, key, collection) { 4163 setter(accumulator, value, iteratee(value), collection); 4164 }); 4165 return accumulator; 4166 } 4167 4168 /** 4169 * The base implementation of `_.assign` without support for multiple sources 4170 * or `customizer` functions. 4171 * 4172 * @private 4173 * @param {Object} object The destination object. 4174 * @param {Object} source The source object. 4175 * @returns {Object} Returns `object`. 4176 */ 4177 function baseAssign(object, source) { 4178 return object && copyObject(source, keys(source), object); 4179 } 4180 4181 /** 4182 * The base implementation of `_.assignIn` without support for multiple sources 4183 * or `customizer` functions. 4184 * 4185 * @private 4186 * @param {Object} object The destination object. 4187 * @param {Object} source The source object. 4188 * @returns {Object} Returns `object`. 4189 */ 4190 function baseAssignIn(object, source) { 4191 return object && copyObject(source, keysIn(source), object); 4192 } 4193 4194 /** 4195 * The base implementation of `assignValue` and `assignMergeValue` without 4196 * value checks. 4197 * 4198 * @private 4199 * @param {Object} object The object to modify. 4200 * @param {string} key The key of the property to assign. 4201 * @param {*} value The value to assign. 4202 */ 4203 function baseAssignValue(object, key, value) { 4204 if (key == '__proto__' && defineProperty) { 4205 defineProperty(object, key, { 4206 'configurable': true, 4207 'enumerable': true, 4208 'value': value, 4209 'writable': true 4210 }); 4211 } else { 4212 object[key] = value; 4213 } 4214 } 4215 4216 /** 4217 * The base implementation of `_.at` without support for individual paths. 4218 * 4219 * @private 4220 * @param {Object} object The object to iterate over. 4221 * @param {string[]} paths The property paths to pick. 4222 * @returns {Array} Returns the picked elements. 4223 */ 4224 function baseAt(object, paths) { 4225 var index = -1, 4226 length = paths.length, 4227 result = Array(length), 4228 skip = object == null; 4229 4230 while (++index < length) { 4231 result[index] = skip ? undefined : get(object, paths[index]); 4232 } 4233 return result; 4234 } 4235 4236 /** 4237 * The base implementation of `_.clamp` which doesn't coerce arguments. 4238 * 4239 * @private 4240 * @param {number} number The number to clamp. 4241 * @param {number} [lower] The lower bound. 4242 * @param {number} upper The upper bound. 4243 * @returns {number} Returns the clamped number. 4244 */ 4245 function baseClamp(number, lower, upper) { 4246 if (number === number) { 4247 if (upper !== undefined) { 4248 number = number <= upper ? number : upper; 4249 } 4250 if (lower !== undefined) { 4251 number = number >= lower ? number : lower; 4252 } 4253 } 4254 return number; 4255 } 4256 4257 /** 4258 * The base implementation of `_.clone` and `_.cloneDeep` which tracks 4259 * traversed objects. 4260 * 4261 * @private 4262 * @param {*} value The value to clone. 4263 * @param {boolean} bitmask The bitmask flags. 4264 * 1 - Deep clone 4265 * 2 - Flatten inherited properties 4266 * 4 - Clone symbols 4267 * @param {Function} [customizer] The function to customize cloning. 4268 * @param {string} [key] The key of `value`. 4269 * @param {Object} [object] The parent object of `value`. 4270 * @param {Object} [stack] Tracks traversed objects and their clone counterparts. 4271 * @returns {*} Returns the cloned value. 4272 */ 4273 function baseClone(value, bitmask, customizer, key, object, stack) { 4274 var result, 4275 isDeep = bitmask & CLONE_DEEP_FLAG, 4276 isFlat = bitmask & CLONE_FLAT_FLAG, 4277 isFull = bitmask & CLONE_SYMBOLS_FLAG; 4278 4279 if (customizer) { 4280 result = object ? customizer(value, key, object, stack) : customizer(value); 4281 } 4282 if (result !== undefined) { 4283 return result; 4284 } 4285 if (!isObject(value)) { 4286 return value; 4287 } 4288 var isArr = isArray(value); 4289 if (isArr) { 4290 result = initCloneArray(value); 4291 if (!isDeep) { 4292 return copyArray(value, result); 4293 } 4294 } else { 4295 var tag = getTag(value), 4296 isFunc = tag == funcTag || tag == genTag; 4297 4298 if (isBuffer(value)) { 4299 return cloneBuffer(value, isDeep); 4300 } 4301 if (tag == objectTag || tag == argsTag || (isFunc && !object)) { 4302 result = (isFlat || isFunc) ? {} : initCloneObject(value); 4303 if (!isDeep) { 4304 return isFlat 4305 ? copySymbolsIn(value, baseAssignIn(result, value)) 4306 : copySymbols(value, baseAssign(result, value)); 4307 } 4308 } else { 4309 if (!cloneableTags[tag]) { 4310 return object ? value : {}; 4311 } 4312 result = initCloneByTag(value, tag, isDeep); 4313 } 4314 } 4315 // Check for circular references and return its corresponding clone. 4316 stack || (stack = new Stack); 4317 var stacked = stack.get(value); 4318 if (stacked) { 4319 return stacked; 4320 } 4321 stack.set(value, result); 4322 4323 if (isSet(value)) { 4324 value.forEach(function(subValue) { 4325 result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack)); 4326 }); 4327 } else if (isMap(value)) { 4328 value.forEach(function(subValue, key) { 4329 result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack)); 4330 }); 4331 } 4332 4333 var keysFunc = isFull 4334 ? (isFlat ? getAllKeysIn : getAllKeys) 4335 : (isFlat ? keysIn : keys); 4336 4337 var props = isArr ? undefined : keysFunc(value); 4338 arrayEach(props || value, function(subValue, key) { 4339 if (props) { 4340 key = subValue; 4341 subValue = value[key]; 4342 } 4343 // Recursively populate clone (susceptible to call stack limits). 4344 assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack)); 4345 }); 4346 return result; 4347 } 4348 4349 /** 4350 * The base implementation of `_.conforms` which doesn't clone `source`. 4351 * 4352 * @private 4353 * @param {Object} source The object of property predicates to conform to. 4354 * @returns {Function} Returns the new spec function. 4355 */ 4356 function baseConforms(source) { 4357 var props = keys(source); 4358 return function(object) { 4359 return baseConformsTo(object, source, props); 4360 }; 4361 } 4362 4363 /** 4364 * The base implementation of `_.conformsTo` which accepts `props` to check. 4365 * 4366 * @private 4367 * @param {Object} object The object to inspect. 4368 * @param {Object} source The object of property predicates to conform to. 4369 * @returns {boolean} Returns `true` if `object` conforms, else `false`. 4370 */ 4371 function baseConformsTo(object, source, props) { 4372 var length = props.length; 4373 if (object == null) { 4374 return !length; 4375 } 4376 object = Object(object); 4377 while (length--) { 4378 var key = props[length], 4379 predicate = source[key], 4380 value = object[key]; 4381 4382 if ((value === undefined && !(key in object)) || !predicate(value)) { 4383 return false; 4384 } 4385 } 4386 return true; 4387 } 4388 4389 /** 4390 * The base implementation of `_.delay` and `_.defer` which accepts `args` 4391 * to provide to `func`. 4392 * 4393 * @private 4394 * @param {Function} func The function to delay. 4395 * @param {number} wait The number of milliseconds to delay invocation. 4396 * @param {Array} args The arguments to provide to `func`. 4397 * @returns {number|Object} Returns the timer id or timeout object. 4398 */ 4399 function baseDelay(func, wait, args) { 4400 if (typeof func != 'function') { 4401 throw new TypeError(FUNC_ERROR_TEXT); 4402 } 4403 return setTimeout(function() { func.apply(undefined, args); }, wait); 4404 } 4405 4406 /** 4407 * The base implementation of methods like `_.difference` without support 4408 * for excluding multiple arrays or iteratee shorthands. 4409 * 4410 * @private 4411 * @param {Array} array The array to inspect. 4412 * @param {Array} values The values to exclude. 4413 * @param {Function} [iteratee] The iteratee invoked per element. 4414 * @param {Function} [comparator] The comparator invoked per element. 4415 * @returns {Array} Returns the new array of filtered values. 4416 */ 4417 function baseDifference(array, values, iteratee, comparator) { 4418 var index = -1, 4419 includes = arrayIncludes, 4420 isCommon = true, 4421 length = array.length, 4422 result = [], 4423 valuesLength = values.length; 4424 4425 if (!length) { 4426 return result; 4427 } 4428 if (iteratee) { 4429 values = arrayMap(values, baseUnary(iteratee)); 4430 } 4431 if (comparator) { 4432 includes = arrayIncludesWith; 4433 isCommon = false; 4434 } 4435 else if (values.length >= LARGE_ARRAY_SIZE) { 4436 includes = cacheHas; 4437 isCommon = false; 4438 values = new SetCache(values); 4439 } 4440 outer: 4441 while (++index < length) { 4442 var value = array[index], 4443 computed = iteratee == null ? value : iteratee(value); 4444 4445 value = (comparator || value !== 0) ? value : 0; 4446 if (isCommon && computed === computed) { 4447 var valuesIndex = valuesLength; 4448 while (valuesIndex--) { 4449 if (values[valuesIndex] === computed) { 4450 continue outer; 4451 } 4452 } 4453 result.push(value); 4454 } 4455 else if (!includes(values, computed, comparator)) { 4456 result.push(value); 4457 } 4458 } 4459 return result; 4460 } 4461 4462 /** 4463 * The base implementation of `_.forEach` without support for iteratee shorthands. 4464 * 4465 * @private 4466 * @param {Array|Object} collection The collection to iterate over. 4467 * @param {Function} iteratee The function invoked per iteration. 4468 * @returns {Array|Object} Returns `collection`. 4469 */ 4470 var baseEach = createBaseEach(baseForOwn); 4471 4472 /** 4473 * The base implementation of `_.forEachRight` without support for iteratee shorthands. 4474 * 4475 * @private 4476 * @param {Array|Object} collection The collection to iterate over. 4477 * @param {Function} iteratee The function invoked per iteration. 4478 * @returns {Array|Object} Returns `collection`. 4479 */ 4480 var baseEachRight = createBaseEach(baseForOwnRight, true); 4481 4482 /** 4483 * The base implementation of `_.every` without support for iteratee shorthands. 4484 * 4485 * @private 4486 * @param {Array|Object} collection The collection to iterate over. 4487 * @param {Function} predicate The function invoked per iteration. 4488 * @returns {boolean} Returns `true` if all elements pass the predicate check, 4489 * else `false` 4490 */ 4491 function baseEvery(collection, predicate) { 4492 var result = true; 4493 baseEach(collection, function(value, index, collection) { 4494 result = !!predicate(value, index, collection); 4495 return result; 4496 }); 4497 return result; 4498 } 4499 4500 /** 4501 * The base implementation of methods like `_.max` and `_.min` which accepts a 4502 * `comparator` to determine the extremum value. 4503 * 4504 * @private 4505 * @param {Array} array The array to iterate over. 4506 * @param {Function} iteratee The iteratee invoked per iteration. 4507 * @param {Function} comparator The comparator used to compare values. 4508 * @returns {*} Returns the extremum value. 4509 */ 4510 function baseExtremum(array, iteratee, comparator) { 4511 var index = -1, 4512 length = array.length; 4513 4514 while (++index < length) { 4515 var value = array[index], 4516 current = iteratee(value); 4517 4518 if (current != null && (computed === undefined 4519 ? (current === current && !isSymbol(current)) 4520 : comparator(current, computed) 4521 )) { 4522 var computed = current, 4523 result = value; 4524 } 4525 } 4526 return result; 4527 } 4528 4529 /** 4530 * The base implementation of `_.fill` without an iteratee call guard. 4531 * 4532 * @private 4533 * @param {Array} array The array to fill. 4534 * @param {*} value The value to fill `array` with. 4535 * @param {number} [start=0] The start position. 4536 * @param {number} [end=array.length] The end position. 4537 * @returns {Array} Returns `array`. 4538 */ 4539 function baseFill(array, value, start, end) { 4540 var length = array.length; 4541 4542 start = toInteger(start); 4543 if (start < 0) { 4544 start = -start > length ? 0 : (length + start); 4545 } 4546 end = (end === undefined || end > length) ? length : toInteger(end); 4547 if (end < 0) { 4548 end += length; 4549 } 4550 end = start > end ? 0 : toLength(end); 4551 while (start < end) { 4552 array[start++] = value; 4553 } 4554 return array; 4555 } 4556 4557 /** 4558 * The base implementation of `_.filter` without support for iteratee shorthands. 4559 * 4560 * @private 4561 * @param {Array|Object} collection The collection to iterate over. 4562 * @param {Function} predicate The function invoked per iteration. 4563 * @returns {Array} Returns the new filtered array. 4564 */ 4565 function baseFilter(collection, predicate) { 4566 var result = []; 4567 baseEach(collection, function(value, index, collection) { 4568 if (predicate(value, index, collection)) { 4569 result.push(value); 4570 } 4571 }); 4572 return result; 4573 } 4574 4575 /** 4576 * The base implementation of `_.flatten` with support for restricting flattening. 4577 * 4578 * @private 4579 * @param {Array} array The array to flatten. 4580 * @param {number} depth The maximum recursion depth. 4581 * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. 4582 * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. 4583 * @param {Array} [result=[]] The initial result value. 4584 * @returns {Array} Returns the new flattened array. 4585 */ 4586 function baseFlatten(array, depth, predicate, isStrict, result) { 4587 var index = -1, 4588 length = array.length; 4589 4590 predicate || (predicate = isFlattenable); 4591 result || (result = []); 4592 4593 while (++index < length) { 4594 var value = array[index]; 4595 if (depth > 0 && predicate(value)) { 4596 if (depth > 1) { 4597 // Recursively flatten arrays (susceptible to call stack limits). 4598 baseFlatten(value, depth - 1, predicate, isStrict, result); 4599 } else { 4600 arrayPush(result, value); 4601 } 4602 } else if (!isStrict) { 4603 result[result.length] = value; 4604 } 4605 } 4606 return result; 4607 } 4608 4609 /** 4610 * The base implementation of `baseForOwn` which iterates over `object` 4611 * properties returned by `keysFunc` and invokes `iteratee` for each property. 4612 * Iteratee functions may exit iteration early by explicitly returning `false`. 4613 * 4614 * @private 4615 * @param {Object} object The object to iterate over. 4616 * @param {Function} iteratee The function invoked per iteration. 4617 * @param {Function} keysFunc The function to get the keys of `object`. 4618 * @returns {Object} Returns `object`. 4619 */ 4620 var baseFor = createBaseFor(); 4621 4622 /** 4623 * This function is like `baseFor` except that it iterates over properties 4624 * in the opposite order. 4625 * 4626 * @private 4627 * @param {Object} object The object to iterate over. 4628 * @param {Function} iteratee The function invoked per iteration. 4629 * @param {Function} keysFunc The function to get the keys of `object`. 4630 * @returns {Object} Returns `object`. 4631 */ 4632 var baseForRight = createBaseFor(true); 4633 4634 /** 4635 * The base implementation of `_.forOwn` without support for iteratee shorthands. 4636 * 4637 * @private 4638 * @param {Object} object The object to iterate over. 4639 * @param {Function} iteratee The function invoked per iteration. 4640 * @returns {Object} Returns `object`. 4641 */ 4642 function baseForOwn(object, iteratee) { 4643 return object && baseFor(object, iteratee, keys); 4644 } 4645 4646 /** 4647 * The base implementation of `_.forOwnRight` without support for iteratee shorthands. 4648 * 4649 * @private 4650 * @param {Object} object The object to iterate over. 4651 * @param {Function} iteratee The function invoked per iteration. 4652 * @returns {Object} Returns `object`. 4653 */ 4654 function baseForOwnRight(object, iteratee) { 4655 return object && baseForRight(object, iteratee, keys); 4656 } 4657 4658 /** 4659 * The base implementation of `_.functions` which creates an array of 4660 * `object` function property names filtered from `props`. 4661 * 4662 * @private 4663 * @param {Object} object The object to inspect. 4664 * @param {Array} props The property names to filter. 4665 * @returns {Array} Returns the function names. 4666 */ 4667 function baseFunctions(object, props) { 4668 return arrayFilter(props, function(key) { 4669 return isFunction(object[key]); 4670 }); 4671 } 4672 4673 /** 4674 * The base implementation of `_.get` without support for default values. 4675 * 4676 * @private 4677 * @param {Object} object The object to query. 4678 * @param {Array|string} path The path of the property to get. 4679 * @returns {*} Returns the resolved value. 4680 */ 4681 function baseGet(object, path) { 4682 path = castPath(path, object); 4683 4684 var index = 0, 4685 length = path.length; 4686 4687 while (object != null && index < length) { 4688 object = object[toKey(path[index++])]; 4689 } 4690 return (index && index == length) ? object : undefined; 4691 } 4692 4693 /** 4694 * The base implementation of `getAllKeys` and `getAllKeysIn` which uses 4695 * `keysFunc` and `symbolsFunc` to get the enumerable property names and 4696 * symbols of `object`. 4697 * 4698 * @private 4699 * @param {Object} object The object to query. 4700 * @param {Function} keysFunc The function to get the keys of `object`. 4701 * @param {Function} symbolsFunc The function to get the symbols of `object`. 4702 * @returns {Array} Returns the array of property names and symbols. 4703 */ 4704 function baseGetAllKeys(object, keysFunc, symbolsFunc) { 4705 var result = keysFunc(object); 4706 return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); 4707 } 4708 4709 /** 4710 * The base implementation of `getTag` without fallbacks for buggy environments. 4711 * 4712 * @private 4713 * @param {*} value The value to query. 4714 * @returns {string} Returns the `toStringTag`. 4715 */ 4716 function baseGetTag(value) { 4717 if (value == null) { 4718 return value === undefined ? undefinedTag : nullTag; 4719 } 4720 return (symToStringTag && symToStringTag in Object(value)) 4721 ? getRawTag(value) 4722 : objectToString(value); 4723 } 4724 4725 /** 4726 * The base implementation of `_.gt` which doesn't coerce arguments. 4727 * 4728 * @private 4729 * @param {*} value The value to compare. 4730 * @param {*} other The other value to compare. 4731 * @returns {boolean} Returns `true` if `value` is greater than `other`, 4732 * else `false`. 4733 */ 4734 function baseGt(value, other) { 4735 return value > other; 4736 } 4737 4738 /** 4739 * The base implementation of `_.has` without support for deep paths. 4740 * 4741 * @private 4742 * @param {Object} [object] The object to query. 4743 * @param {Array|string} key The key to check. 4744 * @returns {boolean} Returns `true` if `key` exists, else `false`. 4745 */ 4746 function baseHas(object, key) { 4747 return object != null && hasOwnProperty.call(object, key); 4748 } 4749 4750 /** 4751 * The base implementation of `_.hasIn` without support for deep paths. 4752 * 4753 * @private 4754 * @param {Object} [object] The object to query. 4755 * @param {Array|string} key The key to check. 4756 * @returns {boolean} Returns `true` if `key` exists, else `false`. 4757 */ 4758 function baseHasIn(object, key) { 4759 return object != null && key in Object(object); 4760 } 4761 4762 /** 4763 * The base implementation of `_.inRange` which doesn't coerce arguments. 4764 * 4765 * @private 4766 * @param {number} number The number to check. 4767 * @param {number} start The start of the range. 4768 * @param {number} end The end of the range. 4769 * @returns {boolean} Returns `true` if `number` is in the range, else `false`. 4770 */ 4771 function baseInRange(number, start, end) { 4772 return number >= nativeMin(start, end) && number < nativeMax(start, end); 4773 } 4774 4775 /** 4776 * The base implementation of methods like `_.intersection`, without support 4777 * for iteratee shorthands, that accepts an array of arrays to inspect. 4778 * 4779 * @private 4780 * @param {Array} arrays The arrays to inspect. 4781 * @param {Function} [iteratee] The iteratee invoked per element. 4782 * @param {Function} [comparator] The comparator invoked per element. 4783 * @returns {Array} Returns the new array of shared values. 4784 */ 4785 function baseIntersection(arrays, iteratee, comparator) { 4786 var includes = comparator ? arrayIncludesWith : arrayIncludes, 4787 length = arrays[0].length, 4788 othLength = arrays.length, 4789 othIndex = othLength, 4790 caches = Array(othLength), 4791 maxLength = Infinity, 4792 result = []; 4793 4794 while (othIndex--) { 4795 var array = arrays[othIndex]; 4796 if (othIndex && iteratee) { 4797 array = arrayMap(array, baseUnary(iteratee)); 4798 } 4799 maxLength = nativeMin(array.length, maxLength); 4800 caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120)) 4801 ? new SetCache(othIndex && array) 4802 : undefined; 4803 } 4804 array = arrays[0]; 4805 4806 var index = -1, 4807 seen = caches[0]; 4808 4809 outer: 4810 while (++index < length && result.length < maxLength) { 4811 var value = array[index], 4812 computed = iteratee ? iteratee(value) : value; 4813 4814 value = (comparator || value !== 0) ? value : 0; 4815 if (!(seen 4816 ? cacheHas(seen, computed) 4817 : includes(result, computed, comparator) 4818 )) { 4819 othIndex = othLength; 4820 while (--othIndex) { 4821 var cache = caches[othIndex]; 4822 if (!(cache 4823 ? cacheHas(cache, computed) 4824 : includes(arrays[othIndex], computed, comparator)) 4825 ) { 4826 continue outer; 4827 } 4828 } 4829 if (seen) { 4830 seen.push(computed); 4831 } 4832 result.push(value); 4833 } 4834 } 4835 return result; 4836 } 4837 4838 /** 4839 * The base implementation of `_.invert` and `_.invertBy` which inverts 4840 * `object` with values transformed by `iteratee` and set by `setter`. 4841 * 4842 * @private 4843 * @param {Object} object The object to iterate over. 4844 * @param {Function} setter The function to set `accumulator` values. 4845 * @param {Function} iteratee The iteratee to transform values. 4846 * @param {Object} accumulator The initial inverted object. 4847 * @returns {Function} Returns `accumulator`. 4848 */ 4849 function baseInverter(object, setter, iteratee, accumulator) { 4850 baseForOwn(object, function(value, key, object) { 4851 setter(accumulator, iteratee(value), key, object); 4852 }); 4853 return accumulator; 4854 } 4855 4856 /** 4857 * The base implementation of `_.invoke` without support for individual 4858 * method arguments. 4859 * 4860 * @private 4861 * @param {Object} object The object to query. 4862 * @param {Array|string} path The path of the method to invoke. 4863 * @param {Array} args The arguments to invoke the method with. 4864 * @returns {*} Returns the result of the invoked method. 4865 */ 4866 function baseInvoke(object, path, args) { 4867 path = castPath(path, object); 4868 object = parent(object, path); 4869 var func = object == null ? object : object[toKey(last(path))]; 4870 return func == null ? undefined : apply(func, object, args); 4871 } 4872 4873 /** 4874 * The base implementation of `_.isArguments`. 4875 * 4876 * @private 4877 * @param {*} value The value to check. 4878 * @returns {boolean} Returns `true` if `value` is an `arguments` object, 4879 */ 4880 function baseIsArguments(value) { 4881 return isObjectLike(value) && baseGetTag(value) == argsTag; 4882 } 4883 4884 /** 4885 * The base implementation of `_.isArrayBuffer` without Node.js optimizations. 4886 * 4887 * @private 4888 * @param {*} value The value to check. 4889 * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. 4890 */ 4891 function baseIsArrayBuffer(value) { 4892 return isObjectLike(value) && baseGetTag(value) == arrayBufferTag; 4893 } 4894 4895 /** 4896 * The base implementation of `_.isDate` without Node.js optimizations. 4897 * 4898 * @private 4899 * @param {*} value The value to check. 4900 * @returns {boolean} Returns `true` if `value` is a date object, else `false`. 4901 */ 4902 function baseIsDate(value) { 4903 return isObjectLike(value) && baseGetTag(value) == dateTag; 4904 } 4905 4906 /** 4907 * The base implementation of `_.isEqual` which supports partial comparisons 4908 * and tracks traversed objects. 4909 * 4910 * @private 4911 * @param {*} value The value to compare. 4912 * @param {*} other The other value to compare. 4913 * @param {boolean} bitmask The bitmask flags. 4914 * 1 - Unordered comparison 4915 * 2 - Partial comparison 4916 * @param {Function} [customizer] The function to customize comparisons. 4917 * @param {Object} [stack] Tracks traversed `value` and `other` objects. 4918 * @returns {boolean} Returns `true` if the values are equivalent, else `false`. 4919 */ 4920 function baseIsEqual(value, other, bitmask, customizer, stack) { 4921 if (value === other) { 4922 return true; 4923 } 4924 if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { 4925 return value !== value && other !== other; 4926 } 4927 return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); 4928 } 4929 4930 /** 4931 * A specialized version of `baseIsEqual` for arrays and objects which performs 4932 * deep comparisons and tracks traversed objects enabling objects with circular 4933 * references to be compared. 4934 * 4935 * @private 4936 * @param {Object} object The object to compare. 4937 * @param {Object} other The other object to compare. 4938 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. 4939 * @param {Function} customizer The function to customize comparisons. 4940 * @param {Function} equalFunc The function to determine equivalents of values. 4941 * @param {Object} [stack] Tracks traversed `object` and `other` objects. 4942 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. 4943 */ 4944 function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { 4945 var objIsArr = isArray(object), 4946 othIsArr = isArray(other), 4947 objTag = objIsArr ? arrayTag : getTag(object), 4948 othTag = othIsArr ? arrayTag : getTag(other); 4949 4950 objTag = objTag == argsTag ? objectTag : objTag; 4951 othTag = othTag == argsTag ? objectTag : othTag; 4952 4953 var objIsObj = objTag == objectTag, 4954 othIsObj = othTag == objectTag, 4955 isSameTag = objTag == othTag; 4956 4957 if (isSameTag && isBuffer(object)) { 4958 if (!isBuffer(other)) { 4959 return false; 4960 } 4961 objIsArr = true; 4962 objIsObj = false; 4963 } 4964 if (isSameTag && !objIsObj) { 4965 stack || (stack = new Stack); 4966 return (objIsArr || isTypedArray(object)) 4967 ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) 4968 : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); 4969 } 4970 if (!(bitmask & COMPARE_PARTIAL_FLAG)) { 4971 var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), 4972 othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); 4973 4974 if (objIsWrapped || othIsWrapped) { 4975 var objUnwrapped = objIsWrapped ? object.value() : object, 4976 othUnwrapped = othIsWrapped ? other.value() : other; 4977 4978 stack || (stack = new Stack); 4979 return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); 4980 } 4981 } 4982 if (!isSameTag) { 4983 return false; 4984 } 4985 stack || (stack = new Stack); 4986 return equalObjects(object, other, bitmask, customizer, equalFunc, stack); 4987 } 4988 4989 /** 4990 * The base implementation of `_.isMap` without Node.js optimizations. 4991 * 4992 * @private 4993 * @param {*} value The value to check. 4994 * @returns {boolean} Returns `true` if `value` is a map, else `false`. 4995 */ 4996 function baseIsMap(value) { 4997 return isObjectLike(value) && getTag(value) == mapTag; 4998 } 4999 5000 /** 5001 * The base implementation of `_.isMatch` without support for iteratee shorthands. 5002 * 5003 * @private 5004 * @param {Object} object The object to inspect. 5005 * @param {Object} source The object of property values to match. 5006 * @param {Array} matchData The property names, values, and compare flags to match. 5007 * @param {Function} [customizer] The function to customize comparisons. 5008 * @returns {boolean} Returns `true` if `object` is a match, else `false`. 5009 */ 5010 function baseIsMatch(object, source, matchData, customizer) { 5011 var index = matchData.length, 5012 length = index, 5013 noCustomizer = !customizer; 5014 5015 if (object == null) { 5016 return !length; 5017 } 5018 object = Object(object); 5019 while (index--) { 5020 var data = matchData[index]; 5021 if ((noCustomizer && data[2]) 5022 ? data[1] !== object[data[0]] 5023 : !(data[0] in object) 5024 ) { 5025 return false; 5026 } 5027 } 5028 while (++index < length) { 5029 data = matchData[index]; 5030 var key = data[0], 5031 objValue = object[key], 5032 srcValue = data[1]; 5033 5034 if (noCustomizer && data[2]) { 5035 if (objValue === undefined && !(key in object)) { 5036 return false; 5037 } 5038 } else { 5039 var stack = new Stack; 5040 if (customizer) { 5041 var result = customizer(objValue, srcValue, key, object, source, stack); 5042 } 5043 if (!(result === undefined 5044 ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) 5045 : result 5046 )) { 5047 return false; 5048 } 5049 } 5050 } 5051 return true; 5052 } 5053 5054 /** 5055 * The base implementation of `_.isNative` without bad shim checks. 5056 * 5057 * @private 5058 * @param {*} value The value to check. 5059 * @returns {boolean} Returns `true` if `value` is a native function, 5060 * else `false`. 5061 */ 5062 function baseIsNative(value) { 5063 if (!isObject(value) || isMasked(value)) { 5064 return false; 5065 } 5066 var pattern = isFunction(value) ? reIsNative : reIsHostCtor; 5067 return pattern.test(toSource(value)); 5068 } 5069 5070 /** 5071 * The base implementation of `_.isRegExp` without Node.js optimizations. 5072 * 5073 * @private 5074 * @param {*} value The value to check. 5075 * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. 5076 */ 5077 function baseIsRegExp(value) { 5078 return isObjectLike(value) && baseGetTag(value) == regexpTag; 5079 } 5080 5081 /** 5082 * The base implementation of `_.isSet` without Node.js optimizations. 5083 * 5084 * @private 5085 * @param {*} value The value to check. 5086 * @returns {boolean} Returns `true` if `value` is a set, else `false`. 5087 */ 5088 function baseIsSet(value) { 5089 return isObjectLike(value) && getTag(value) == setTag; 5090 } 5091 5092 /** 5093 * The base implementation of `_.isTypedArray` without Node.js optimizations. 5094 * 5095 * @private 5096 * @param {*} value The value to check. 5097 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. 5098 */ 5099 function baseIsTypedArray(value) { 5100 return isObjectLike(value) && 5101 isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; 5102 } 5103 5104 /** 5105 * The base implementation of `_.iteratee`. 5106 * 5107 * @private 5108 * @param {*} [value=_.identity] The value to convert to an iteratee. 5109 * @returns {Function} Returns the iteratee. 5110 */ 5111 function baseIteratee(value) { 5112 // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. 5113 // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. 5114 if (typeof value == 'function') { 5115 return value; 5116 } 5117 if (value == null) { 5118 return identity; 5119 } 5120 if (typeof value == 'object') { 5121 return isArray(value) 5122 ? baseMatchesProperty(value[0], value[1]) 5123 : baseMatches(value); 5124 } 5125 return property(value); 5126 } 5127 5128 /** 5129 * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. 5130 * 5131 * @private 5132 * @param {Object} object The object to query. 5133 * @returns {Array} Returns the array of property names. 5134 */ 5135 function baseKeys(object) { 5136 if (!isPrototype(object)) { 5137 return nativeKeys(object); 5138 } 5139 var result = []; 5140 for (var key in Object(object)) { 5141 if (hasOwnProperty.call(object, key) && key != 'constructor') { 5142 result.push(key); 5143 } 5144 } 5145 return result; 5146 } 5147 5148 /** 5149 * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. 5150 * 5151 * @private 5152 * @param {Object} object The object to query. 5153 * @returns {Array} Returns the array of property names. 5154 */ 5155 function baseKeysIn(object) { 5156 if (!isObject(object)) { 5157 return nativeKeysIn(object); 5158 } 5159 var isProto = isPrototype(object), 5160 result = []; 5161 5162 for (var key in object) { 5163 if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { 5164 result.push(key); 5165 } 5166 } 5167 return result; 5168 } 5169 5170 /** 5171 * The base implementation of `_.lt` which doesn't coerce arguments. 5172 * 5173 * @private 5174 * @param {*} value The value to compare. 5175 * @param {*} other The other value to compare. 5176 * @returns {boolean} Returns `true` if `value` is less than `other`, 5177 * else `false`. 5178 */ 5179 function baseLt(value, other) { 5180 return value < other; 5181 } 5182 5183 /** 5184 * The base implementation of `_.map` without support for iteratee shorthands. 5185 * 5186 * @private 5187 * @param {Array|Object} collection The collection to iterate over. 5188 * @param {Function} iteratee The function invoked per iteration. 5189 * @returns {Array} Returns the new mapped array. 5190 */ 5191 function baseMap(collection, iteratee) { 5192 var index = -1, 5193 result = isArrayLike(collection) ? Array(collection.length) : []; 5194 5195 baseEach(collection, function(value, key, collection) { 5196 result[++index] = iteratee(value, key, collection); 5197 }); 5198 return result; 5199 } 5200 5201 /** 5202 * The base implementation of `_.matches` which doesn't clone `source`. 5203 * 5204 * @private 5205 * @param {Object} source The object of property values to match. 5206 * @returns {Function} Returns the new spec function. 5207 */ 5208 function baseMatches(source) { 5209 var matchData = getMatchData(source); 5210 if (matchData.length == 1 && matchData[0][2]) { 5211 return matchesStrictComparable(matchData[0][0], matchData[0][1]); 5212 } 5213 return function(object) { 5214 return object === source || baseIsMatch(object, source, matchData); 5215 }; 5216 } 5217 5218 /** 5219 * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. 5220 * 5221 * @private 5222 * @param {string} path The path of the property to get. 5223 * @param {*} srcValue The value to match. 5224 * @returns {Function} Returns the new spec function. 5225 */ 5226 function baseMatchesProperty(path, srcValue) { 5227 if (isKey(path) && isStrictComparable(srcValue)) { 5228 return matchesStrictComparable(toKey(path), srcValue); 5229 } 5230 return function(object) { 5231 var objValue = get(object, path); 5232 return (objValue === undefined && objValue === srcValue) 5233 ? hasIn(object, path) 5234 : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG); 5235 }; 5236 } 5237 5238 /** 5239 * The base implementation of `_.merge` without support for multiple sources. 5240 * 5241 * @private 5242 * @param {Object} object The destination object. 5243 * @param {Object} source The source object. 5244 * @param {number} srcIndex The index of `source`. 5245 * @param {Function} [customizer] The function to customize merged values. 5246 * @param {Object} [stack] Tracks traversed source values and their merged 5247 * counterparts. 5248 */ 5249 function baseMerge(object, source, srcIndex, customizer, stack) { 5250 if (object === source) { 5251 return; 5252 } 5253 baseFor(source, function(srcValue, key) { 5254 stack || (stack = new Stack); 5255 if (isObject(srcValue)) { 5256 baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); 5257 } 5258 else { 5259 var newValue = customizer 5260 ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack) 5261 : undefined; 5262 5263 if (newValue === undefined) { 5264 newValue = srcValue; 5265 } 5266 assignMergeValue(object, key, newValue); 5267 } 5268 }, keysIn); 5269 } 5270 5271 /** 5272 * A specialized version of `baseMerge` for arrays and objects which performs 5273 * deep merges and tracks traversed objects enabling objects with circular 5274 * references to be merged. 5275 * 5276 * @private 5277 * @param {Object} object The destination object. 5278 * @param {Object} source The source object. 5279 * @param {string} key The key of the value to merge. 5280 * @param {number} srcIndex The index of `source`. 5281 * @param {Function} mergeFunc The function to merge values. 5282 * @param {Function} [customizer] The function to customize assigned values. 5283 * @param {Object} [stack] Tracks traversed source values and their merged 5284 * counterparts. 5285 */ 5286 function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { 5287 var objValue = safeGet(object, key), 5288 srcValue = safeGet(source, key), 5289 stacked = stack.get(srcValue); 5290 5291 if (stacked) { 5292 assignMergeValue(object, key, stacked); 5293 return; 5294 } 5295 var newValue = customizer 5296 ? customizer(objValue, srcValue, (key + ''), object, source, stack) 5297 : undefined; 5298 5299 var isCommon = newValue === undefined; 5300 5301 if (isCommon) { 5302 var isArr = isArray(srcValue), 5303 isBuff = !isArr && isBuffer(srcValue), 5304 isTyped = !isArr && !isBuff && isTypedArray(srcValue); 5305 5306 newValue = srcValue; 5307 if (isArr || isBuff || isTyped) { 5308 if (isArray(objValue)) { 5309 newValue = objValue; 5310 } 5311 else if (isArrayLikeObject(objValue)) { 5312 newValue = copyArray(objValue); 5313 } 5314 else if (isBuff) { 5315 isCommon = false; 5316 newValue = cloneBuffer(srcValue, true); 5317 } 5318 else if (isTyped) { 5319 isCommon = false; 5320 newValue = cloneTypedArray(srcValue, true); 5321 } 5322 else { 5323 newValue = []; 5324 } 5325 } 5326 else if (isPlainObject(srcValue) || isArguments(srcValue)) { 5327 newValue = objValue; 5328 if (isArguments(objValue)) { 5329 newValue = toPlainObject(objValue); 5330 } 5331 else if (!isObject(objValue) || isFunction(objValue)) { 5332 newValue = initCloneObject(srcValue); 5333 } 5334 } 5335 else { 5336 isCommon = false; 5337 } 5338 } 5339 if (isCommon) { 5340 // Recursively merge objects and arrays (susceptible to call stack limits). 5341 stack.set(srcValue, newValue); 5342 mergeFunc(newValue, srcValue, srcIndex, customizer, stack); 5343 stack['delete'](srcValue); 5344 } 5345 assignMergeValue(object, key, newValue); 5346 } 5347 5348 /** 5349 * The base implementation of `_.nth` which doesn't coerce arguments. 5350 * 5351 * @private 5352 * @param {Array} array The array to query. 5353 * @param {number} n The index of the element to return. 5354 * @returns {*} Returns the nth element of `array`. 5355 */ 5356 function baseNth(array, n) { 5357 var length = array.length; 5358 if (!length) { 5359 return; 5360 } 5361 n += n < 0 ? length : 0; 5362 return isIndex(n, length) ? array[n] : undefined; 5363 } 5364 5365 /** 5366 * The base implementation of `_.orderBy` without param guards. 5367 * 5368 * @private 5369 * @param {Array|Object} collection The collection to iterate over. 5370 * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. 5371 * @param {string[]} orders The sort orders of `iteratees`. 5372 * @returns {Array} Returns the new sorted array. 5373 */ 5374 function baseOrderBy(collection, iteratees, orders) { 5375 if (iteratees.length) { 5376 iteratees = arrayMap(iteratees, function(iteratee) { 5377 if (isArray(iteratee)) { 5378 return function(value) { 5379 return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee); 5380 } 5381 } 5382 return iteratee; 5383 }); 5384 } else { 5385 iteratees = [identity]; 5386 } 5387 5388 var index = -1; 5389 iteratees = arrayMap(iteratees, baseUnary(getIteratee())); 5390 5391 var result = baseMap(collection, function(value, key, collection) { 5392 var criteria = arrayMap(iteratees, function(iteratee) { 5393 return iteratee(value); 5394 }); 5395 return { 'criteria': criteria, 'index': ++index, 'value': value }; 5396 }); 5397 5398 return baseSortBy(result, function(object, other) { 5399 return compareMultiple(object, other, orders); 5400 }); 5401 } 5402 5403 /** 5404 * The base implementation of `_.pick` without support for individual 5405 * property identifiers. 5406 * 5407 * @private 5408 * @param {Object} object The source object. 5409 * @param {string[]} paths The property paths to pick. 5410 * @returns {Object} Returns the new object. 5411 */ 5412 function basePick(object, paths) { 5413 return basePickBy(object, paths, function(value, path) { 5414 return hasIn(object, path); 5415 }); 5416 } 5417 5418 /** 5419 * The base implementation of `_.pickBy` without support for iteratee shorthands. 5420 * 5421 * @private 5422 * @param {Object} object The source object. 5423 * @param {string[]} paths The property paths to pick. 5424 * @param {Function} predicate The function invoked per property. 5425 * @returns {Object} Returns the new object. 5426 */ 5427 function basePickBy(object, paths, predicate) { 5428 var index = -1, 5429 length = paths.length, 5430 result = {}; 5431 5432 while (++index < length) { 5433 var path = paths[index], 5434 value = baseGet(object, path); 5435 5436 if (predicate(value, path)) { 5437 baseSet(result, castPath(path, object), value); 5438 } 5439 } 5440 return result; 5441 } 5442 5443 /** 5444 * A specialized version of `baseProperty` which supports deep paths. 5445 * 5446 * @private 5447 * @param {Array|string} path The path of the property to get. 5448 * @returns {Function} Returns the new accessor function. 5449 */ 5450 function basePropertyDeep(path) { 5451 return function(object) { 5452 return baseGet(object, path); 5453 }; 5454 } 5455 5456 /** 5457 * The base implementation of `_.pullAllBy` without support for iteratee 5458 * shorthands. 5459 * 5460 * @private 5461 * @param {Array} array The array to modify. 5462 * @param {Array} values The values to remove. 5463 * @param {Function} [iteratee] The iteratee invoked per element. 5464 * @param {Function} [comparator] The comparator invoked per element. 5465 * @returns {Array} Returns `array`. 5466 */ 5467 function basePullAll(array, values, iteratee, comparator) { 5468 var indexOf = comparator ? baseIndexOfWith : baseIndexOf, 5469 index = -1, 5470 length = values.length, 5471 seen = array; 5472 5473 if (array === values) { 5474 values = copyArray(values); 5475 } 5476 if (iteratee) { 5477 seen = arrayMap(array, baseUnary(iteratee)); 5478 } 5479 while (++index < length) { 5480 var fromIndex = 0, 5481 value = values[index], 5482 computed = iteratee ? iteratee(value) : value; 5483 5484 while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) { 5485 if (seen !== array) { 5486 splice.call(seen, fromIndex, 1); 5487 } 5488 splice.call(array, fromIndex, 1); 5489 } 5490 } 5491 return array; 5492 } 5493 5494 /** 5495 * The base implementation of `_.pullAt` without support for individual 5496 * indexes or capturing the removed elements. 5497 * 5498 * @private 5499 * @param {Array} array The array to modify. 5500 * @param {number[]} indexes The indexes of elements to remove. 5501 * @returns {Array} Returns `array`. 5502 */ 5503 function basePullAt(array, indexes) { 5504 var length = array ? indexes.length : 0, 5505 lastIndex = length - 1; 5506 5507 while (length--) { 5508 var index = indexes[length]; 5509 if (length == lastIndex || index !== previous) { 5510 var previous = index; 5511 if (isIndex(index)) { 5512 splice.call(array, index, 1); 5513 } else { 5514 baseUnset(array, index); 5515 } 5516 } 5517 } 5518 return array; 5519 } 5520 5521 /** 5522 * The base implementation of `_.random` without support for returning 5523 * floating-point numbers. 5524 * 5525 * @private 5526 * @param {number} lower The lower bound. 5527 * @param {number} upper The upper bound. 5528 * @returns {number} Returns the random number. 5529 */ 5530 function baseRandom(lower, upper) { 5531 return lower + nativeFloor(nativeRandom() * (upper - lower + 1)); 5532 } 5533 5534 /** 5535 * The base implementation of `_.range` and `_.rangeRight` which doesn't 5536 * coerce arguments. 5537 * 5538 * @private 5539 * @param {number} start The start of the range. 5540 * @param {number} end The end of the range. 5541 * @param {number} step The value to increment or decrement by. 5542 * @param {boolean} [fromRight] Specify iterating from right to left. 5543 * @returns {Array} Returns the range of numbers. 5544 */ 5545 function baseRange(start, end, step, fromRight) { 5546 var index = -1, 5547 length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), 5548 result = Array(length); 5549 5550 while (length--) { 5551 result[fromRight ? length : ++index] = start; 5552 start += step; 5553 } 5554 return result; 5555 } 5556 5557 /** 5558 * The base implementation of `_.repeat` which doesn't coerce arguments. 5559 * 5560 * @private 5561 * @param {string} string The string to repeat. 5562 * @param {number} n The number of times to repeat the string. 5563 * @returns {string} Returns the repeated string. 5564 */ 5565 function baseRepeat(string, n) { 5566 var result = ''; 5567 if (!string || n < 1 || n > MAX_SAFE_INTEGER) { 5568 return result; 5569 } 5570 // Leverage the exponentiation by squaring algorithm for a faster repeat. 5571 // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. 5572 do { 5573 if (n % 2) { 5574 result += string; 5575 } 5576 n = nativeFloor(n / 2); 5577 if (n) { 5578 string += string; 5579 } 5580 } while (n); 5581 5582 return result; 5583 } 5584 5585 /** 5586 * The base implementation of `_.rest` which doesn't validate or coerce arguments. 5587 * 5588 * @private 5589 * @param {Function} func The function to apply a rest parameter to. 5590 * @param {number} [start=func.length-1] The start position of the rest parameter. 5591 * @returns {Function} Returns the new function. 5592 */ 5593 function baseRest(func, start) { 5594 return setToString(overRest(func, start, identity), func + ''); 5595 } 5596 5597 /** 5598 * The base implementation of `_.sample`. 5599 * 5600 * @private 5601 * @param {Array|Object} collection The collection to sample. 5602 * @returns {*} Returns the random element. 5603 */ 5604 function baseSample(collection) { 5605 return arraySample(values(collection)); 5606 } 5607 5608 /** 5609 * The base implementation of `_.sampleSize` without param guards. 5610 * 5611 * @private 5612 * @param {Array|Object} collection The collection to sample. 5613 * @param {number} n The number of elements to sample. 5614 * @returns {Array} Returns the random elements. 5615 */ 5616 function baseSampleSize(collection, n) { 5617 var array = values(collection); 5618 return shuffleSelf(array, baseClamp(n, 0, array.length)); 5619 } 5620 5621 /** 5622 * The base implementation of `_.set`. 5623 * 5624 * @private 5625 * @param {Object} object The object to modify. 5626 * @param {Array|string} path The path of the property to set. 5627 * @param {*} value The value to set. 5628 * @param {Function} [customizer] The function to customize path creation. 5629 * @returns {Object} Returns `object`. 5630 */ 5631 function baseSet(object, path, value, customizer) { 5632 if (!isObject(object)) { 5633 return object; 5634 } 5635 path = castPath(path, object); 5636 5637 var index = -1, 5638 length = path.length, 5639 lastIndex = length - 1, 5640 nested = object; 5641 5642 while (nested != null && ++index < length) { 5643 var key = toKey(path[index]), 5644 newValue = value; 5645 5646 if (key === '__proto__' || key === 'constructor' || key === 'prototype') { 5647 return object; 5648 } 5649 5650 if (index != lastIndex) { 5651 var objValue = nested[key]; 5652 newValue = customizer ? customizer(objValue, key, nested) : undefined; 5653 if (newValue === undefined) { 5654 newValue = isObject(objValue) 5655 ? objValue 5656 : (isIndex(path[index + 1]) ? [] : {}); 5657 } 5658 } 5659 assignValue(nested, key, newValue); 5660 nested = nested[key]; 5661 } 5662 return object; 5663 } 5664 5665 /** 5666 * The base implementation of `setData` without support for hot loop shorting. 5667 * 5668 * @private 5669 * @param {Function} func The function to associate metadata with. 5670 * @param {*} data The metadata. 5671 * @returns {Function} Returns `func`. 5672 */ 5673 var baseSetData = !metaMap ? identity : function(func, data) { 5674 metaMap.set(func, data); 5675 return func; 5676 }; 5677 5678 /** 5679 * The base implementation of `setToString` without support for hot loop shorting. 5680 * 5681 * @private 5682 * @param {Function} func The function to modify. 5683 * @param {Function} string The `toString` result. 5684 * @returns {Function} Returns `func`. 5685 */ 5686 var baseSetToString = !defineProperty ? identity : function(func, string) { 5687 return defineProperty(func, 'toString', { 5688 'configurable': true, 5689 'enumerable': false, 5690 'value': constant(string), 5691 'writable': true 5692 }); 5693 }; 5694 5695 /** 5696 * The base implementation of `_.shuffle`. 5697 * 5698 * @private 5699 * @param {Array|Object} collection The collection to shuffle. 5700 * @returns {Array} Returns the new shuffled array. 5701 */ 5702 function baseShuffle(collection) { 5703 return shuffleSelf(values(collection)); 5704 } 5705 5706 /** 5707 * The base implementation of `_.slice` without an iteratee call guard. 5708 * 5709 * @private 5710 * @param {Array} array The array to slice. 5711 * @param {number} [start=0] The start position. 5712 * @param {number} [end=array.length] The end position. 5713 * @returns {Array} Returns the slice of `array`. 5714 */ 5715 function baseSlice(array, start, end) { 5716 var index = -1, 5717 length = array.length; 5718 5719 if (start < 0) { 5720 start = -start > length ? 0 : (length + start); 5721 } 5722 end = end > length ? length : end; 5723 if (end < 0) { 5724 end += length; 5725 } 5726 length = start > end ? 0 : ((end - start) >>> 0); 5727 start >>>= 0; 5728 5729 var result = Array(length); 5730 while (++index < length) { 5731 result[index] = array[index + start]; 5732 } 5733 return result; 5734 } 5735 5736 /** 5737 * The base implementation of `_.some` without support for iteratee shorthands. 5738 * 5739 * @private 5740 * @param {Array|Object} collection The collection to iterate over. 5741 * @param {Function} predicate The function invoked per iteration. 5742 * @returns {boolean} Returns `true` if any element passes the predicate check, 5743 * else `false`. 5744 */ 5745 function baseSome(collection, predicate) { 5746 var result; 5747 5748 baseEach(collection, function(value, index, collection) { 5749 result = predicate(value, index, collection); 5750 return !result; 5751 }); 5752 return !!result; 5753 } 5754 5755 /** 5756 * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which 5757 * performs a binary search of `array` to determine the index at which `value` 5758 * should be inserted into `array` in order to maintain its sort order. 5759 * 5760 * @private 5761 * @param {Array} array The sorted array to inspect. 5762 * @param {*} value The value to evaluate. 5763 * @param {boolean} [retHighest] Specify returning the highest qualified index. 5764 * @returns {number} Returns the index at which `value` should be inserted 5765 * into `array`. 5766 */ 5767 function baseSortedIndex(array, value, retHighest) { 5768 var low = 0, 5769 high = array == null ? low : array.length; 5770 5771 if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) { 5772 while (low < high) { 5773 var mid = (low + high) >>> 1, 5774 computed = array[mid]; 5775 5776 if (computed !== null && !isSymbol(computed) && 5777 (retHighest ? (computed <= value) : (computed < value))) { 5778 low = mid + 1; 5779 } else { 5780 high = mid; 5781 } 5782 } 5783 return high; 5784 } 5785 return baseSortedIndexBy(array, value, identity, retHighest); 5786 } 5787 5788 /** 5789 * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy` 5790 * which invokes `iteratee` for `value` and each element of `array` to compute 5791 * their sort ranking. The iteratee is invoked with one argument; (value). 5792 * 5793 * @private 5794 * @param {Array} array The sorted array to inspect. 5795 * @param {*} value The value to evaluate. 5796 * @param {Function} iteratee The iteratee invoked per element. 5797 * @param {boolean} [retHighest] Specify returning the highest qualified index. 5798 * @returns {number} Returns the index at which `value` should be inserted 5799 * into `array`. 5800 */ 5801 function baseSortedIndexBy(array, value, iteratee, retHighest) { 5802 var low = 0, 5803 high = array == null ? 0 : array.length; 5804 if (high === 0) { 5805 return 0; 5806 } 5807 5808 value = iteratee(value); 5809 var valIsNaN = value !== value, 5810 valIsNull = value === null, 5811 valIsSymbol = isSymbol(value), 5812 valIsUndefined = value === undefined; 5813 5814 while (low < high) { 5815 var mid = nativeFloor((low + high) / 2), 5816 computed = iteratee(array[mid]), 5817 othIsDefined = computed !== undefined, 5818 othIsNull = computed === null, 5819 othIsReflexive = computed === computed, 5820 othIsSymbol = isSymbol(computed); 5821 5822 if (valIsNaN) { 5823 var setLow = retHighest || othIsReflexive; 5824 } else if (valIsUndefined) { 5825 setLow = othIsReflexive && (retHighest || othIsDefined); 5826 } else if (valIsNull) { 5827 setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull); 5828 } else if (valIsSymbol) { 5829 setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol); 5830 } else if (othIsNull || othIsSymbol) { 5831 setLow = false; 5832 } else { 5833 setLow = retHighest ? (computed <= value) : (computed < value); 5834 } 5835 if (setLow) { 5836 low = mid + 1; 5837 } else { 5838 high = mid; 5839 } 5840 } 5841 return nativeMin(high, MAX_ARRAY_INDEX); 5842 } 5843 5844 /** 5845 * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without 5846 * support for iteratee shorthands. 5847 * 5848 * @private 5849 * @param {Array} array The array to inspect. 5850 * @param {Function} [iteratee] The iteratee invoked per element. 5851 * @returns {Array} Returns the new duplicate free array. 5852 */ 5853 function baseSortedUniq(array, iteratee) { 5854 var index = -1, 5855 length = array.length, 5856 resIndex = 0, 5857 result = []; 5858 5859 while (++index < length) { 5860 var value = array[index], 5861 computed = iteratee ? iteratee(value) : value; 5862 5863 if (!index || !eq(computed, seen)) { 5864 var seen = computed; 5865 result[resIndex++] = value === 0 ? 0 : value; 5866 } 5867 } 5868 return result; 5869 } 5870 5871 /** 5872 * The base implementation of `_.toNumber` which doesn't ensure correct 5873 * conversions of binary, hexadecimal, or octal string values. 5874 * 5875 * @private 5876 * @param {*} value The value to process. 5877 * @returns {number} Returns the number. 5878 */ 5879 function baseToNumber(value) { 5880 if (typeof value == 'number') { 5881 return value; 5882 } 5883 if (isSymbol(value)) { 5884 return NAN; 5885 } 5886 return +value; 5887 } 5888 5889 /** 5890 * The base implementation of `_.toString` which doesn't convert nullish 5891 * values to empty strings. 5892 * 5893 * @private 5894 * @param {*} value The value to process. 5895 * @returns {string} Returns the string. 5896 */ 5897 function baseToString(value) { 5898 // Exit early for strings to avoid a performance hit in some environments. 5899 if (typeof value == 'string') { 5900 return value; 5901 } 5902 if (isArray(value)) { 5903 // Recursively convert values (susceptible to call stack limits). 5904 return arrayMap(value, baseToString) + ''; 5905 } 5906 if (isSymbol(value)) { 5907 return symbolToString ? symbolToString.call(value) : ''; 5908 } 5909 var result = (value + ''); 5910 return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; 5911 } 5912 5913 /** 5914 * The base implementation of `_.uniqBy` without support for iteratee shorthands. 5915 * 5916 * @private 5917 * @param {Array} array The array to inspect. 5918 * @param {Function} [iteratee] The iteratee invoked per element. 5919 * @param {Function} [comparator] The comparator invoked per element. 5920 * @returns {Array} Returns the new duplicate free array. 5921 */ 5922 function baseUniq(array, iteratee, comparator) { 5923 var index = -1, 5924 includes = arrayIncludes, 5925 length = array.length, 5926 isCommon = true, 5927 result = [], 5928 seen = result; 5929 5930 if (comparator) { 5931 isCommon = false; 5932 includes = arrayIncludesWith; 5933 } 5934 else if (length >= LARGE_ARRAY_SIZE) { 5935 var set = iteratee ? null : createSet(array); 5936 if (set) { 5937 return setToArray(set); 5938 } 5939 isCommon = false; 5940 includes = cacheHas; 5941 seen = new SetCache; 5942 } 5943 else { 5944 seen = iteratee ? [] : result; 5945 } 5946 outer: 5947 while (++index < length) { 5948 var value = array[index], 5949 computed = iteratee ? iteratee(value) : value; 5950 5951 value = (comparator || value !== 0) ? value : 0; 5952 if (isCommon && computed === computed) { 5953 var seenIndex = seen.length; 5954 while (seenIndex--) { 5955 if (seen[seenIndex] === computed) { 5956 continue outer; 5957 } 5958 } 5959 if (iteratee) { 5960 seen.push(computed); 5961 } 5962 result.push(value); 5963 } 5964 else if (!includes(seen, computed, comparator)) { 5965 if (seen !== result) { 5966 seen.push(computed); 5967 } 5968 result.push(value); 5969 } 5970 } 5971 return result; 5972 } 5973 5974 /** 5975 * The base implementation of `_.unset`. 5976 * 5977 * @private 5978 * @param {Object} object The object to modify. 5979 * @param {Array|string} path The property path to unset. 5980 * @returns {boolean} Returns `true` if the property is deleted, else `false`. 5981 */ 5982 function baseUnset(object, path) { 5983 path = castPath(path, object); 5984 object = parent(object, path); 5985 return object == null || delete object[toKey(last(path))]; 5986 } 5987 5988 /** 5989 * The base implementation of `_.update`. 5990 * 5991 * @private 5992 * @param {Object} object The object to modify. 5993 * @param {Array|string} path The path of the property to update. 5994 * @param {Function} updater The function to produce the updated value. 5995 * @param {Function} [customizer] The function to customize path creation. 5996 * @returns {Object} Returns `object`. 5997 */ 5998 function baseUpdate(object, path, updater, customizer) { 5999 return baseSet(object, path, updater(baseGet(object, path)), customizer); 6000 } 6001 6002 /** 6003 * The base implementation of methods like `_.dropWhile` and `_.takeWhile` 6004 * without support for iteratee shorthands. 6005 * 6006 * @private 6007 * @param {Array} array The array to query. 6008 * @param {Function} predicate The function invoked per iteration. 6009 * @param {boolean} [isDrop] Specify dropping elements instead of taking them. 6010 * @param {boolean} [fromRight] Specify iterating from right to left. 6011 * @returns {Array} Returns the slice of `array`. 6012 */ 6013 function baseWhile(array, predicate, isDrop, fromRight) { 6014 var length = array.length, 6015 index = fromRight ? length : -1; 6016 6017 while ((fromRight ? index-- : ++index < length) && 6018 predicate(array[index], index, array)) {} 6019 6020 return isDrop 6021 ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length)) 6022 : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index)); 6023 } 6024 6025 /** 6026 * The base implementation of `wrapperValue` which returns the result of 6027 * performing a sequence of actions on the unwrapped `value`, where each 6028 * successive action is supplied the return value of the previous. 6029 * 6030 * @private 6031 * @param {*} value The unwrapped value. 6032 * @param {Array} actions Actions to perform to resolve the unwrapped value. 6033 * @returns {*} Returns the resolved value. 6034 */ 6035 function baseWrapperValue(value, actions) { 6036 var result = value; 6037 if (result instanceof LazyWrapper) { 6038 result = result.value(); 6039 } 6040 return arrayReduce(actions, function(result, action) { 6041 return action.func.apply(action.thisArg, arrayPush([result], action.args)); 6042 }, result); 6043 } 6044 6045 /** 6046 * The base implementation of methods like `_.xor`, without support for 6047 * iteratee shorthands, that accepts an array of arrays to inspect. 6048 * 6049 * @private 6050 * @param {Array} arrays The arrays to inspect. 6051 * @param {Function} [iteratee] The iteratee invoked per element. 6052 * @param {Function} [comparator] The comparator invoked per element. 6053 * @returns {Array} Returns the new array of values. 6054 */ 6055 function baseXor(arrays, iteratee, comparator) { 6056 var length = arrays.length; 6057 if (length < 2) { 6058 return length ? baseUniq(arrays[0]) : []; 6059 } 6060 var index = -1, 6061 result = Array(length); 6062 6063 while (++index < length) { 6064 var array = arrays[index], 6065 othIndex = -1; 6066 6067 while (++othIndex < length) { 6068 if (othIndex != index) { 6069 result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator); 6070 } 6071 } 6072 } 6073 return baseUniq(baseFlatten(result, 1), iteratee, comparator); 6074 } 6075 6076 /** 6077 * This base implementation of `_.zipObject` which assigns values using `assignFunc`. 6078 * 6079 * @private 6080 * @param {Array} props The property identifiers. 6081 * @param {Array} values The property values. 6082 * @param {Function} assignFunc The function to assign values. 6083 * @returns {Object} Returns the new object. 6084 */ 6085 function baseZipObject(props, values, assignFunc) { 6086 var index = -1, 6087 length = props.length, 6088 valsLength = values.length, 6089 result = {}; 6090 6091 while (++index < length) { 6092 var value = index < valsLength ? values[index] : undefined; 6093 assignFunc(result, props[index], value); 6094 } 6095 return result; 6096 } 6097 6098 /** 6099 * Casts `value` to an empty array if it's not an array like object. 6100 * 6101 * @private 6102 * @param {*} value The value to inspect. 6103 * @returns {Array|Object} Returns the cast array-like object. 6104 */ 6105 function castArrayLikeObject(value) { 6106 return isArrayLikeObject(value) ? value : []; 6107 } 6108 6109 /** 6110 * Casts `value` to `identity` if it's not a function. 6111 * 6112 * @private 6113 * @param {*} value The value to inspect. 6114 * @returns {Function} Returns cast function. 6115 */ 6116 function castFunction(value) { 6117 return typeof value == 'function' ? value : identity; 6118 } 6119 6120 /** 6121 * Casts `value` to a path array if it's not one. 6122 * 6123 * @private 6124 * @param {*} value The value to inspect. 6125 * @param {Object} [object] The object to query keys on. 6126 * @returns {Array} Returns the cast property path array. 6127 */ 6128 function castPath(value, object) { 6129 if (isArray(value)) { 6130 return value; 6131 } 6132 return isKey(value, object) ? [value] : stringToPath(toString(value)); 6133 } 6134 6135 /** 6136 * A `baseRest` alias which can be replaced with `identity` by module 6137 * replacement plugins. 6138 * 6139 * @private 6140 * @type {Function} 6141 * @param {Function} func The function to apply a rest parameter to. 6142 * @returns {Function} Returns the new function. 6143 */ 6144 var castRest = baseRest; 6145 6146 /** 6147 * Casts `array` to a slice if it's needed. 6148 * 6149 * @private 6150 * @param {Array} array The array to inspect. 6151 * @param {number} start The start position. 6152 * @param {number} [end=array.length] The end position. 6153 * @returns {Array} Returns the cast slice. 6154 */ 6155 function castSlice(array, start, end) { 6156 var length = array.length; 6157 end = end === undefined ? length : end; 6158 return (!start && end >= length) ? array : baseSlice(array, start, end); 6159 } 6160 6161 /** 6162 * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout). 6163 * 6164 * @private 6165 * @param {number|Object} id The timer id or timeout object of the timer to clear. 6166 */ 6167 var clearTimeout = ctxClearTimeout || function(id) { 6168 return root.clearTimeout(id); 6169 }; 6170 6171 /** 6172 * Creates a clone of `buffer`. 6173 * 6174 * @private 6175 * @param {Buffer} buffer The buffer to clone. 6176 * @param {boolean} [isDeep] Specify a deep clone. 6177 * @returns {Buffer} Returns the cloned buffer. 6178 */ 6179 function cloneBuffer(buffer, isDeep) { 6180 if (isDeep) { 6181 return buffer.slice(); 6182 } 6183 var length = buffer.length, 6184 result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); 6185 6186 buffer.copy(result); 6187 return result; 6188 } 6189 6190 /** 6191 * Creates a clone of `arrayBuffer`. 6192 * 6193 * @private 6194 * @param {ArrayBuffer} arrayBuffer The array buffer to clone. 6195 * @returns {ArrayBuffer} Returns the cloned array buffer. 6196 */ 6197 function cloneArrayBuffer(arrayBuffer) { 6198 var result = new arrayBuffer.constructor(arrayBuffer.byteLength); 6199 new Uint8Array(result).set(new Uint8Array(arrayBuffer)); 6200 return result; 6201 } 6202 6203 /** 6204 * Creates a clone of `dataView`. 6205 * 6206 * @private 6207 * @param {Object} dataView The data view to clone. 6208 * @param {boolean} [isDeep] Specify a deep clone. 6209 * @returns {Object} Returns the cloned data view. 6210 */ 6211 function cloneDataView(dataView, isDeep) { 6212 var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; 6213 return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); 6214 } 6215 6216 /** 6217 * Creates a clone of `regexp`. 6218 * 6219 * @private 6220 * @param {Object} regexp The regexp to clone. 6221 * @returns {Object} Returns the cloned regexp. 6222 */ 6223 function cloneRegExp(regexp) { 6224 var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); 6225 result.lastIndex = regexp.lastIndex; 6226 return result; 6227 } 6228 6229 /** 6230 * Creates a clone of the `symbol` object. 6231 * 6232 * @private 6233 * @param {Object} symbol The symbol object to clone. 6234 * @returns {Object} Returns the cloned symbol object. 6235 */ 6236 function cloneSymbol(symbol) { 6237 return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; 6238 } 6239 6240 /** 6241 * Creates a clone of `typedArray`. 6242 * 6243 * @private 6244 * @param {Object} typedArray The typed array to clone. 6245 * @param {boolean} [isDeep] Specify a deep clone. 6246 * @returns {Object} Returns the cloned typed array. 6247 */ 6248 function cloneTypedArray(typedArray, isDeep) { 6249 var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; 6250 return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); 6251 } 6252 6253 /** 6254 * Compares values to sort them in ascending order. 6255 * 6256 * @private 6257 * @param {*} value The value to compare. 6258 * @param {*} other The other value to compare. 6259 * @returns {number} Returns the sort order indicator for `value`. 6260 */ 6261 function compareAscending(value, other) { 6262 if (value !== other) { 6263 var valIsDefined = value !== undefined, 6264 valIsNull = value === null, 6265 valIsReflexive = value === value, 6266 valIsSymbol = isSymbol(value); 6267 6268 var othIsDefined = other !== undefined, 6269 othIsNull = other === null, 6270 othIsReflexive = other === other, 6271 othIsSymbol = isSymbol(other); 6272 6273 if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) || 6274 (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) || 6275 (valIsNull && othIsDefined && othIsReflexive) || 6276 (!valIsDefined && othIsReflexive) || 6277 !valIsReflexive) { 6278 return 1; 6279 } 6280 if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) || 6281 (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) || 6282 (othIsNull && valIsDefined && valIsReflexive) || 6283 (!othIsDefined && valIsReflexive) || 6284 !othIsReflexive) { 6285 return -1; 6286 } 6287 } 6288 return 0; 6289 } 6290 6291 /** 6292 * Used by `_.orderBy` to compare multiple properties of a value to another 6293 * and stable sort them. 6294 * 6295 * If `orders` is unspecified, all values are sorted in ascending order. Otherwise, 6296 * specify an order of "desc" for descending or "asc" for ascending sort order 6297 * of corresponding values. 6298 * 6299 * @private 6300 * @param {Object} object The object to compare. 6301 * @param {Object} other The other object to compare. 6302 * @param {boolean[]|string[]} orders The order to sort by for each property. 6303 * @returns {number} Returns the sort order indicator for `object`. 6304 */ 6305 function compareMultiple(object, other, orders) { 6306 var index = -1, 6307 objCriteria = object.criteria, 6308 othCriteria = other.criteria, 6309 length = objCriteria.length, 6310 ordersLength = orders.length; 6311 6312 while (++index < length) { 6313 var result = compareAscending(objCriteria[index], othCriteria[index]); 6314 if (result) { 6315 if (index >= ordersLength) { 6316 return result; 6317 } 6318 var order = orders[index]; 6319 return result * (order == 'desc' ? -1 : 1); 6320 } 6321 } 6322 // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications 6323 // that causes it, under certain circumstances, to provide the same value for 6324 // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 6325 // for more details. 6326 // 6327 // This also ensures a stable sort in V8 and other engines. 6328 // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details. 6329 return object.index - other.index; 6330 } 6331 6332 /** 6333 * Creates an array that is the composition of partially applied arguments, 6334 * placeholders, and provided arguments into a single array of arguments. 6335 * 6336 * @private 6337 * @param {Array} args The provided arguments. 6338 * @param {Array} partials The arguments to prepend to those provided. 6339 * @param {Array} holders The `partials` placeholder indexes. 6340 * @params {boolean} [isCurried] Specify composing for a curried function. 6341 * @returns {Array} Returns the new array of composed arguments. 6342 */ 6343 function composeArgs(args, partials, holders, isCurried) { 6344 var argsIndex = -1, 6345 argsLength = args.length, 6346 holdersLength = holders.length, 6347 leftIndex = -1, 6348 leftLength = partials.length, 6349 rangeLength = nativeMax(argsLength - holdersLength, 0), 6350 result = Array(leftLength + rangeLength), 6351 isUncurried = !isCurried; 6352 6353 while (++leftIndex < leftLength) { 6354 result[leftIndex] = partials[leftIndex]; 6355 } 6356 while (++argsIndex < holdersLength) { 6357 if (isUncurried || argsIndex < argsLength) { 6358 result[holders[argsIndex]] = args[argsIndex]; 6359 } 6360 } 6361 while (rangeLength--) { 6362 result[leftIndex++] = args[argsIndex++]; 6363 } 6364 return result; 6365 } 6366 6367 /** 6368 * This function is like `composeArgs` except that the arguments composition 6369 * is tailored for `_.partialRight`. 6370 * 6371 * @private 6372 * @param {Array} args The provided arguments. 6373 * @param {Array} partials The arguments to append to those provided. 6374 * @param {Array} holders The `partials` placeholder indexes. 6375 * @params {boolean} [isCurried] Specify composing for a curried function. 6376 * @returns {Array} Returns the new array of composed arguments. 6377 */ 6378 function composeArgsRight(args, partials, holders, isCurried) { 6379 var argsIndex = -1, 6380 argsLength = args.length, 6381 holdersIndex = -1, 6382 holdersLength = holders.length, 6383 rightIndex = -1, 6384 rightLength = partials.length, 6385 rangeLength = nativeMax(argsLength - holdersLength, 0), 6386 result = Array(rangeLength + rightLength), 6387 isUncurried = !isCurried; 6388 6389 while (++argsIndex < rangeLength) { 6390 result[argsIndex] = args[argsIndex]; 6391 } 6392 var offset = argsIndex; 6393 while (++rightIndex < rightLength) { 6394 result[offset + rightIndex] = partials[rightIndex]; 6395 } 6396 while (++holdersIndex < holdersLength) { 6397 if (isUncurried || argsIndex < argsLength) { 6398 result[offset + holders[holdersIndex]] = args[argsIndex++]; 6399 } 6400 } 6401 return result; 6402 } 6403 6404 /** 6405 * Copies the values of `source` to `array`. 6406 * 6407 * @private 6408 * @param {Array} source The array to copy values from. 6409 * @param {Array} [array=[]] The array to copy values to. 6410 * @returns {Array} Returns `array`. 6411 */ 6412 function copyArray(source, array) { 6413 var index = -1, 6414 length = source.length; 6415 6416 array || (array = Array(length)); 6417 while (++index < length) { 6418 array[index] = source[index]; 6419 } 6420 return array; 6421 } 6422 6423 /** 6424 * Copies properties of `source` to `object`. 6425 * 6426 * @private 6427 * @param {Object} source The object to copy properties from. 6428 * @param {Array} props The property identifiers to copy. 6429 * @param {Object} [object={}] The object to copy properties to. 6430 * @param {Function} [customizer] The function to customize copied values. 6431 * @returns {Object} Returns `object`. 6432 */ 6433 function copyObject(source, props, object, customizer) { 6434 var isNew = !object; 6435 object || (object = {}); 6436 6437 var index = -1, 6438 length = props.length; 6439 6440 while (++index < length) { 6441 var key = props[index]; 6442 6443 var newValue = customizer 6444 ? customizer(object[key], source[key], key, object, source) 6445 : undefined; 6446 6447 if (newValue === undefined) { 6448 newValue = source[key]; 6449 } 6450 if (isNew) { 6451 baseAssignValue(object, key, newValue); 6452 } else { 6453 assignValue(object, key, newValue); 6454 } 6455 } 6456 return object; 6457 } 6458 6459 /** 6460 * Copies own symbols of `source` to `object`. 6461 * 6462 * @private 6463 * @param {Object} source The object to copy symbols from. 6464 * @param {Object} [object={}] The object to copy symbols to. 6465 * @returns {Object} Returns `object`. 6466 */ 6467 function copySymbols(source, object) { 6468 return copyObject(source, getSymbols(source), object); 6469 } 6470 6471 /** 6472 * Copies own and inherited symbols of `source` to `object`. 6473 * 6474 * @private 6475 * @param {Object} source The object to copy symbols from. 6476 * @param {Object} [object={}] The object to copy symbols to. 6477 * @returns {Object} Returns `object`. 6478 */ 6479 function copySymbolsIn(source, object) { 6480 return copyObject(source, getSymbolsIn(source), object); 6481 } 6482 6483 /** 6484 * Creates a function like `_.groupBy`. 6485 * 6486 * @private 6487 * @param {Function} setter The function to set accumulator values. 6488 * @param {Function} [initializer] The accumulator object initializer. 6489 * @returns {Function} Returns the new aggregator function. 6490 */ 6491 function createAggregator(setter, initializer) { 6492 return function(collection, iteratee) { 6493 var func = isArray(collection) ? arrayAggregator : baseAggregator, 6494 accumulator = initializer ? initializer() : {}; 6495 6496 return func(collection, setter, getIteratee(iteratee, 2), accumulator); 6497 }; 6498 } 6499 6500 /** 6501 * Creates a function like `_.assign`. 6502 * 6503 * @private 6504 * @param {Function} assigner The function to assign values. 6505 * @returns {Function} Returns the new assigner function. 6506 */ 6507 function createAssigner(assigner) { 6508 return baseRest(function(object, sources) { 6509 var index = -1, 6510 length = sources.length, 6511 customizer = length > 1 ? sources[length - 1] : undefined, 6512 guard = length > 2 ? sources[2] : undefined; 6513 6514 customizer = (assigner.length > 3 && typeof customizer == 'function') 6515 ? (length--, customizer) 6516 : undefined; 6517 6518 if (guard && isIterateeCall(sources[0], sources[1], guard)) { 6519 customizer = length < 3 ? undefined : customizer; 6520 length = 1; 6521 } 6522 object = Object(object); 6523 while (++index < length) { 6524 var source = sources[index]; 6525 if (source) { 6526 assigner(object, source, index, customizer); 6527 } 6528 } 6529 return object; 6530 }); 6531 } 6532 6533 /** 6534 * Creates a `baseEach` or `baseEachRight` function. 6535 * 6536 * @private 6537 * @param {Function} eachFunc The function to iterate over a collection. 6538 * @param {boolean} [fromRight] Specify iterating from right to left. 6539 * @returns {Function} Returns the new base function. 6540 */ 6541 function createBaseEach(eachFunc, fromRight) { 6542 return function(collection, iteratee) { 6543 if (collection == null) { 6544 return collection; 6545 } 6546 if (!isArrayLike(collection)) { 6547 return eachFunc(collection, iteratee); 6548 } 6549 var length = collection.length, 6550 index = fromRight ? length : -1, 6551 iterable = Object(collection); 6552 6553 while ((fromRight ? index-- : ++index < length)) { 6554 if (iteratee(iterable[index], index, iterable) === false) { 6555 break; 6556 } 6557 } 6558 return collection; 6559 }; 6560 } 6561 6562 /** 6563 * Creates a base function for methods like `_.forIn` and `_.forOwn`. 6564 * 6565 * @private 6566 * @param {boolean} [fromRight] Specify iterating from right to left. 6567 * @returns {Function} Returns the new base function. 6568 */ 6569 function createBaseFor(fromRight) { 6570 return function(object, iteratee, keysFunc) { 6571 var index = -1, 6572 iterable = Object(object), 6573 props = keysFunc(object), 6574 length = props.length; 6575 6576 while (length--) { 6577 var key = props[fromRight ? length : ++index]; 6578 if (iteratee(iterable[key], key, iterable) === false) { 6579 break; 6580 } 6581 } 6582 return object; 6583 }; 6584 } 6585 6586 /** 6587 * Creates a function that wraps `func` to invoke it with the optional `this` 6588 * binding of `thisArg`. 6589 * 6590 * @private 6591 * @param {Function} func The function to wrap. 6592 * @param {number} bitmask The bitmask flags. See `createWrap` for more details. 6593 * @param {*} [thisArg] The `this` binding of `func`. 6594 * @returns {Function} Returns the new wrapped function. 6595 */ 6596 function createBind(func, bitmask, thisArg) { 6597 var isBind = bitmask & WRAP_BIND_FLAG, 6598 Ctor = createCtor(func); 6599 6600 function wrapper() { 6601 var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; 6602 return fn.apply(isBind ? thisArg : this, arguments); 6603 } 6604 return wrapper; 6605 } 6606 6607 /** 6608 * Creates a function like `_.lowerFirst`. 6609 * 6610 * @private 6611 * @param {string} methodName The name of the `String` case method to use. 6612 * @returns {Function} Returns the new case function. 6613 */ 6614 function createCaseFirst(methodName) { 6615 return function(string) { 6616 string = toString(string); 6617 6618 var strSymbols = hasUnicode(string) 6619 ? stringToArray(string) 6620 : undefined; 6621 6622 var chr = strSymbols 6623 ? strSymbols[0] 6624 : string.charAt(0); 6625 6626 var trailing = strSymbols 6627 ? castSlice(strSymbols, 1).join('') 6628 : string.slice(1); 6629 6630 return chr[methodName]() + trailing; 6631 }; 6632 } 6633 6634 /** 6635 * Creates a function like `_.camelCase`. 6636 * 6637 * @private 6638 * @param {Function} callback The function to combine each word. 6639 * @returns {Function} Returns the new compounder function. 6640 */ 6641 function createCompounder(callback) { 6642 return function(string) { 6643 return arrayReduce(words(deburr(string).replace(reApos, '')), callback, ''); 6644 }; 6645 } 6646 6647 /** 6648 * Creates a function that produces an instance of `Ctor` regardless of 6649 * whether it was invoked as part of a `new` expression or by `call` or `apply`. 6650 * 6651 * @private 6652 * @param {Function} Ctor The constructor to wrap. 6653 * @returns {Function} Returns the new wrapped function. 6654 */ 6655 function createCtor(Ctor) { 6656 return function() { 6657 // Use a `switch` statement to work with class constructors. See 6658 // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist 6659 // for more details. 6660 var args = arguments; 6661 switch (args.length) { 6662 case 0: return new Ctor; 6663 case 1: return new Ctor(args[0]); 6664 case 2: return new Ctor(args[0], args[1]); 6665 case 3: return new Ctor(args[0], args[1], args[2]); 6666 case 4: return new Ctor(args[0], args[1], args[2], args[3]); 6667 case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); 6668 case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); 6669 case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); 6670 } 6671 var thisBinding = baseCreate(Ctor.prototype), 6672 result = Ctor.apply(thisBinding, args); 6673 6674 // Mimic the constructor's `return` behavior. 6675 // See https://es5.github.io/#x13.2.2 for more details. 6676 return isObject(result) ? result : thisBinding; 6677 }; 6678 } 6679 6680 /** 6681 * Creates a function that wraps `func` to enable currying. 6682 * 6683 * @private 6684 * @param {Function} func The function to wrap. 6685 * @param {number} bitmask The bitmask flags. See `createWrap` for more details. 6686 * @param {number} arity The arity of `func`. 6687 * @returns {Function} Returns the new wrapped function. 6688 */ 6689 function createCurry(func, bitmask, arity) { 6690 var Ctor = createCtor(func); 6691 6692 function wrapper() { 6693 var length = arguments.length, 6694 args = Array(length), 6695 index = length, 6696 placeholder = getHolder(wrapper); 6697 6698 while (index--) { 6699 args[index] = arguments[index]; 6700 } 6701 var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder) 6702 ? [] 6703 : replaceHolders(args, placeholder); 6704 6705 length -= holders.length; 6706 if (length < arity) { 6707 return createRecurry( 6708 func, bitmask, createHybrid, wrapper.placeholder, undefined, 6709 args, holders, undefined, undefined, arity - length); 6710 } 6711 var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; 6712 return apply(fn, this, args); 6713 } 6714 return wrapper; 6715 } 6716 6717 /** 6718 * Creates a `_.find` or `_.findLast` function. 6719 * 6720 * @private 6721 * @param {Function} findIndexFunc The function to find the collection index. 6722 * @returns {Function} Returns the new find function. 6723 */ 6724 function createFind(findIndexFunc) { 6725 return function(collection, predicate, fromIndex) { 6726 var iterable = Object(collection); 6727 if (!isArrayLike(collection)) { 6728 var iteratee = getIteratee(predicate, 3); 6729 collection = keys(collection); 6730 predicate = function(key) { return iteratee(iterable[key], key, iterable); }; 6731 } 6732 var index = findIndexFunc(collection, predicate, fromIndex); 6733 return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined; 6734 }; 6735 } 6736 6737 /** 6738 * Creates a `_.flow` or `_.flowRight` function. 6739 * 6740 * @private 6741 * @param {boolean} [fromRight] Specify iterating from right to left. 6742 * @returns {Function} Returns the new flow function. 6743 */ 6744 function createFlow(fromRight) { 6745 return flatRest(function(funcs) { 6746 var length = funcs.length, 6747 index = length, 6748 prereq = LodashWrapper.prototype.thru; 6749 6750 if (fromRight) { 6751 funcs.reverse(); 6752 } 6753 while (index--) { 6754 var func = funcs[index]; 6755 if (typeof func != 'function') { 6756 throw new TypeError(FUNC_ERROR_TEXT); 6757 } 6758 if (prereq && !wrapper && getFuncName(func) == 'wrapper') { 6759 var wrapper = new LodashWrapper([], true); 6760 } 6761 } 6762 index = wrapper ? index : length; 6763 while (++index < length) { 6764 func = funcs[index]; 6765 6766 var funcName = getFuncName(func), 6767 data = funcName == 'wrapper' ? getData(func) : undefined; 6768 6769 if (data && isLaziable(data[0]) && 6770 data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) && 6771 !data[4].length && data[9] == 1 6772 ) { 6773 wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); 6774 } else { 6775 wrapper = (func.length == 1 && isLaziable(func)) 6776 ? wrapper[funcName]() 6777 : wrapper.thru(func); 6778 } 6779 } 6780 return function() { 6781 var args = arguments, 6782 value = args[0]; 6783 6784 if (wrapper && args.length == 1 && isArray(value)) { 6785 return wrapper.plant(value).value(); 6786 } 6787 var index = 0, 6788 result = length ? funcs[index].apply(this, args) : value; 6789 6790 while (++index < length) { 6791 result = funcs[index].call(this, result); 6792 } 6793 return result; 6794 }; 6795 }); 6796 } 6797 6798 /** 6799 * Creates a function that wraps `func` to invoke it with optional `this` 6800 * binding of `thisArg`, partial application, and currying. 6801 * 6802 * @private 6803 * @param {Function|string} func The function or method name to wrap. 6804 * @param {number} bitmask The bitmask flags. See `createWrap` for more details. 6805 * @param {*} [thisArg] The `this` binding of `func`. 6806 * @param {Array} [partials] The arguments to prepend to those provided to 6807 * the new function. 6808 * @param {Array} [holders] The `partials` placeholder indexes. 6809 * @param {Array} [partialsRight] The arguments to append to those provided 6810 * to the new function. 6811 * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. 6812 * @param {Array} [argPos] The argument positions of the new function. 6813 * @param {number} [ary] The arity cap of `func`. 6814 * @param {number} [arity] The arity of `func`. 6815 * @returns {Function} Returns the new wrapped function. 6816 */ 6817 function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { 6818 var isAry = bitmask & WRAP_ARY_FLAG, 6819 isBind = bitmask & WRAP_BIND_FLAG, 6820 isBindKey = bitmask & WRAP_BIND_KEY_FLAG, 6821 isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG), 6822 isFlip = bitmask & WRAP_FLIP_FLAG, 6823 Ctor = isBindKey ? undefined : createCtor(func); 6824 6825 function wrapper() { 6826 var length = arguments.length, 6827 args = Array(length), 6828 index = length; 6829 6830 while (index--) { 6831 args[index] = arguments[index]; 6832 } 6833 if (isCurried) { 6834 var placeholder = getHolder(wrapper), 6835 holdersCount = countHolders(args, placeholder); 6836 } 6837 if (partials) { 6838 args = composeArgs(args, partials, holders, isCurried); 6839 } 6840 if (partialsRight) { 6841 args = composeArgsRight(args, partialsRight, holdersRight, isCurried); 6842 } 6843 length -= holdersCount; 6844 if (isCurried && length < arity) { 6845 var newHolders = replaceHolders(args, placeholder); 6846 return createRecurry( 6847 func, bitmask, createHybrid, wrapper.placeholder, thisArg, 6848 args, newHolders, argPos, ary, arity - length 6849 ); 6850 } 6851 var thisBinding = isBind ? thisArg : this, 6852 fn = isBindKey ? thisBinding[func] : func; 6853 6854 length = args.length; 6855 if (argPos) { 6856 args = reorder(args, argPos); 6857 } else if (isFlip && length > 1) { 6858 args.reverse(); 6859 } 6860 if (isAry && ary < length) { 6861 args.length = ary; 6862 } 6863 if (this && this !== root && this instanceof wrapper) { 6864 fn = Ctor || createCtor(fn); 6865 } 6866 return fn.apply(thisBinding, args); 6867 } 6868 return wrapper; 6869 } 6870 6871 /** 6872 * Creates a function like `_.invertBy`. 6873 * 6874 * @private 6875 * @param {Function} setter The function to set accumulator values. 6876 * @param {Function} toIteratee The function to resolve iteratees. 6877 * @returns {Function} Returns the new inverter function. 6878 */ 6879 function createInverter(setter, toIteratee) { 6880 return function(object, iteratee) { 6881 return baseInverter(object, setter, toIteratee(iteratee), {}); 6882 }; 6883 } 6884 6885 /** 6886 * Creates a function that performs a mathematical operation on two values. 6887 * 6888 * @private 6889 * @param {Function} operator The function to perform the operation. 6890 * @param {number} [defaultValue] The value used for `undefined` arguments. 6891 * @returns {Function} Returns the new mathematical operation function. 6892 */ 6893 function createMathOperation(operator, defaultValue) { 6894 return function(value, other) { 6895 var result; 6896 if (value === undefined && other === undefined) { 6897 return defaultValue; 6898 } 6899 if (value !== undefined) { 6900 result = value; 6901 } 6902 if (other !== undefined) { 6903 if (result === undefined) { 6904 return other; 6905 } 6906 if (typeof value == 'string' || typeof other == 'string') { 6907 value = baseToString(value); 6908 other = baseToString(other); 6909 } else { 6910 value = baseToNumber(value); 6911 other = baseToNumber(other); 6912 } 6913 result = operator(value, other); 6914 } 6915 return result; 6916 }; 6917 } 6918 6919 /** 6920 * Creates a function like `_.over`. 6921 * 6922 * @private 6923 * @param {Function} arrayFunc The function to iterate over iteratees. 6924 * @returns {Function} Returns the new over function. 6925 */ 6926 function createOver(arrayFunc) { 6927 return flatRest(function(iteratees) { 6928 iteratees = arrayMap(iteratees, baseUnary(getIteratee())); 6929 return baseRest(function(args) { 6930 var thisArg = this; 6931 return arrayFunc(iteratees, function(iteratee) { 6932 return apply(iteratee, thisArg, args); 6933 }); 6934 }); 6935 }); 6936 } 6937 6938 /** 6939 * Creates the padding for `string` based on `length`. The `chars` string 6940 * is truncated if the number of characters exceeds `length`. 6941 * 6942 * @private 6943 * @param {number} length The padding length. 6944 * @param {string} [chars=' '] The string used as padding. 6945 * @returns {string} Returns the padding for `string`. 6946 */ 6947 function createPadding(length, chars) { 6948 chars = chars === undefined ? ' ' : baseToString(chars); 6949 6950 var charsLength = chars.length; 6951 if (charsLength < 2) { 6952 return charsLength ? baseRepeat(chars, length) : chars; 6953 } 6954 var result = baseRepeat(chars, nativeCeil(length / stringSize(chars))); 6955 return hasUnicode(chars) 6956 ? castSlice(stringToArray(result), 0, length).join('') 6957 : result.slice(0, length); 6958 } 6959 6960 /** 6961 * Creates a function that wraps `func` to invoke it with the `this` binding 6962 * of `thisArg` and `partials` prepended to the arguments it receives. 6963 * 6964 * @private 6965 * @param {Function} func The function to wrap. 6966 * @param {number} bitmask The bitmask flags. See `createWrap` for more details. 6967 * @param {*} thisArg The `this` binding of `func`. 6968 * @param {Array} partials The arguments to prepend to those provided to 6969 * the new function. 6970 * @returns {Function} Returns the new wrapped function. 6971 */ 6972 function createPartial(func, bitmask, thisArg, partials) { 6973 var isBind = bitmask & WRAP_BIND_FLAG, 6974 Ctor = createCtor(func); 6975 6976 function wrapper() { 6977 var argsIndex = -1, 6978 argsLength = arguments.length, 6979 leftIndex = -1, 6980 leftLength = partials.length, 6981 args = Array(leftLength + argsLength), 6982 fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; 6983 6984 while (++leftIndex < leftLength) { 6985 args[leftIndex] = partials[leftIndex]; 6986 } 6987 while (argsLength--) { 6988 args[leftIndex++] = arguments[++argsIndex]; 6989 } 6990 return apply(fn, isBind ? thisArg : this, args); 6991 } 6992 return wrapper; 6993 } 6994 6995 /** 6996 * Creates a `_.range` or `_.rangeRight` function. 6997 * 6998 * @private 6999 * @param {boolean} [fromRight] Specify iterating from right to left. 7000 * @returns {Function} Returns the new range function. 7001 */ 7002 function createRange(fromRight) { 7003 return function(start, end, step) { 7004 if (step && typeof step != 'number' && isIterateeCall(start, end, step)) { 7005 end = step = undefined; 7006 } 7007 // Ensure the sign of `-0` is preserved. 7008 start = toFinite(start); 7009 if (end === undefined) { 7010 end = start; 7011 start = 0; 7012 } else { 7013 end = toFinite(end); 7014 } 7015 step = step === undefined ? (start < end ? 1 : -1) : toFinite(step); 7016 return baseRange(start, end, step, fromRight); 7017 }; 7018 } 7019 7020 /** 7021 * Creates a function that performs a relational operation on two values. 7022 * 7023 * @private 7024 * @param {Function} operator The function to perform the operation. 7025 * @returns {Function} Returns the new relational operation function. 7026 */ 7027 function createRelationalOperation(operator) { 7028 return function(value, other) { 7029 if (!(typeof value == 'string' && typeof other == 'string')) { 7030 value = toNumber(value); 7031 other = toNumber(other); 7032 } 7033 return operator(value, other); 7034 }; 7035 } 7036 7037 /** 7038 * Creates a function that wraps `func` to continue currying. 7039 * 7040 * @private 7041 * @param {Function} func The function to wrap. 7042 * @param {number} bitmask The bitmask flags. See `createWrap` for more details. 7043 * @param {Function} wrapFunc The function to create the `func` wrapper. 7044 * @param {*} placeholder The placeholder value. 7045 * @param {*} [thisArg] The `this` binding of `func`. 7046 * @param {Array} [partials] The arguments to prepend to those provided to 7047 * the new function. 7048 * @param {Array} [holders] The `partials` placeholder indexes. 7049 * @param {Array} [argPos] The argument positions of the new function. 7050 * @param {number} [ary] The arity cap of `func`. 7051 * @param {number} [arity] The arity of `func`. 7052 * @returns {Function} Returns the new wrapped function. 7053 */ 7054 function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) { 7055 var isCurry = bitmask & WRAP_CURRY_FLAG, 7056 newHolders = isCurry ? holders : undefined, 7057 newHoldersRight = isCurry ? undefined : holders, 7058 newPartials = isCurry ? partials : undefined, 7059 newPartialsRight = isCurry ? undefined : partials; 7060 7061 bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG); 7062 bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG); 7063 7064 if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) { 7065 bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG); 7066 } 7067 var newData = [ 7068 func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, 7069 newHoldersRight, argPos, ary, arity 7070 ]; 7071 7072 var result = wrapFunc.apply(undefined, newData); 7073 if (isLaziable(func)) { 7074 setData(result, newData); 7075 } 7076 result.placeholder = placeholder; 7077 return setWrapToString(result, func, bitmask); 7078 } 7079 7080 /** 7081 * Creates a function like `_.round`. 7082 * 7083 * @private 7084 * @param {string} methodName The name of the `Math` method to use when rounding. 7085 * @returns {Function} Returns the new round function. 7086 */ 7087 function createRound(methodName) { 7088 var func = Math[methodName]; 7089 return function(number, precision) { 7090 number = toNumber(number); 7091 precision = precision == null ? 0 : nativeMin(toInteger(precision), 292); 7092 if (precision && nativeIsFinite(number)) { 7093 // Shift with exponential notation to avoid floating-point issues. 7094 // See [MDN](https://mdn.io/round#Examples) for more details. 7095 var pair = (toString(number) + 'e').split('e'), 7096 value = func(pair[0] + 'e' + (+pair[1] + precision)); 7097 7098 pair = (toString(value) + 'e').split('e'); 7099 return +(pair[0] + 'e' + (+pair[1] - precision)); 7100 } 7101 return func(number); 7102 }; 7103 } 7104 7105 /** 7106 * Creates a set object of `values`. 7107 * 7108 * @private 7109 * @param {Array} values The values to add to the set. 7110 * @returns {Object} Returns the new set. 7111 */ 7112 var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) { 7113 return new Set(values); 7114 }; 7115 7116 /** 7117 * Creates a `_.toPairs` or `_.toPairsIn` function. 7118 * 7119 * @private 7120 * @param {Function} keysFunc The function to get the keys of a given object. 7121 * @returns {Function} Returns the new pairs function. 7122 */ 7123 function createToPairs(keysFunc) { 7124 return function(object) { 7125 var tag = getTag(object); 7126 if (tag == mapTag) { 7127 return mapToArray(object); 7128 } 7129 if (tag == setTag) { 7130 return setToPairs(object); 7131 } 7132 return baseToPairs(object, keysFunc(object)); 7133 }; 7134 } 7135 7136 /** 7137 * Creates a function that either curries or invokes `func` with optional 7138 * `this` binding and partially applied arguments. 7139 * 7140 * @private 7141 * @param {Function|string} func The function or method name to wrap. 7142 * @param {number} bitmask The bitmask flags. 7143 * 1 - `_.bind` 7144 * 2 - `_.bindKey` 7145 * 4 - `_.curry` or `_.curryRight` of a bound function 7146 * 8 - `_.curry` 7147 * 16 - `_.curryRight` 7148 * 32 - `_.partial` 7149 * 64 - `_.partialRight` 7150 * 128 - `_.rearg` 7151 * 256 - `_.ary` 7152 * 512 - `_.flip` 7153 * @param {*} [thisArg] The `this` binding of `func`. 7154 * @param {Array} [partials] The arguments to be partially applied. 7155 * @param {Array} [holders] The `partials` placeholder indexes. 7156 * @param {Array} [argPos] The argument positions of the new function. 7157 * @param {number} [ary] The arity cap of `func`. 7158 * @param {number} [arity] The arity of `func`. 7159 * @returns {Function} Returns the new wrapped function. 7160 */ 7161 function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { 7162 var isBindKey = bitmask & WRAP_BIND_KEY_FLAG; 7163 if (!isBindKey && typeof func != 'function') { 7164 throw new TypeError(FUNC_ERROR_TEXT); 7165 } 7166 var length = partials ? partials.length : 0; 7167 if (!length) { 7168 bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG); 7169 partials = holders = undefined; 7170 } 7171 ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0); 7172 arity = arity === undefined ? arity : toInteger(arity); 7173 length -= holders ? holders.length : 0; 7174 7175 if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) { 7176 var partialsRight = partials, 7177 holdersRight = holders; 7178 7179 partials = holders = undefined; 7180 } 7181 var data = isBindKey ? undefined : getData(func); 7182 7183 var newData = [ 7184 func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, 7185 argPos, ary, arity 7186 ]; 7187 7188 if (data) { 7189 mergeData(newData, data); 7190 } 7191 func = newData[0]; 7192 bitmask = newData[1]; 7193 thisArg = newData[2]; 7194 partials = newData[3]; 7195 holders = newData[4]; 7196 arity = newData[9] = newData[9] === undefined 7197 ? (isBindKey ? 0 : func.length) 7198 : nativeMax(newData[9] - length, 0); 7199 7200 if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) { 7201 bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG); 7202 } 7203 if (!bitmask || bitmask == WRAP_BIND_FLAG) { 7204 var result = createBind(func, bitmask, thisArg); 7205 } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) { 7206 result = createCurry(func, bitmask, arity); 7207 } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) { 7208 result = createPartial(func, bitmask, thisArg, partials); 7209 } else { 7210 result = createHybrid.apply(undefined, newData); 7211 } 7212 var setter = data ? baseSetData : setData; 7213 return setWrapToString(setter(result, newData), func, bitmask); 7214 } 7215 7216 /** 7217 * Used by `_.defaults` to customize its `_.assignIn` use to assign properties 7218 * of source objects to the destination object for all destination properties 7219 * that resolve to `undefined`. 7220 * 7221 * @private 7222 * @param {*} objValue The destination value. 7223 * @param {*} srcValue The source value. 7224 * @param {string} key The key of the property to assign. 7225 * @param {Object} object The parent object of `objValue`. 7226 * @returns {*} Returns the value to assign. 7227 */ 7228 function customDefaultsAssignIn(objValue, srcValue, key, object) { 7229 if (objValue === undefined || 7230 (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) { 7231 return srcValue; 7232 } 7233 return objValue; 7234 } 7235 7236 /** 7237 * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source 7238 * objects into destination objects that are passed thru. 7239 * 7240 * @private 7241 * @param {*} objValue The destination value. 7242 * @param {*} srcValue The source value. 7243 * @param {string} key The key of the property to merge. 7244 * @param {Object} object The parent object of `objValue`. 7245 * @param {Object} source The parent object of `srcValue`. 7246 * @param {Object} [stack] Tracks traversed source values and their merged 7247 * counterparts. 7248 * @returns {*} Returns the value to assign. 7249 */ 7250 function customDefaultsMerge(objValue, srcValue, key, object, source, stack) { 7251 if (isObject(objValue) && isObject(srcValue)) { 7252 // Recursively merge objects and arrays (susceptible to call stack limits). 7253 stack.set(srcValue, objValue); 7254 baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack); 7255 stack['delete'](srcValue); 7256 } 7257 return objValue; 7258 } 7259 7260 /** 7261 * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain 7262 * objects. 7263 * 7264 * @private 7265 * @param {*} value The value to inspect. 7266 * @param {string} key The key of the property to inspect. 7267 * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`. 7268 */ 7269 function customOmitClone(value) { 7270 return isPlainObject(value) ? undefined : value; 7271 } 7272 7273 /** 7274 * A specialized version of `baseIsEqualDeep` for arrays with support for 7275 * partial deep comparisons. 7276 * 7277 * @private 7278 * @param {Array} array The array to compare. 7279 * @param {Array} other The other array to compare. 7280 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. 7281 * @param {Function} customizer The function to customize comparisons. 7282 * @param {Function} equalFunc The function to determine equivalents of values. 7283 * @param {Object} stack Tracks traversed `array` and `other` objects. 7284 * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. 7285 */ 7286 function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { 7287 var isPartial = bitmask & COMPARE_PARTIAL_FLAG, 7288 arrLength = array.length, 7289 othLength = other.length; 7290 7291 if (arrLength != othLength && !(isPartial && othLength > arrLength)) { 7292 return false; 7293 } 7294 // Check that cyclic values are equal. 7295 var arrStacked = stack.get(array); 7296 var othStacked = stack.get(other); 7297 if (arrStacked && othStacked) { 7298 return arrStacked == other && othStacked == array; 7299 } 7300 var index = -1, 7301 result = true, 7302 seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined; 7303 7304 stack.set(array, other); 7305 stack.set(other, array); 7306 7307 // Ignore non-index properties. 7308 while (++index < arrLength) { 7309 var arrValue = array[index], 7310 othValue = other[index]; 7311 7312 if (customizer) { 7313 var compared = isPartial 7314 ? customizer(othValue, arrValue, index, other, array, stack) 7315 : customizer(arrValue, othValue, index, array, other, stack); 7316 } 7317 if (compared !== undefined) { 7318 if (compared) { 7319 continue; 7320 } 7321 result = false; 7322 break; 7323 } 7324 // Recursively compare arrays (susceptible to call stack limits). 7325 if (seen) { 7326 if (!arraySome(other, function(othValue, othIndex) { 7327 if (!cacheHas(seen, othIndex) && 7328 (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { 7329 return seen.push(othIndex); 7330 } 7331 })) { 7332 result = false;
vendor: 4,179 bytes, lines 7333-7444
7333 break; 7334 } 7335 } else if (!( 7336 arrValue === othValue || 7337 equalFunc(arrValue, othValue, bitmask, customizer, stack) 7338 )) { 7339 result = false; 7340 break; 7341 } 7342 } 7343 stack['delete'](array); 7344 stack['delete'](other); 7345 return result; 7346 } 7347 7348 /** 7349 * A specialized version of `baseIsEqualDeep` for comparing objects of 7350 * the same `toStringTag`. 7351 * 7352 * **Note:** This function only supports comparing values with tags of 7353 * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. 7354 * 7355 * @private 7356 * @param {Object} object The object to compare. 7357 * @param {Object} other The other object to compare. 7358 * @param {string} tag The `toStringTag` of the objects to compare. 7359 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. 7360 * @param {Function} customizer The function to customize comparisons. 7361 * @param {Function} equalFunc The function to determine equivalents of values. 7362 * @param {Object} stack Tracks traversed `object` and `other` objects. 7363 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. 7364 */ 7365 function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { 7366 switch (tag) { 7367 case dataViewTag: 7368 if ((object.byteLength != other.byteLength) || 7369 (object.byteOffset != other.byteOffset)) { 7370 return false; 7371 } 7372 object = object.buffer; 7373 other = other.buffer; 7374 7375 case arrayBufferTag: 7376 if ((object.byteLength != other.byteLength) || 7377 !equalFunc(new Uint8Array(object), new Uint8Array(other))) { 7378 return false; 7379 } 7380 return true; 7381 7382 case boolTag: 7383 case dateTag: 7384 case numberTag: 7385 // Coerce booleans to `1` or `0` and dates to milliseconds. 7386 // Invalid dates are coerced to `NaN`. 7387 return eq(+object, +other); 7388 7389 case errorTag: 7390 return object.name == other.name && object.message == other.message; 7391 7392 case regexpTag: 7393 case stringTag: 7394 // Coerce regexes to strings and treat strings, primitives and objects, 7395 // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring 7396 // for more details. 7397 return object == (other + ''); 7398 7399 case mapTag: 7400 var convert = mapToArray; 7401 7402 case setTag: 7403 var isPartial = bitmask & COMPARE_PARTIAL_FLAG; 7404 convert || (convert = setToArray); 7405 7406 if (object.size != other.size && !isPartial) { 7407 return false; 7408 } 7409 // Assume cyclic values are equal. 7410 var stacked = stack.get(object); 7411 if (stacked) { 7412 return stacked == other; 7413 } 7414 bitmask |= COMPARE_UNORDERED_FLAG; 7415 7416 // Recursively compare objects (susceptible to call stack limits). 7417 stack.set(object, other); 7418 var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); 7419 stack['delete'](object); 7420 return result; 7421 7422 case symbolTag: 7423 if (symbolValueOf) { 7424 return symbolValueOf.call(object) == symbolValueOf.call(other); 7425 } 7426 } 7427 return false; 7428 } 7429 7430 /** 7431 * A specialized version of `baseIsEqualDeep` for objects with support for 7432 * partial deep comparisons. 7433 * 7434 * @private 7435 * @param {Object} object The object to compare. 7436 * @param {Object} other The other object to compare. 7437 * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. 7438 * @param {Function} customizer The function to customize comparisons. 7439 * @param {Function} equalFunc The function to determine equivalents of values. 7440 * @param {Object} stack Tracks traversed `object` and `other` objects. 7441 * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. 7442 */ 7443 function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { 7444 var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
vendor: 9,614 bytes, lines 7445-7752
7445 objProps = getAllKeys(object), 7446 objLength = objProps.length, 7447 othProps = getAllKeys(other), 7448 othLength = othProps.length; 7449 7450 if (objLength != othLength && !isPartial) { 7451 return false; 7452 } 7453 var index = objLength; 7454 while (index--) { 7455 var key = objProps[index]; 7456 if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { 7457 return false; 7458 } 7459 } 7460 // Check that cyclic values are equal. 7461 var objStacked = stack.get(object); 7462 var othStacked = stack.get(other); 7463 if (objStacked && othStacked) { 7464 return objStacked == other && othStacked == object; 7465 } 7466 var result = true; 7467 stack.set(object, other); 7468 stack.set(other, object); 7469 7470 var skipCtor = isPartial; 7471 while (++index < objLength) { 7472 key = objProps[index]; 7473 var objValue = object[key], 7474 othValue = other[key]; 7475 7476 if (customizer) { 7477 var compared = isPartial 7478 ? customizer(othValue, objValue, key, other, object, stack) 7479 : customizer(objValue, othValue, key, object, other, stack); 7480 } 7481 // Recursively compare objects (susceptible to call stack limits). 7482 if (!(compared === undefined 7483 ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) 7484 : compared 7485 )) { 7486 result = false; 7487 break; 7488 } 7489 skipCtor || (skipCtor = key == 'constructor'); 7490 } 7491 if (result && !skipCtor) { 7492 var objCtor = object.constructor, 7493 othCtor = other.constructor; 7494 7495 // Non `Object` object instances with different constructors are not equal. 7496 if (objCtor != othCtor && 7497 ('constructor' in object && 'constructor' in other) && 7498 !(typeof objCtor == 'function' && objCtor instanceof objCtor && 7499 typeof othCtor == 'function' && othCtor instanceof othCtor)) { 7500 result = false; 7501 } 7502 } 7503 stack['delete'](object); 7504 stack['delete'](other); 7505 return result; 7506 } 7507 7508 /** 7509 * A specialized version of `baseRest` which flattens the rest array. 7510 * 7511 * @private 7512 * @param {Function} func The function to apply a rest parameter to. 7513 * @returns {Function} Returns the new function. 7514 */ 7515 function flatRest(func) { 7516 return setToString(overRest(func, undefined, flatten), func + ''); 7517 } 7518 7519 /** 7520 * Creates an array of own enumerable property names and symbols of `object`. 7521 * 7522 * @private 7523 * @param {Object} object The object to query. 7524 * @returns {Array} Returns the array of property names and symbols. 7525 */ 7526 function getAllKeys(object) { 7527 return baseGetAllKeys(object, keys, getSymbols); 7528 } 7529 7530 /** 7531 * Creates an array of own and inherited enumerable property names and 7532 * symbols of `object`. 7533 * 7534 * @private 7535 * @param {Object} object The object to query. 7536 * @returns {Array} Returns the array of property names and symbols. 7537 */ 7538 function getAllKeysIn(object) { 7539 return baseGetAllKeys(object, keysIn, getSymbolsIn); 7540 } 7541 7542 /** 7543 * Gets metadata for `func`. 7544 * 7545 * @private 7546 * @param {Function} func The function to query. 7547 * @returns {*} Returns the metadata for `func`. 7548 */ 7549 var getData = !metaMap ? noop : function(func) { 7550 return metaMap.get(func); 7551 }; 7552 7553 /** 7554 * Gets the name of `func`. 7555 * 7556 * @private 7557 * @param {Function} func The function to query. 7558 * @returns {string} Returns the function name. 7559 */ 7560 function getFuncName(func) { 7561 var result = (func.name + ''), 7562 array = realNames[result], 7563 length = hasOwnProperty.call(realNames, result) ? array.length : 0; 7564 7565 while (length--) { 7566 var data = array[length], 7567 otherFunc = data.func; 7568 if (otherFunc == null || otherFunc == func) { 7569 return data.name; 7570 } 7571 } 7572 return result; 7573 } 7574 7575 /** 7576 * Gets the argument placeholder value for `func`. 7577 * 7578 * @private 7579 * @param {Function} func The function to inspect. 7580 * @returns {*} Returns the placeholder value. 7581 */ 7582 function getHolder(func) { 7583 var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func; 7584 return object.placeholder; 7585 } 7586 7587 /** 7588 * Gets the appropriate "iteratee" function. If `_.iteratee` is customized, 7589 * this function returns the custom method, otherwise it returns `baseIteratee`. 7590 * If arguments are provided, the chosen function is invoked with them and 7591 * its result is returned. 7592 * 7593 * @private 7594 * @param {*} [value] The value to convert to an iteratee. 7595 * @param {number} [arity] The arity of the created iteratee. 7596 * @returns {Function} Returns the chosen function or its result. 7597 */ 7598 function getIteratee() { 7599 var result = lodash.iteratee || iteratee; 7600 result = result === iteratee ? baseIteratee : result; 7601 return arguments.length ? result(arguments[0], arguments[1]) : result; 7602 } 7603 7604 /** 7605 * Gets the data for `map`. 7606 * 7607 * @private 7608 * @param {Object} map The map to query. 7609 * @param {string} key The reference key. 7610 * @returns {*} Returns the map data. 7611 */ 7612 function getMapData(map, key) { 7613 var data = map.__data__; 7614 return isKeyable(key) 7615 ? data[typeof key == 'string' ? 'string' : 'hash'] 7616 : data.map; 7617 } 7618 7619 /** 7620 * Gets the property names, values, and compare flags of `object`. 7621 * 7622 * @private 7623 * @param {Object} object The object to query. 7624 * @returns {Array} Returns the match data of `object`. 7625 */ 7626 function getMatchData(object) { 7627 var result = keys(object), 7628 length = result.length; 7629 7630 while (length--) { 7631 var key = result[length], 7632 value = object[key]; 7633 7634 result[length] = [key, value, isStrictComparable(value)]; 7635 } 7636 return result; 7637 } 7638 7639 /** 7640 * Gets the native function at `key` of `object`. 7641 * 7642 * @private 7643 * @param {Object} object The object to query. 7644 * @param {string} key The key of the method to get. 7645 * @returns {*} Returns the function if it's native, else `undefined`. 7646 */ 7647 function getNative(object, key) { 7648 var value = getValue(object, key); 7649 return baseIsNative(value) ? value : undefined; 7650 } 7651 7652 /** 7653 * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. 7654 * 7655 * @private 7656 * @param {*} value The value to query. 7657 * @returns {string} Returns the raw `toStringTag`. 7658 */ 7659 function getRawTag(value) { 7660 var isOwn = hasOwnProperty.call(value, symToStringTag), 7661 tag = value[symToStringTag]; 7662 7663 try { 7664 value[symToStringTag] = undefined; 7665 var unmasked = true; 7666 } catch (e) {} 7667 7668 var result = nativeObjectToString.call(value); 7669 if (unmasked) { 7670 if (isOwn) { 7671 value[symToStringTag] = tag; 7672 } else { 7673 delete value[symToStringTag]; 7674 } 7675 } 7676 return result; 7677 } 7678 7679 /** 7680 * Creates an array of the own enumerable symbols of `object`. 7681 * 7682 * @private 7683 * @param {Object} object The object to query. 7684 * @returns {Array} Returns the array of symbols. 7685 */ 7686 var getSymbols = !nativeGetSymbols ? stubArray : function(object) { 7687 if (object == null) { 7688 return []; 7689 } 7690 object = Object(object); 7691 return arrayFilter(nativeGetSymbols(object), function(symbol) { 7692 return propertyIsEnumerable.call(object, symbol); 7693 }); 7694 }; 7695 7696 /** 7697 * Creates an array of the own and inherited enumerable symbols of `object`. 7698 * 7699 * @private 7700 * @param {Object} object The object to query. 7701 * @returns {Array} Returns the array of symbols. 7702 */ 7703 var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { 7704 var result = []; 7705 while (object) { 7706 arrayPush(result, getSymbols(object)); 7707 object = getPrototype(object); 7708 } 7709 return result; 7710 }; 7711 7712 /** 7713 * Gets the `toStringTag` of `value`. 7714 * 7715 * @private 7716 * @param {*} value The value to query. 7717 * @returns {string} Returns the `toStringTag`. 7718 */ 7719 var getTag = baseGetTag; 7720 7721 // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. 7722 if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || 7723 (Map && getTag(new Map) != mapTag) || 7724 (Promise && getTag(Promise.resolve()) != promiseTag) || 7725 (Set && getTag(new Set) != setTag) || 7726 (WeakMap && getTag(new WeakMap) != weakMapTag)) { 7727 getTag = function(value) { 7728 var result = baseGetTag(value), 7729 Ctor = result == objectTag ? value.constructor : undefined, 7730 ctorString = Ctor ? toSource(Ctor) : ''; 7731 7732 if (ctorString) { 7733 switch (ctorString) { 7734 case dataViewCtorString: return dataViewTag; 7735 case mapCtorString: return mapTag; 7736 case promiseCtorString: return promiseTag; 7737 case setCtorString: return setTag; 7738 case weakMapCtorString: return weakMapTag; 7739 } 7740 } 7741 return result; 7742 }; 7743 } 7744 7745 /** 7746 * Gets the view, applying any `transforms` to the `start` and `end` positions. 7747 * 7748 * @private 7749 * @param {number} start The start of the view. 7750 * @param {number} end The end of the view. 7751 * @param {Array} transforms The transformations to apply to the view. 7752 * @returns {Object}
vendor: 6,432 bytes, lines 7752-7957
7752 Returns an object containing the `start` and `end` 7753 * positions of the view. 7754 */ 7755 function getView(start, end, transforms) { 7756 var index = -1, 7757 length = transforms.length; 7758 7759 while (++index < length) { 7760 var data = transforms[index], 7761 size = data.size; 7762 7763 switch (data.type) { 7764 case 'drop': start += size; break; 7765 case 'dropRight': end -= size; break; 7766 case 'take': end = nativeMin(end, start + size); break; 7767 case 'takeRight': start = nativeMax(start, end - size); break; 7768 } 7769 } 7770 return { 'start': start, 'end': end }; 7771 } 7772 7773 /** 7774 * Extracts wrapper details from the `source` body comment. 7775 * 7776 * @private 7777 * @param {string} source The source to inspect. 7778 * @returns {Array} Returns the wrapper details. 7779 */ 7780 function getWrapDetails(source) { 7781 var match = source.match(reWrapDetails); 7782 return match ? match[1].split(reSplitDetails) : []; 7783 } 7784 7785 /** 7786 * Checks if `path` exists on `object`. 7787 * 7788 * @private 7789 * @param {Object} object The object to query. 7790 * @param {Array|string} path The path to check. 7791 * @param {Function} hasFunc The function to check properties. 7792 * @returns {boolean} Returns `true` if `path` exists, else `false`. 7793 */ 7794 function hasPath(object, path, hasFunc) { 7795 path = castPath(path, object); 7796 7797 var index = -1, 7798 length = path.length, 7799 result = false; 7800 7801 while (++index < length) { 7802 var key = toKey(path[index]); 7803 if (!(result = object != null && hasFunc(object, key))) { 7804 break; 7805 } 7806 object = object[key]; 7807 } 7808 if (result || ++index != length) { 7809 return result; 7810 } 7811 length = object == null ? 0 : object.length; 7812 return !!length && isLength(length) && isIndex(key, length) && 7813 (isArray(object) || isArguments(object)); 7814 } 7815 7816 /** 7817 * Initializes an array clone. 7818 * 7819 * @private 7820 * @param {Array} array The array to clone. 7821 * @returns {Array} Returns the initialized clone. 7822 */ 7823 function initCloneArray(array) { 7824 var length = array.length, 7825 result = new array.constructor(length); 7826 7827 // Add properties assigned by `RegExp#exec`. 7828 if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { 7829 result.index = array.index; 7830 result.input = array.input; 7831 } 7832 return result; 7833 } 7834 7835 /** 7836 * Initializes an object clone. 7837 * 7838 * @private 7839 * @param {Object} object The object to clone. 7840 * @returns {Object} Returns the initialized clone. 7841 */ 7842 function initCloneObject(object) { 7843 return (typeof object.constructor == 'function' && !isPrototype(object)) 7844 ? baseCreate(getPrototype(object)) 7845 : {}; 7846 } 7847 7848 /** 7849 * Initializes an object clone based on its `toStringTag`. 7850 * 7851 * **Note:** This function only supports cloning values with tags of 7852 * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`. 7853 * 7854 * @private 7855 * @param {Object} object The object to clone. 7856 * @param {string} tag The `toStringTag` of the object to clone. 7857 * @param {boolean} [isDeep] Specify a deep clone. 7858 * @returns {Object} Returns the initialized clone. 7859 */ 7860 function initCloneByTag(object, tag, isDeep) { 7861 var Ctor = object.constructor; 7862 switch (tag) { 7863 case arrayBufferTag: 7864 return cloneArrayBuffer(object); 7865 7866 case boolTag: 7867 case dateTag: 7868 return new Ctor(+object); 7869 7870 case dataViewTag: 7871 return cloneDataView(object, isDeep); 7872 7873 case float32Tag: case float64Tag: 7874 case int8Tag: case int16Tag: case int32Tag: 7875 case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: 7876 return cloneTypedArray(object, isDeep); 7877 7878 case mapTag: 7879 return new Ctor; 7880 7881 case numberTag: 7882 case stringTag: 7883 return new Ctor(object); 7884 7885 case regexpTag: 7886 return cloneRegExp(object); 7887 7888 case setTag: 7889 return new Ctor; 7890 7891 case symbolTag: 7892 return cloneSymbol(object); 7893 } 7894 } 7895 7896 /** 7897 * Inserts wrapper `details` in a comment at the top of the `source` body. 7898 * 7899 * @private 7900 * @param {string} source The source to modify. 7901 * @returns {Array} details The details to insert. 7902 * @returns {string} Returns the modified source. 7903 */ 7904 function insertWrapDetails(source, details) { 7905 var length = details.length; 7906 if (!length) { 7907 return source; 7908 } 7909 var lastIndex = length - 1; 7910 details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex]; 7911 details = details.join(length > 2 ? ', ' : ' '); 7912 return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n'); 7913 } 7914 7915 /** 7916 * Checks if `value` is a flattenable `arguments` object or array. 7917 * 7918 * @private 7919 * @param {*} value The value to check. 7920 * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. 7921 */ 7922 function isFlattenable(value) { 7923 return isArray(value) || isArguments(value) || 7924 !!(spreadableSymbol && value && value[spreadableSymbol]); 7925 } 7926 7927 /** 7928 * Checks if `value` is a valid array-like index. 7929 * 7930 * @private 7931 * @param {*} value The value to check. 7932 * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. 7933 * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. 7934 */ 7935 function isIndex(value, length) { 7936 var type = typeof value; 7937 length = length == null ? MAX_SAFE_INTEGER : length; 7938 7939 return !!length && 7940 (type == 'number' || 7941 (type != 'symbol' && reIsUint.test(value))) && 7942 (value > -1 && value % 1 == 0 && value < length); 7943 } 7944 7945 /** 7946 * Checks if the given arguments are from an iteratee call. 7947 * 7948 * @private 7949 * @param {*} value The potential iteratee value argument. 7950 * @param {*} index The potential iteratee index or key argument. 7951 * @param {*} object The potential iteratee object argument. 7952 * @returns {boolean} Returns `true` if the arguments are from an iteratee call, 7953 * else `false`. 7954 */ 7955 function isIterateeCall(value, index, object) { 7956 if (!isObject(object)) { 7957 return false;
vendor: 14,387 bytes, lines 7958-8404
7958 } 7959 var type = typeof index; 7960 if (type == 'number' 7961 ? (isArrayLike(object) && isIndex(index, object.length)) 7962 : (type == 'string' && index in object) 7963 ) { 7964 return eq(object[index], value); 7965 } 7966 return false; 7967 } 7968 7969 /** 7970 * Checks if `value` is a property name and not a property path. 7971 * 7972 * @private 7973 * @param {*} value The value to check. 7974 * @param {Object} [object] The object to query keys on. 7975 * @returns {boolean} Returns `true` if `value` is a property name, else `false`. 7976 */ 7977 function isKey(value, object) { 7978 if (isArray(value)) { 7979 return false; 7980 } 7981 var type = typeof value; 7982 if (type == 'number' || type == 'symbol' || type == 'boolean' || 7983 value == null || isSymbol(value)) { 7984 return true; 7985 } 7986 return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || 7987 (object != null && value in Object(object)); 7988 } 7989 7990 /** 7991 * Checks if `value` is suitable for use as unique object key. 7992 * 7993 * @private 7994 * @param {*} value The value to check. 7995 * @returns {boolean} Returns `true` if `value` is suitable, else `false`. 7996 */ 7997 function isKeyable(value) { 7998 var type = typeof value; 7999 return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') 8000 ? (value !== '__proto__') 8001 : (value === null); 8002 } 8003 8004 /** 8005 * Checks if `func` has a lazy counterpart. 8006 * 8007 * @private 8008 * @param {Function} func The function to check. 8009 * @returns {boolean} Returns `true` if `func` has a lazy counterpart, 8010 * else `false`. 8011 */ 8012 function isLaziable(func) { 8013 var funcName = getFuncName(func), 8014 other = lodash[funcName]; 8015 8016 if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) { 8017 return false; 8018 } 8019 if (func === other) { 8020 return true; 8021 } 8022 var data = getData(other); 8023 return !!data && func === data[0]; 8024 } 8025 8026 /** 8027 * Checks if `func` has its source masked. 8028 * 8029 * @private 8030 * @param {Function} func The function to check. 8031 * @returns {boolean} Returns `true` if `func` is masked, else `false`. 8032 */ 8033 function isMasked(func) { 8034 return !!maskSrcKey && (maskSrcKey in func); 8035 } 8036 8037 /** 8038 * Checks if `func` is capable of being masked. 8039 * 8040 * @private 8041 * @param {*} value The value to check. 8042 * @returns {boolean} Returns `true` if `func` is maskable, else `false`. 8043 */ 8044 var isMaskable = coreJsData ? isFunction : stubFalse; 8045 8046 /** 8047 * Checks if `value` is likely a prototype object. 8048 * 8049 * @private 8050 * @param {*} value The value to check. 8051 * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. 8052 */ 8053 function isPrototype(value) { 8054 var Ctor = value && value.constructor, 8055 proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; 8056 8057 return value === proto; 8058 } 8059 8060 /** 8061 * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. 8062 * 8063 * @private 8064 * @param {*} value The value to check. 8065 * @returns {boolean} Returns `true` if `value` if suitable for strict 8066 * equality comparisons, else `false`. 8067 */ 8068 function isStrictComparable(value) { 8069 return value === value && !isObject(value); 8070 } 8071 8072 /** 8073 * A specialized version of `matchesProperty` for source values suitable 8074 * for strict equality comparisons, i.e. `===`. 8075 * 8076 * @private 8077 * @param {string} key The key of the property to get. 8078 * @param {*} srcValue The value to match. 8079 * @returns {Function} Returns the new spec function. 8080 */ 8081 function matchesStrictComparable(key, srcValue) { 8082 return function(object) { 8083 if (object == null) { 8084 return false; 8085 } 8086 return object[key] === srcValue && 8087 (srcValue !== undefined || (key in Object(object))); 8088 }; 8089 } 8090 8091 /** 8092 * A specialized version of `_.memoize` which clears the memoized function's 8093 * cache when it exceeds `MAX_MEMOIZE_SIZE`. 8094 * 8095 * @private 8096 * @param {Function} func The function to have its output memoized. 8097 * @returns {Function} Returns the new memoized function. 8098 */ 8099 function memoizeCapped(func) { 8100 var result = memoize(func, function(key) { 8101 if (cache.size === MAX_MEMOIZE_SIZE) { 8102 cache.clear(); 8103 } 8104 return key; 8105 }); 8106 8107 var cache = result.cache; 8108 return result; 8109 } 8110 8111 /** 8112 * Merges the function metadata of `source` into `data`. 8113 * 8114 * Merging metadata reduces the number of wrappers used to invoke a function. 8115 * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` 8116 * may be applied regardless of execution order. Methods like `_.ary` and 8117 * `_.rearg` modify function arguments, making the order in which they are 8118 * executed important, preventing the merging of metadata. However, we make 8119 * an exception for a safe combined case where curried functions have `_.ary` 8120 * and or `_.rearg` applied. 8121 * 8122 * @private 8123 * @param {Array} data The destination metadata. 8124 * @param {Array} source The source metadata. 8125 * @returns {Array} Returns `data`. 8126 */ 8127 function mergeData(data, source) { 8128 var bitmask = data[1], 8129 srcBitmask = source[1], 8130 newBitmask = bitmask | srcBitmask, 8131 isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG); 8132 8133 var isCombo = 8134 ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) || 8135 ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) || 8136 ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG)); 8137 8138 // Exit early if metadata can't be merged. 8139 if (!(isCommon || isCombo)) { 8140 return data; 8141 } 8142 // Use source `thisArg` if available. 8143 if (srcBitmask & WRAP_BIND_FLAG) { 8144 data[2] = source[2]; 8145 // Set when currying a bound function. 8146 newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG; 8147 } 8148 // Compose partial arguments. 8149 var value = source[3]; 8150 if (value) { 8151 var partials = data[3]; 8152 data[3] = partials ? composeArgs(partials, value, source[4]) : value; 8153 data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4]; 8154 } 8155 // Compose partial right arguments. 8156 value = source[5]; 8157 if (value) { 8158 partials = data[5]; 8159 data[5] = partials ? composeArgsRight(partials, value, source[6]) : value; 8160 data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6]; 8161 } 8162 // Use source `argPos` if available. 8163 value = source[7]; 8164 if (value) { 8165 data[7] = value; 8166 } 8167 // Use source `ary` if it's smaller. 8168 if (srcBitmask & WRAP_ARY_FLAG) { 8169 data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); 8170 } 8171 // Use source `arity` if one is not provided. 8172 if (data[9] == null) { 8173 data[9] = source[9]; 8174 } 8175 // Use source `func` and merge bitmasks. 8176 data[0] = source[0]; 8177 data[1] = newBitmask; 8178 8179 return data; 8180 } 8181 8182 /** 8183 * This function is like 8184 * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) 8185 * except that it includes inherited enumerable properties. 8186 * 8187 * @private 8188 * @param {Object} object The object to query. 8189 * @returns {Array} Returns the array of property names. 8190 */ 8191 function nativeKeysIn(object) { 8192 var result = []; 8193 if (object != null) { 8194 for (var key in Object(object)) { 8195 result.push(key); 8196 } 8197 } 8198 return result; 8199 } 8200 8201 /** 8202 * Converts `value` to a string using `Object.prototype.toString`. 8203 * 8204 * @private 8205 * @param {*} value The value to convert. 8206 * @returns {string} Returns the converted string. 8207 */ 8208 function objectToString(value) { 8209 return nativeObjectToString.call(value); 8210 } 8211 8212 /** 8213 * A specialized version of `baseRest` which transforms the rest array. 8214 * 8215 * @private 8216 * @param {Function} func The function to apply a rest parameter to. 8217 * @param {number} [start=func.length-1] The start position of the rest parameter. 8218 * @param {Function} transform The rest array transform. 8219 * @returns {Function} Returns the new function. 8220 */ 8221 function overRest(func, start, transform) { 8222 start = nativeMax(start === undefined ? (func.length - 1) : start, 0); 8223 return function() { 8224 var args = arguments, 8225 index = -1, 8226 length = nativeMax(args.length - start, 0), 8227 array = Array(length); 8228 8229 while (++index < length) { 8230 array[index] = args[start + index]; 8231 } 8232 index = -1; 8233 var otherArgs = Array(start + 1); 8234 while (++index < start) { 8235 otherArgs[index] = args[index]; 8236 } 8237 otherArgs[start] = transform(array); 8238 return apply(func, this, otherArgs); 8239 }; 8240 } 8241 8242 /** 8243 * Gets the parent value at `path` of `object`. 8244 * 8245 * @private 8246 * @param {Object} object The object to query. 8247 * @param {Array} path The path to get the parent value of. 8248 * @returns {*} Returns the parent value. 8249 */ 8250 function parent(object, path) { 8251 return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1)); 8252 } 8253 8254 /** 8255 * Reorder `array` according to the specified indexes where the element at 8256 * the first index is assigned as the first element, the element at 8257 * the second index is assigned as the second element, and so on. 8258 * 8259 * @private 8260 * @param {Array} array The array to reorder. 8261 * @param {Array} indexes The arranged array indexes. 8262 * @returns {Array} Returns `array`. 8263 */ 8264 function reorder(array, indexes) { 8265 var arrLength = array.length, 8266 length = nativeMin(indexes.length, arrLength), 8267 oldArray = copyArray(array); 8268 8269 while (length--) { 8270 var index = indexes[length]; 8271 array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; 8272 } 8273 return array; 8274 } 8275 8276 /** 8277 * Gets the value at `key`, unless `key` is "__proto__" or "constructor". 8278 * 8279 * @private 8280 * @param {Object} object The object to query. 8281 * @param {string} key The key of the property to get. 8282 * @returns {*} Returns the property value. 8283 */ 8284 function safeGet(object, key) { 8285 if (key === 'constructor' && typeof object[key] === 'function') { 8286 return; 8287 } 8288 8289 if (key == '__proto__') { 8290 return; 8291 } 8292 8293 return object[key]; 8294 } 8295 8296 /** 8297 * Sets metadata for `func`. 8298 * 8299 * **Note:** If this function becomes hot, i.e. is invoked a lot in a short 8300 * period of time, it will trip its breaker and transition to an identity 8301 * function to avoid garbage collection pauses in V8. See 8302 * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070) 8303 * for more details. 8304 * 8305 * @private 8306 * @param {Function} func The function to associate metadata with. 8307 * @param {*} data The metadata. 8308 * @returns {Function} Returns `func`. 8309 */ 8310 var setData = shortOut(baseSetData); 8311 8312 /** 8313 * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout). 8314 * 8315 * @private 8316 * @param {Function} func The function to delay. 8317 * @param {number} wait The number of milliseconds to delay invocation. 8318 * @returns {number|Object} Returns the timer id or timeout object. 8319 */ 8320 var setTimeout = ctxSetTimeout || function(func, wait) { 8321 return root.setTimeout(func, wait); 8322 }; 8323 8324 /** 8325 * Sets the `toString` method of `func` to return `string`. 8326 * 8327 * @private 8328 * @param {Function} func The function to modify. 8329 * @param {Function} string The `toString` result. 8330 * @returns {Function} Returns `func`. 8331 */ 8332 var setToString = shortOut(baseSetToString); 8333 8334 /** 8335 * Sets the `toString` method of `wrapper` to mimic the source of `reference` 8336 * with wrapper details in a comment at the top of the source body. 8337 * 8338 * @private 8339 * @param {Function} wrapper The function to modify. 8340 * @param {Function} reference The reference function. 8341 * @param {number} bitmask The bitmask flags. See `createWrap` for more details. 8342 * @returns {Function} Returns `wrapper`. 8343 */ 8344 function setWrapToString(wrapper, reference, bitmask) { 8345 var source = (reference + ''); 8346 return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); 8347 } 8348 8349 /** 8350 * Creates a function that'll short out and invoke `identity` instead 8351 * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` 8352 * milliseconds. 8353 * 8354 * @private 8355 * @param {Function} func The function to restrict. 8356 * @returns {Function} Returns the new shortable function. 8357 */ 8358 function shortOut(func) { 8359 var count = 0, 8360 lastCalled = 0; 8361 8362 return function() { 8363 var stamp = nativeNow(), 8364 remaining = HOT_SPAN - (stamp - lastCalled); 8365 8366 lastCalled = stamp; 8367 if (remaining > 0) { 8368 if (++count >= HOT_COUNT) { 8369 return arguments[0]; 8370 } 8371 } else { 8372 count = 0; 8373 } 8374 return func.apply(undefined, arguments); 8375 }; 8376 } 8377 8378 /** 8379 * A specialized version of `_.shuffle` which mutates and sets the size of `array`. 8380 * 8381 * @private 8382 * @param {Array} array The array to shuffle. 8383 * @param {number} [size=array.length] The size of `array`. 8384 * @returns {Array} Returns `array`. 8385 */ 8386 function shuffleSelf(array, size) { 8387 var index = -1, 8388 length = array.length, 8389 lastIndex = length - 1; 8390 8391 size = size === undefined ? length : size; 8392 while (++index < size) { 8393 var rand = baseRandom(index, lastIndex), 8394 value = array[rand]; 8395 8396 array[rand] = array[index]; 8397 array[index] = value; 8398 } 8399 array.length = size; 8400 return array; 8401 } 8402 8403 /** 8404 * Converts `string` to a property path array.
vendor: 1,775 bytes, lines 8405-8465
8405 * 8406 * @private 8407 * @param {string} string The string to convert. 8408 * @returns {Array} Returns the property path array. 8409 */ 8410 var stringToPath = memoizeCapped(function(string) { 8411 var result = []; 8412 if (string.charCodeAt(0) === 46 /* . */) { 8413 result.push(''); 8414 } 8415 string.replace(rePropName, function(match, number, quote, subString) { 8416 result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match)); 8417 }); 8418 return result; 8419 }); 8420 8421 /** 8422 * Converts `value` to a string key if it's not a string or symbol. 8423 * 8424 * @private 8425 * @param {*} value The value to inspect. 8426 * @returns {string|symbol} Returns the key. 8427 */ 8428 function toKey(value) { 8429 if (typeof value == 'string' || isSymbol(value)) { 8430 return value; 8431 } 8432 var result = (value + ''); 8433 return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; 8434 } 8435 8436 /** 8437 * Converts `func` to its source code. 8438 * 8439 * @private 8440 * @param {Function} func The function to convert. 8441 * @returns {string} Returns the source code. 8442 */ 8443 function toSource(func) { 8444 if (func != null) { 8445 try { 8446 return funcToString.call(func); 8447 } catch (e) {} 8448 try { 8449 return (func + ''); 8450 } catch (e) {} 8451 } 8452 return ''; 8453 } 8454 8455 /** 8456 * Updates wrapper `details` based on `bitmask` flags. 8457 * 8458 * @private 8459 * @returns {Array} details The details to modify. 8460 * @param {number} bitmask The bitmask flags. See `createWrap` for more details. 8461 * @returns {Array} Returns `details`. 8462 */ 8463 function updateWrapDetails(details, bitmask) { 8464 arrayEach(wrapFlags, function(pair) { 8465 var value = '_.' + pair[0];
vendor: 80,381 bytes, lines 8466-11049
8466 if ((bitmask & pair[1]) && !arrayIncludes(details, value)) { 8467 details.push(value); 8468 } 8469 }); 8470 return details.sort(); 8471 } 8472 8473 /** 8474 * Creates a clone of `wrapper`. 8475 * 8476 * @private 8477 * @param {Object} wrapper The wrapper to clone. 8478 * @returns {Object} Returns the cloned wrapper. 8479 */ 8480 function wrapperClone(wrapper) { 8481 if (wrapper instanceof LazyWrapper) { 8482 return wrapper.clone(); 8483 } 8484 var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); 8485 result.__actions__ = copyArray(wrapper.__actions__); 8486 result.__index__ = wrapper.__index__; 8487 result.__values__ = wrapper.__values__; 8488 return result; 8489 } 8490 8491 /*------------------------------------------------------------------------*/ 8492 8493 /** 8494 * Creates an array of elements split into groups the length of `size`. 8495 * If `array` can't be split evenly, the final chunk will be the remaining 8496 * elements. 8497 * 8498 * @static 8499 * @memberOf _ 8500 * @since 3.0.0 8501 * @category Array 8502 * @param {Array} array The array to process. 8503 * @param {number} [size=1] The length of each chunk 8504 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 8505 * @returns {Array} Returns the new array of chunks. 8506 * @example 8507 * 8508 * _.chunk(['a', 'b', 'c', 'd'], 2); 8509 * // => [['a', 'b'], ['c', 'd']] 8510 * 8511 * _.chunk(['a', 'b', 'c', 'd'], 3); 8512 * // => [['a', 'b', 'c'], ['d']] 8513 */ 8514 function chunk(array, size, guard) { 8515 if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) { 8516 size = 1; 8517 } else { 8518 size = nativeMax(toInteger(size), 0); 8519 } 8520 var length = array == null ? 0 : array.length; 8521 if (!length || size < 1) { 8522 return []; 8523 } 8524 var index = 0, 8525 resIndex = 0, 8526 result = Array(nativeCeil(length / size)); 8527 8528 while (index < length) { 8529 result[resIndex++] = baseSlice(array, index, (index += size)); 8530 } 8531 return result; 8532 } 8533 8534 /** 8535 * Creates an array with all falsey values removed. The values `false`, `null`, 8536 * `0`, `""`, `undefined`, and `NaN` are falsey. 8537 * 8538 * @static 8539 * @memberOf _ 8540 * @since 0.1.0 8541 * @category Array 8542 * @param {Array} array The array to compact. 8543 * @returns {Array} Returns the new array of filtered values. 8544 * @example 8545 * 8546 * _.compact([0, 1, false, 2, '', 3]); 8547 * // => [1, 2, 3] 8548 */ 8549 function compact(array) { 8550 var index = -1, 8551 length = array == null ? 0 : array.length, 8552 resIndex = 0, 8553 result = []; 8554 8555 while (++index < length) { 8556 var value = array[index]; 8557 if (value) { 8558 result[resIndex++] = value; 8559 } 8560 } 8561 return result; 8562 } 8563 8564 /** 8565 * Creates a new array concatenating `array` with any additional arrays 8566 * and/or values. 8567 * 8568 * @static 8569 * @memberOf _ 8570 * @since 4.0.0 8571 * @category Array 8572 * @param {Array} array The array to concatenate. 8573 * @param {...*} [values] The values to concatenate. 8574 * @returns {Array} Returns the new concatenated array. 8575 * @example 8576 * 8577 * var array = [1]; 8578 * var other = _.concat(array, 2, [3], [[4]]); 8579 * 8580 * console.log(other); 8581 * // => [1, 2, 3, [4]] 8582 * 8583 * console.log(array); 8584 * // => [1] 8585 */ 8586 function concat() { 8587 var length = arguments.length; 8588 if (!length) { 8589 return []; 8590 } 8591 var args = Array(length - 1), 8592 array = arguments[0], 8593 index = length; 8594 8595 while (index--) { 8596 args[index - 1] = arguments[index]; 8597 } 8598 return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); 8599 } 8600 8601 /** 8602 * Creates an array of `array` values not included in the other given arrays 8603 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) 8604 * for equality comparisons. The order and references of result values are 8605 * determined by the first array. 8606 * 8607 * **Note:** Unlike `_.pullAll`, this method returns a new array. 8608 * 8609 * @static 8610 * @memberOf _ 8611 * @since 0.1.0 8612 * @category Array 8613 * @param {Array} array The array to inspect. 8614 * @param {...Array} [values] The values to exclude. 8615 * @returns {Array} Returns the new array of filtered values. 8616 * @see _.without, _.xor 8617 * @example 8618 * 8619 * _.difference([2, 1], [2, 3]); 8620 * // => [1] 8621 */ 8622 var difference = baseRest(function(array, values) { 8623 return isArrayLikeObject(array) 8624 ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) 8625 : []; 8626 }); 8627 8628 /** 8629 * This method is like `_.difference` except that it accepts `iteratee` which 8630 * is invoked for each element of `array` and `values` to generate the criterion 8631 * by which they're compared. The order and references of result values are 8632 * determined by the first array. The iteratee is invoked with one argument: 8633 * (value). 8634 * 8635 * **Note:** Unlike `_.pullAllBy`, this method returns a new array. 8636 * 8637 * @static 8638 * @memberOf _ 8639 * @since 4.0.0 8640 * @category Array 8641 * @param {Array} array The array to inspect. 8642 * @param {...Array} [values] The values to exclude. 8643 * @param {Function} [iteratee=_.identity] The iteratee invoked per element. 8644 * @returns {Array} Returns the new array of filtered values. 8645 * @example 8646 * 8647 * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); 8648 * // => [1.2] 8649 * 8650 * // The `_.property` iteratee shorthand. 8651 * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x'); 8652 * // => [{ 'x': 2 }] 8653 */ 8654 var differenceBy = baseRest(function(array, values) { 8655 var iteratee = last(values); 8656 if (isArrayLikeObject(iteratee)) { 8657 iteratee = undefined; 8658 } 8659 return isArrayLikeObject(array) 8660 ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)) 8661 : []; 8662 }); 8663 8664 /** 8665 * This method is like `_.difference` except that it accepts `comparator` 8666 * which is invoked to compare elements of `array` to `values`. The order and 8667 * references of result values are determined by the first array. The comparator 8668 * is invoked with two arguments: (arrVal, othVal). 8669 * 8670 * **Note:** Unlike `_.pullAllWith`, this method returns a new array. 8671 * 8672 * @static 8673 * @memberOf _ 8674 * @since 4.0.0 8675 * @category Array 8676 * @param {Array} array The array to inspect. 8677 * @param {...Array} [values] The values to exclude. 8678 * @param {Function} [comparator] The comparator invoked per element. 8679 * @returns {Array} Returns the new array of filtered values. 8680 * @example 8681 * 8682 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; 8683 * 8684 * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual); 8685 * // => [{ 'x': 2, 'y': 1 }] 8686 */ 8687 var differenceWith = baseRest(function(array, values) { 8688 var comparator = last(values); 8689 if (isArrayLikeObject(comparator)) { 8690 comparator = undefined; 8691 } 8692 return isArrayLikeObject(array) 8693 ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator) 8694 : []; 8695 }); 8696 8697 /** 8698 * Creates a slice of `array` with `n` elements dropped from the beginning. 8699 * 8700 * @static 8701 * @memberOf _ 8702 * @since 0.5.0 8703 * @category Array 8704 * @param {Array} array The array to query. 8705 * @param {number} [n=1] The number of elements to drop. 8706 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 8707 * @returns {Array} Returns the slice of `array`. 8708 * @example 8709 * 8710 * _.drop([1, 2, 3]); 8711 * // => [2, 3] 8712 * 8713 * _.drop([1, 2, 3], 2); 8714 * // => [3] 8715 * 8716 * _.drop([1, 2, 3], 5); 8717 * // => [] 8718 * 8719 * _.drop([1, 2, 3], 0); 8720 * // => [1, 2, 3] 8721 */ 8722 function drop(array, n, guard) { 8723 var length = array == null ? 0 : array.length; 8724 if (!length) { 8725 return []; 8726 } 8727 n = (guard || n === undefined) ? 1 : toInteger(n); 8728 return baseSlice(array, n < 0 ? 0 : n, length); 8729 } 8730 8731 /** 8732 * Creates a slice of `array` with `n` elements dropped from the end. 8733 * 8734 * @static 8735 * @memberOf _ 8736 * @since 3.0.0 8737 * @category Array 8738 * @param {Array} array The array to query. 8739 * @param {number} [n=1] The number of elements to drop. 8740 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 8741 * @returns {Array} Returns the slice of `array`. 8742 * @example 8743 * 8744 * _.dropRight([1, 2, 3]); 8745 * // => [1, 2] 8746 * 8747 * _.dropRight([1, 2, 3], 2); 8748 * // => [1] 8749 * 8750 * _.dropRight([1, 2, 3], 5); 8751 * // => [] 8752 * 8753 * _.dropRight([1, 2, 3], 0); 8754 * // => [1, 2, 3] 8755 */ 8756 function dropRight(array, n, guard) { 8757 var length = array == null ? 0 : array.length; 8758 if (!length) { 8759 return []; 8760 } 8761 n = (guard || n === undefined) ? 1 : toInteger(n); 8762 n = length - n; 8763 return baseSlice(array, 0, n < 0 ? 0 : n); 8764 } 8765 8766 /** 8767 * Creates a slice of `array` excluding elements dropped from the end. 8768 * Elements are dropped until `predicate` returns falsey. The predicate is 8769 * invoked with three arguments: (value, index, array). 8770 * 8771 * @static 8772 * @memberOf _ 8773 * @since 3.0.0 8774 * @category Array 8775 * @param {Array} array The array to query. 8776 * @param {Function} [predicate=_.identity] The function invoked per iteration. 8777 * @returns {Array} Returns the slice of `array`. 8778 * @example 8779 * 8780 * var users = [ 8781 * { 'user': 'barney', 'active': true }, 8782 * { 'user': 'fred', 'active': false }, 8783 * { 'user': 'pebbles', 'active': false } 8784 * ]; 8785 * 8786 * _.dropRightWhile(users, function(o) { return !o.active; }); 8787 * // => objects for ['barney'] 8788 * 8789 * // The `_.matches` iteratee shorthand. 8790 * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false }); 8791 * // => objects for ['barney', 'fred'] 8792 * 8793 * // The `_.matchesProperty` iteratee shorthand. 8794 * _.dropRightWhile(users, ['active', false]); 8795 * // => objects for ['barney'] 8796 * 8797 * // The `_.property` iteratee shorthand. 8798 * _.dropRightWhile(users, 'active'); 8799 * // => objects for ['barney', 'fred', 'pebbles'] 8800 */ 8801 function dropRightWhile(array, predicate) { 8802 return (array && array.length) 8803 ? baseWhile(array, getIteratee(predicate, 3), true, true) 8804 : []; 8805 } 8806 8807 /** 8808 * Creates a slice of `array` excluding elements dropped from the beginning. 8809 * Elements are dropped until `predicate` returns falsey. The predicate is 8810 * invoked with three arguments: (value, index, array). 8811 * 8812 * @static 8813 * @memberOf _ 8814 * @since 3.0.0 8815 * @category Array 8816 * @param {Array} array The array to query. 8817 * @param {Function} [predicate=_.identity] The function invoked per iteration. 8818 * @returns {Array} Returns the slice of `array`. 8819 * @example 8820 * 8821 * var users = [ 8822 * { 'user': 'barney', 'active': false }, 8823 * { 'user': 'fred', 'active': false }, 8824 * { 'user': 'pebbles', 'active': true } 8825 * ]; 8826 * 8827 * _.dropWhile(users, function(o) { return !o.active; }); 8828 * // => objects for ['pebbles'] 8829 * 8830 * // The `_.matches` iteratee shorthand. 8831 * _.dropWhile(users, { 'user': 'barney', 'active': false }); 8832 * // => objects for ['fred', 'pebbles'] 8833 * 8834 * // The `_.matchesProperty` iteratee shorthand. 8835 * _.dropWhile(users, ['active', false]); 8836 * // => objects for ['pebbles'] 8837 * 8838 * // The `_.property` iteratee shorthand. 8839 * _.dropWhile(users, 'active'); 8840 * // => objects for ['barney', 'fred', 'pebbles'] 8841 */ 8842 function dropWhile(array, predicate) { 8843 return (array && array.length) 8844 ? baseWhile(array, getIteratee(predicate, 3), true) 8845 : []; 8846 } 8847 8848 /** 8849 * Fills elements of `array` with `value` from `start` up to, but not 8850 * including, `end`. 8851 * 8852 * **Note:** This method mutates `array`. 8853 * 8854 * @static 8855 * @memberOf _ 8856 * @since 3.2.0 8857 * @category Array 8858 * @param {Array} array The array to fill. 8859 * @param {*} value The value to fill `array` with. 8860 * @param {number} [start=0] The start position. 8861 * @param {number} [end=array.length] The end position. 8862 * @returns {Array} Returns `array`. 8863 * @example 8864 * 8865 * var array = [1, 2, 3]; 8866 * 8867 * _.fill(array, 'a'); 8868 * console.log(array); 8869 * // => ['a', 'a', 'a'] 8870 * 8871 * _.fill(Array(3), 2); 8872 * // => [2, 2, 2] 8873 * 8874 * _.fill([4, 6, 8, 10], '*', 1, 3); 8875 * // => [4, '*', '*', 10] 8876 */ 8877 function fill(array, value, start, end) { 8878 var length = array == null ? 0 : array.length; 8879 if (!length) { 8880 return []; 8881 } 8882 if (start && typeof start != 'number' && isIterateeCall(array, value, start)) { 8883 start = 0; 8884 end = length; 8885 } 8886 return baseFill(array, value, start, end); 8887 } 8888 8889 /** 8890 * This method is like `_.find` except that it returns the index of the first 8891 * element `predicate` returns truthy for instead of the element itself. 8892 * 8893 * @static 8894 * @memberOf _ 8895 * @since 1.1.0 8896 * @category Array 8897 * @param {Array} array The array to inspect. 8898 * @param {Function} [predicate=_.identity] The function invoked per iteration. 8899 * @param {number} [fromIndex=0] The index to search from. 8900 * @returns {number} Returns the index of the found element, else `-1`. 8901 * @example 8902 * 8903 * var users = [ 8904 * { 'user': 'barney', 'active': false }, 8905 * { 'user': 'fred', 'active': false }, 8906 * { 'user': 'pebbles', 'active': true } 8907 * ]; 8908 * 8909 * _.findIndex(users, function(o) { return o.user == 'barney'; }); 8910 * // => 0 8911 * 8912 * // The `_.matches` iteratee shorthand. 8913 * _.findIndex(users, { 'user': 'fred', 'active': false }); 8914 * // => 1 8915 * 8916 * // The `_.matchesProperty` iteratee shorthand. 8917 * _.findIndex(users, ['active', false]); 8918 * // => 0 8919 * 8920 * // The `_.property` iteratee shorthand. 8921 * _.findIndex(users, 'active'); 8922 * // => 2 8923 */ 8924 function findIndex(array, predicate, fromIndex) { 8925 var length = array == null ? 0 : array.length; 8926 if (!length) { 8927 return -1; 8928 } 8929 var index = fromIndex == null ? 0 : toInteger(fromIndex); 8930 if (index < 0) { 8931 index = nativeMax(length + index, 0); 8932 } 8933 return baseFindIndex(array, getIteratee(predicate, 3), index); 8934 } 8935 8936 /** 8937 * This method is like `_.findIndex` except that it iterates over elements 8938 * of `collection` from right to left. 8939 * 8940 * @static 8941 * @memberOf _ 8942 * @since 2.0.0 8943 * @category Array 8944 * @param {Array} array The array to inspect. 8945 * @param {Function} [predicate=_.identity] The function invoked per iteration. 8946 * @param {number} [fromIndex=array.length-1] The index to search from. 8947 * @returns {number} Returns the index of the found element, else `-1`. 8948 * @example 8949 * 8950 * var users = [ 8951 * { 'user': 'barney', 'active': true }, 8952 * { 'user': 'fred', 'active': false }, 8953 * { 'user': 'pebbles', 'active': false } 8954 * ]; 8955 * 8956 * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; }); 8957 * // => 2 8958 * 8959 * // The `_.matches` iteratee shorthand. 8960 * _.findLastIndex(users, { 'user': 'barney', 'active': true }); 8961 * // => 0 8962 * 8963 * // The `_.matchesProperty` iteratee shorthand. 8964 * _.findLastIndex(users, ['active', false]); 8965 * // => 2 8966 * 8967 * // The `_.property` iteratee shorthand. 8968 * _.findLastIndex(users, 'active'); 8969 * // => 0 8970 */ 8971 function findLastIndex(array, predicate, fromIndex) { 8972 var length = array == null ? 0 : array.length; 8973 if (!length) { 8974 return -1; 8975 } 8976 var index = length - 1; 8977 if (fromIndex !== undefined) { 8978 index = toInteger(fromIndex); 8979 index = fromIndex < 0 8980 ? nativeMax(length + index, 0) 8981 : nativeMin(index, length - 1); 8982 } 8983 return baseFindIndex(array, getIteratee(predicate, 3), index, true); 8984 } 8985 8986 /** 8987 * Flattens `array` a single level deep. 8988 * 8989 * @static 8990 * @memberOf _ 8991 * @since 0.1.0 8992 * @category Array 8993 * @param {Array} array The array to flatten. 8994 * @returns {Array} Returns the new flattened array. 8995 * @example 8996 * 8997 * _.flatten([1, [2, [3, [4]], 5]]); 8998 * // => [1, 2, [3, [4]], 5] 8999 */ 9000 function flatten(array) { 9001 var length = array == null ? 0 : array.length; 9002 return length ? baseFlatten(array, 1) : []; 9003 } 9004 9005 /** 9006 * Recursively flattens `array`. 9007 * 9008 * @static 9009 * @memberOf _ 9010 * @since 3.0.0 9011 * @category Array 9012 * @param {Array} array The array to flatten. 9013 * @returns {Array} Returns the new flattened array. 9014 * @example 9015 * 9016 * _.flattenDeep([1, [2, [3, [4]], 5]]); 9017 * // => [1, 2, 3, 4, 5] 9018 */ 9019 function flattenDeep(array) { 9020 var length = array == null ? 0 : array.length; 9021 return length ? baseFlatten(array, INFINITY) : []; 9022 } 9023 9024 /** 9025 * Recursively flatten `array` up to `depth` times. 9026 * 9027 * @static 9028 * @memberOf _ 9029 * @since 4.4.0 9030 * @category Array 9031 * @param {Array} array The array to flatten. 9032 * @param {number} [depth=1] The maximum recursion depth. 9033 * @returns {Array} Returns the new flattened array. 9034 * @example 9035 * 9036 * var array = [1, [2, [3, [4]], 5]]; 9037 * 9038 * _.flattenDepth(array, 1); 9039 * // => [1, 2, [3, [4]], 5] 9040 * 9041 * _.flattenDepth(array, 2); 9042 * // => [1, 2, 3, [4], 5] 9043 */ 9044 function flattenDepth(array, depth) { 9045 var length = array == null ? 0 : array.length; 9046 if (!length) { 9047 return []; 9048 } 9049 depth = depth === undefined ? 1 : toInteger(depth); 9050 return baseFlatten(array, depth); 9051 } 9052 9053 /** 9054 * The inverse of `_.toPairs`; this method returns an object composed 9055 * from key-value `pairs`. 9056 * 9057 * @static 9058 * @memberOf _ 9059 * @since 4.0.0 9060 * @category Array 9061 * @param {Array} pairs The key-value pairs. 9062 * @returns {Object} Returns the new object. 9063 * @example 9064 * 9065 * _.fromPairs([['a', 1], ['b', 2]]); 9066 * // => { 'a': 1, 'b': 2 } 9067 */ 9068 function fromPairs(pairs) { 9069 var index = -1, 9070 length = pairs == null ? 0 : pairs.length, 9071 result = {}; 9072 9073 while (++index < length) { 9074 var pair = pairs[index]; 9075 result[pair[0]] = pair[1]; 9076 } 9077 return result; 9078 } 9079 9080 /** 9081 * Gets the first element of `array`. 9082 * 9083 * @static 9084 * @memberOf _ 9085 * @since 0.1.0 9086 * @alias first 9087 * @category Array 9088 * @param {Array} array The array to query. 9089 * @returns {*} Returns the first element of `array`. 9090 * @example 9091 * 9092 * _.head([1, 2, 3]); 9093 * // => 1 9094 * 9095 * _.head([]); 9096 * // => undefined 9097 */ 9098 function head(array) { 9099 return (array && array.length) ? array[0] : undefined; 9100 } 9101 9102 /** 9103 * Gets the index at which the first occurrence of `value` is found in `array` 9104 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) 9105 * for equality comparisons. If `fromIndex` is negative, it's used as the 9106 * offset from the end of `array`. 9107 * 9108 * @static 9109 * @memberOf _ 9110 * @since 0.1.0 9111 * @category Array 9112 * @param {Array} array The array to inspect. 9113 * @param {*} value The value to search for. 9114 * @param {number} [fromIndex=0] The index to search from. 9115 * @returns {number} Returns the index of the matched value, else `-1`. 9116 * @example 9117 * 9118 * _.indexOf([1, 2, 1, 2], 2); 9119 * // => 1 9120 * 9121 * // Search from the `fromIndex`. 9122 * _.indexOf([1, 2, 1, 2], 2, 2); 9123 * // => 3 9124 */ 9125 function indexOf(array, value, fromIndex) { 9126 var length = array == null ? 0 : array.length; 9127 if (!length) { 9128 return -1; 9129 } 9130 var index = fromIndex == null ? 0 : toInteger(fromIndex); 9131 if (index < 0) { 9132 index = nativeMax(length + index, 0); 9133 } 9134 return baseIndexOf(array, value, index); 9135 } 9136 9137 /** 9138 * Gets all but the last element of `array`. 9139 * 9140 * @static 9141 * @memberOf _ 9142 * @since 0.1.0 9143 * @category Array 9144 * @param {Array} array The array to query. 9145 * @returns {Array} Returns the slice of `array`. 9146 * @example 9147 * 9148 * _.initial([1, 2, 3]); 9149 * // => [1, 2] 9150 */ 9151 function initial(array) { 9152 var length = array == null ? 0 : array.length; 9153 return length ? baseSlice(array, 0, -1) : []; 9154 } 9155 9156 /** 9157 * Creates an array of unique values that are included in all given arrays 9158 * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) 9159 * for equality comparisons. The order and references of result values are 9160 * determined by the first array. 9161 * 9162 * @static 9163 * @memberOf _ 9164 * @since 0.1.0 9165 * @category Array 9166 * @param {...Array} [arrays] The arrays to inspect. 9167 * @returns {Array} Returns the new array of intersecting values. 9168 * @example 9169 * 9170 * _.intersection([2, 1], [2, 3]); 9171 * // => [2] 9172 */ 9173 var intersection = baseRest(function(arrays) { 9174 var mapped = arrayMap(arrays, castArrayLikeObject); 9175 return (mapped.length && mapped[0] === arrays[0]) 9176 ? baseIntersection(mapped) 9177 : []; 9178 }); 9179 9180 /** 9181 * This method is like `_.intersection` except that it accepts `iteratee` 9182 * which is invoked for each element of each `arrays` to generate the criterion 9183 * by which they're compared. The order and references of result values are 9184 * determined by the first array. The iteratee is invoked with one argument: 9185 * (value). 9186 * 9187 * @static 9188 * @memberOf _ 9189 * @since 4.0.0 9190 * @category Array 9191 * @param {...Array} [arrays] The arrays to inspect. 9192 * @param {Function} [iteratee=_.identity] The iteratee invoked per element. 9193 * @returns {Array} Returns the new array of intersecting values. 9194 * @example 9195 * 9196 * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); 9197 * // => [2.1] 9198 * 9199 * // The `_.property` iteratee shorthand. 9200 * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); 9201 * // => [{ 'x': 1 }] 9202 */ 9203 var intersectionBy = baseRest(function(arrays) { 9204 var iteratee = last(arrays), 9205 mapped = arrayMap(arrays, castArrayLikeObject); 9206 9207 if (iteratee === last(mapped)) { 9208 iteratee = undefined; 9209 } else { 9210 mapped.pop(); 9211 } 9212 return (mapped.length && mapped[0] === arrays[0]) 9213 ? baseIntersection(mapped, getIteratee(iteratee, 2)) 9214 : []; 9215 }); 9216 9217 /** 9218 * This method is like `_.intersection` except that it accepts `comparator` 9219 * which is invoked to compare elements of `arrays`. The order and references 9220 * of result values are determined by the first array. The comparator is 9221 * invoked with two arguments: (arrVal, othVal). 9222 * 9223 * @static 9224 * @memberOf _ 9225 * @since 4.0.0 9226 * @category Array 9227 * @param {...Array} [arrays] The arrays to inspect. 9228 * @param {Function} [comparator] The comparator invoked per element. 9229 * @returns {Array} Returns the new array of intersecting values. 9230 * @example 9231 * 9232 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; 9233 * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; 9234 * 9235 * _.intersectionWith(objects, others, _.isEqual); 9236 * // => [{ 'x': 1, 'y': 2 }] 9237 */ 9238 var intersectionWith = baseRest(function(arrays) { 9239 var comparator = last(arrays), 9240 mapped = arrayMap(arrays, castArrayLikeObject); 9241 9242 comparator = typeof comparator == 'function' ? comparator : undefined; 9243 if (comparator) { 9244 mapped.pop(); 9245 } 9246 return (mapped.length && mapped[0] === arrays[0]) 9247 ? baseIntersection(mapped, undefined, comparator) 9248 : []; 9249 }); 9250 9251 /** 9252 * Converts all elements in `array` into a string separated by `separator`. 9253 * 9254 * @static 9255 * @memberOf _ 9256 * @since 4.0.0 9257 * @category Array 9258 * @param {Array} array The array to convert. 9259 * @param {string} [separator=','] The element separator. 9260 * @returns {string} Returns the joined string. 9261 * @example 9262 * 9263 * _.join(['a', 'b', 'c'], '~'); 9264 * // => 'a~b~c' 9265 */ 9266 function join(array, separator) { 9267 return array == null ? '' : nativeJoin.call(array, separator); 9268 } 9269 9270 /** 9271 * Gets the last element of `array`. 9272 * 9273 * @static 9274 * @memberOf _ 9275 * @since 0.1.0 9276 * @category Array 9277 * @param {Array} array The array to query. 9278 * @returns {*} Returns the last element of `array`. 9279 * @example 9280 * 9281 * _.last([1, 2, 3]); 9282 * // => 3 9283 */ 9284 function last(array) { 9285 var length = array == null ? 0 : array.length; 9286 return length ? array[length - 1] : undefined; 9287 } 9288 9289 /** 9290 * This method is like `_.indexOf` except that it iterates over elements of 9291 * `array` from right to left. 9292 * 9293 * @static 9294 * @memberOf _ 9295 * @since 0.1.0 9296 * @category Array 9297 * @param {Array} array The array to inspect. 9298 * @param {*} value The value to search for. 9299 * @param {number} [fromIndex=array.length-1] The index to search from. 9300 * @returns {number} Returns the index of the matched value, else `-1`. 9301 * @example 9302 * 9303 * _.lastIndexOf([1, 2, 1, 2], 2); 9304 * // => 3 9305 * 9306 * // Search from the `fromIndex`. 9307 * _.lastIndexOf([1, 2, 1, 2], 2, 2); 9308 * // => 1 9309 */ 9310 function lastIndexOf(array, value, fromIndex) { 9311 var length = array == null ? 0 : array.length; 9312 if (!length) { 9313 return -1; 9314 } 9315 var index = length; 9316 if (fromIndex !== undefined) { 9317 index = toInteger(fromIndex); 9318 index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1); 9319 } 9320 return value === value 9321 ? strictLastIndexOf(array, value, index) 9322 : baseFindIndex(array, baseIsNaN, index, true); 9323 } 9324 9325 /** 9326 * Gets the element at index `n` of `array`. If `n` is negative, the nth 9327 * element from the end is returned. 9328 * 9329 * @static 9330 * @memberOf _ 9331 * @since 4.11.0 9332 * @category Array 9333 * @param {Array} array The array to query. 9334 * @param {number} [n=0] The index of the element to return. 9335 * @returns {*} Returns the nth element of `array`. 9336 * @example 9337 * 9338 * var array = ['a', 'b', 'c', 'd']; 9339 * 9340 * _.nth(array, 1); 9341 * // => 'b' 9342 * 9343 * _.nth(array, -2); 9344 * // => 'c'; 9345 */ 9346 function nth(array, n) { 9347 return (array && array.length) ? baseNth(array, toInteger(n)) : undefined; 9348 } 9349 9350 /** 9351 * Removes all given values from `array` using 9352 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) 9353 * for equality comparisons. 9354 * 9355 * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove` 9356 * to remove elements from an array by predicate. 9357 * 9358 * @static 9359 * @memberOf _ 9360 * @since 2.0.0 9361 * @category Array 9362 * @param {Array} array The array to modify. 9363 * @param {...*} [values] The values to remove. 9364 * @returns {Array} Returns `array`. 9365 * @example 9366 * 9367 * var array = ['a', 'b', 'c', 'a', 'b', 'c']; 9368 * 9369 * _.pull(array, 'a', 'c'); 9370 * console.log(array); 9371 * // => ['b', 'b'] 9372 */ 9373 var pull = baseRest(pullAll); 9374 9375 /** 9376 * This method is like `_.pull` except that it accepts an array of values to remove. 9377 * 9378 * **Note:** Unlike `_.difference`, this method mutates `array`. 9379 * 9380 * @static 9381 * @memberOf _ 9382 * @since 4.0.0 9383 * @category Array 9384 * @param {Array} array The array to modify. 9385 * @param {Array} values The values to remove. 9386 * @returns {Array} Returns `array`. 9387 * @example 9388 * 9389 * var array = ['a', 'b', 'c', 'a', 'b', 'c']; 9390 * 9391 * _.pullAll(array, ['a', 'c']); 9392 * console.log(array); 9393 * // => ['b', 'b'] 9394 */ 9395 function pullAll(array, values) { 9396 return (array && array.length && values && values.length) 9397 ? basePullAll(array, values) 9398 : array; 9399 } 9400 9401 /** 9402 * This method is like `_.pullAll` except that it accepts `iteratee` which is 9403 * invoked for each element of `array` and `values` to generate the criterion 9404 * by which they're compared. The iteratee is invoked with one argument: (value). 9405 * 9406 * **Note:** Unlike `_.differenceBy`, this method mutates `array`. 9407 * 9408 * @static 9409 * @memberOf _ 9410 * @since 4.0.0 9411 * @category Array 9412 * @param {Array} array The array to modify. 9413 * @param {Array} values The values to remove. 9414 * @param {Function} [iteratee=_.identity] The iteratee invoked per element. 9415 * @returns {Array} Returns `array`. 9416 * @example 9417 * 9418 * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }]; 9419 * 9420 * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x'); 9421 * console.log(array); 9422 * // => [{ 'x': 2 }] 9423 */ 9424 function pullAllBy(array, values, iteratee) { 9425 return (array && array.length && values && values.length) 9426 ? basePullAll(array, values, getIteratee(iteratee, 2)) 9427 : array; 9428 } 9429 9430 /** 9431 * This method is like `_.pullAll` except that it accepts `comparator` which 9432 * is invoked to compare elements of `array` to `values`. The comparator is 9433 * invoked with two arguments: (arrVal, othVal). 9434 * 9435 * **Note:** Unlike `_.differenceWith`, this method mutates `array`. 9436 * 9437 * @static 9438 * @memberOf _ 9439 * @since 4.6.0 9440 * @category Array 9441 * @param {Array} array The array to modify. 9442 * @param {Array} values The values to remove. 9443 * @param {Function} [comparator] The comparator invoked per element. 9444 * @returns {Array} Returns `array`. 9445 * @example 9446 * 9447 * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }]; 9448 * 9449 * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual); 9450 * console.log(array); 9451 * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }] 9452 */ 9453 function pullAllWith(array, values, comparator) { 9454 return (array && array.length && values && values.length) 9455 ? basePullAll(array, values, undefined, comparator) 9456 : array; 9457 } 9458 9459 /** 9460 * Removes elements from `array` corresponding to `indexes` and returns an 9461 * array of removed elements. 9462 * 9463 * **Note:** Unlike `_.at`, this method mutates `array`. 9464 * 9465 * @static 9466 * @memberOf _ 9467 * @since 3.0.0 9468 * @category Array 9469 * @param {Array} array The array to modify. 9470 * @param {...(number|number[])} [indexes] The indexes of elements to remove. 9471 * @returns {Array} Returns the new array of removed elements. 9472 * @example 9473 * 9474 * var array = ['a', 'b', 'c', 'd']; 9475 * var pulled = _.pullAt(array, [1, 3]); 9476 * 9477 * console.log(array); 9478 * // => ['a', 'c'] 9479 * 9480 * console.log(pulled); 9481 * // => ['b', 'd'] 9482 */ 9483 var pullAt = flatRest(function(array, indexes) { 9484 var length = array == null ? 0 : array.length, 9485 result = baseAt(array, indexes); 9486 9487 basePullAt(array, arrayMap(indexes, function(index) { 9488 return isIndex(index, length) ? +index : index; 9489 }).sort(compareAscending)); 9490 9491 return result; 9492 }); 9493 9494 /** 9495 * Removes all elements from `array` that `predicate` returns truthy for 9496 * and returns an array of the removed elements. The predicate is invoked 9497 * with three arguments: (value, index, array). 9498 * 9499 * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull` 9500 * to pull elements from an array by value. 9501 * 9502 * @static 9503 * @memberOf _ 9504 * @since 2.0.0 9505 * @category Array 9506 * @param {Array} array The array to modify. 9507 * @param {Function} [predicate=_.identity] The function invoked per iteration. 9508 * @returns {Array} Returns the new array of removed elements. 9509 * @example 9510 * 9511 * var array = [1, 2, 3, 4]; 9512 * var evens = _.remove(array, function(n) { 9513 * return n % 2 == 0; 9514 * }); 9515 * 9516 * console.log(array); 9517 * // => [1, 3] 9518 * 9519 * console.log(evens); 9520 * // => [2, 4] 9521 */ 9522 function remove(array, predicate) { 9523 var result = []; 9524 if (!(array && array.length)) { 9525 return result; 9526 } 9527 var index = -1, 9528 indexes = [], 9529 length = array.length; 9530 9531 predicate = getIteratee(predicate, 3); 9532 while (++index < length) { 9533 var value = array[index]; 9534 if (predicate(value, index, array)) { 9535 result.push(value); 9536 indexes.push(index); 9537 } 9538 } 9539 basePullAt(array, indexes); 9540 return result; 9541 } 9542 9543 /** 9544 * Reverses `array` so that the first element becomes the last, the second 9545 * element becomes the second to last, and so on. 9546 * 9547 * **Note:** This method mutates `array` and is based on 9548 * [`Array#reverse`](https://mdn.io/Array/reverse). 9549 * 9550 * @static 9551 * @memberOf _ 9552 * @since 4.0.0 9553 * @category Array 9554 * @param {Array} array The array to modify. 9555 * @returns {Array} Returns `array`. 9556 * @example 9557 * 9558 * var array = [1, 2, 3]; 9559 * 9560 * _.reverse(array); 9561 * // => [3, 2, 1] 9562 * 9563 * console.log(array); 9564 * // => [3, 2, 1] 9565 */ 9566 function reverse(array) { 9567 return array == null ? array : nativeReverse.call(array); 9568 } 9569 9570 /** 9571 * Creates a slice of `array` from `start` up to, but not including, `end`. 9572 * 9573 * **Note:** This method is used instead of 9574 * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are 9575 * returned. 9576 * 9577 * @static 9578 * @memberOf _ 9579 * @since 3.0.0 9580 * @category Array 9581 * @param {Array} array The array to slice. 9582 * @param {number} [start=0] The start position. 9583 * @param {number} [end=array.length] The end position. 9584 * @returns {Array} Returns the slice of `array`. 9585 */ 9586 function slice(array, start, end) { 9587 var length = array == null ? 0 : array.length; 9588 if (!length) { 9589 return []; 9590 } 9591 if (end && typeof end != 'number' && isIterateeCall(array, start, end)) { 9592 start = 0; 9593 end = length; 9594 } 9595 else { 9596 start = start == null ? 0 : toInteger(start); 9597 end = end === undefined ? length : toInteger(end); 9598 } 9599 return baseSlice(array, start, end); 9600 } 9601 9602 /** 9603 * Uses a binary search to determine the lowest index at which `value` 9604 * should be inserted into `array` in order to maintain its sort order. 9605 * 9606 * @static 9607 * @memberOf _ 9608 * @since 0.1.0 9609 * @category Array 9610 * @param {Array} array The sorted array to inspect. 9611 * @param {*} value The value to evaluate. 9612 * @returns {number} Returns the index at which `value` should be inserted 9613 * into `array`. 9614 * @example 9615 * 9616 * _.sortedIndex([30, 50], 40); 9617 * // => 1 9618 */ 9619 function sortedIndex(array, value) { 9620 return baseSortedIndex(array, value); 9621 } 9622 9623 /** 9624 * This method is like `_.sortedIndex` except that it accepts `iteratee` 9625 * which is invoked for `value` and each element of `array` to compute their 9626 * sort ranking. The iteratee is invoked with one argument: (value). 9627 * 9628 * @static 9629 * @memberOf _ 9630 * @since 4.0.0 9631 * @category Array 9632 * @param {Array} array The sorted array to inspect. 9633 * @param {*} value The value to evaluate. 9634 * @param {Function} [iteratee=_.identity] The iteratee invoked per element. 9635 * @returns {number} Returns the index at which `value` should be inserted 9636 * into `array`. 9637 * @example 9638 * 9639 * var objects = [{ 'x': 4 }, { 'x': 5 }]; 9640 * 9641 * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); 9642 * // => 0 9643 * 9644 * // The `_.property` iteratee shorthand. 9645 * _.sortedIndexBy(objects, { 'x': 4 }, 'x'); 9646 * // => 0 9647 */ 9648 function sortedIndexBy(array, value, iteratee) { 9649 return baseSortedIndexBy(array, value, getIteratee(iteratee, 2)); 9650 } 9651 9652 /** 9653 * This method is like `_.indexOf` except that it performs a binary 9654 * search on a sorted `array`. 9655 * 9656 * @static 9657 * @memberOf _ 9658 * @since 4.0.0 9659 * @category Array 9660 * @param {Array} array The array to inspect. 9661 * @param {*} value The value to search for. 9662 * @returns {number} Returns the index of the matched value, else `-1`. 9663 * @example 9664 * 9665 * _.sortedIndexOf([4, 5, 5, 5, 6], 5); 9666 * // => 1 9667 */ 9668 function sortedIndexOf(array, value) { 9669 var length = array == null ? 0 : array.length; 9670 if (length) { 9671 var index = baseSortedIndex(array, value); 9672 if (index < length && eq(array[index], value)) { 9673 return index; 9674 } 9675 } 9676 return -1; 9677 } 9678 9679 /** 9680 * This method is like `_.sortedIndex` except that it returns the highest 9681 * index at which `value` should be inserted into `array` in order to 9682 * maintain its sort order. 9683 * 9684 * @static 9685 * @memberOf _ 9686 * @since 3.0.0 9687 * @category Array 9688 * @param {Array} array The sorted array to inspect. 9689 * @param {*} value The value to evaluate. 9690 * @returns {number} Returns the index at which `value` should be inserted 9691 * into `array`. 9692 * @example 9693 * 9694 * _.sortedLastIndex([4, 5, 5, 5, 6], 5); 9695 * // => 4 9696 */ 9697 function sortedLastIndex(array, value) { 9698 return baseSortedIndex(array, value, true); 9699 } 9700 9701 /** 9702 * This method is like `_.sortedLastIndex` except that it accepts `iteratee` 9703 * which is invoked for `value` and each element of `array` to compute their 9704 * sort ranking. The iteratee is invoked with one argument: (value). 9705 * 9706 * @static 9707 * @memberOf _ 9708 * @since 4.0.0 9709 * @category Array 9710 * @param {Array} array The sorted array to inspect. 9711 * @param {*} value The value to evaluate. 9712 * @param {Function} [iteratee=_.identity] The iteratee invoked per element. 9713 * @returns {number} Returns the index at which `value` should be inserted 9714 * into `array`. 9715 * @example 9716 * 9717 * var objects = [{ 'x': 4 }, { 'x': 5 }]; 9718 * 9719 * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); 9720 * // => 1 9721 * 9722 * // The `_.property` iteratee shorthand. 9723 * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x'); 9724 * // => 1 9725 */ 9726 function sortedLastIndexBy(array, value, iteratee) { 9727 return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true); 9728 } 9729 9730 /** 9731 * This method is like `_.lastIndexOf` except that it performs a binary 9732 * search on a sorted `array`. 9733 * 9734 * @static 9735 * @memberOf _ 9736 * @since 4.0.0 9737 * @category Array 9738 * @param {Array} array The array to inspect. 9739 * @param {*} value The value to search for. 9740 * @returns {number} Returns the index of the matched value, else `-1`. 9741 * @example 9742 * 9743 * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5); 9744 * // => 3 9745 */ 9746 function sortedLastIndexOf(array, value) { 9747 var length = array == null ? 0 : array.length; 9748 if (length) { 9749 var index = baseSortedIndex(array, value, true) - 1; 9750 if (eq(array[index], value)) { 9751 return index; 9752 } 9753 } 9754 return -1; 9755 } 9756 9757 /** 9758 * This method is like `_.uniq` except that it's designed and optimized 9759 * for sorted arrays. 9760 * 9761 * @static 9762 * @memberOf _ 9763 * @since 4.0.0 9764 * @category Array 9765 * @param {Array} array The array to inspect. 9766 * @returns {Array} Returns the new duplicate free array. 9767 * @example 9768 * 9769 * _.sortedUniq([1, 1, 2]); 9770 * // => [1, 2] 9771 */ 9772 function sortedUniq(array) { 9773 return (array && array.length) 9774 ? baseSortedUniq(array) 9775 : []; 9776 } 9777 9778 /** 9779 * This method is like `_.uniqBy` except that it's designed and optimized 9780 * for sorted arrays. 9781 * 9782 * @static 9783 * @memberOf _ 9784 * @since 4.0.0 9785 * @category Array 9786 * @param {Array} array The array to inspect. 9787 * @param {Function} [iteratee] The iteratee invoked per element. 9788 * @returns {Array} Returns the new duplicate free array. 9789 * @example 9790 * 9791 * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor); 9792 * // => [1.1, 2.3] 9793 */ 9794 function sortedUniqBy(array, iteratee) { 9795 return (array && array.length) 9796 ? baseSortedUniq(array, getIteratee(iteratee, 2)) 9797 : []; 9798 } 9799 9800 /** 9801 * Gets all but the first element of `array`. 9802 * 9803 * @static 9804 * @memberOf _ 9805 * @since 4.0.0 9806 * @category Array 9807 * @param {Array} array The array to query. 9808 * @returns {Array} Returns the slice of `array`. 9809 * @example 9810 * 9811 * _.tail([1, 2, 3]); 9812 * // => [2, 3] 9813 */ 9814 function tail(array) { 9815 var length = array == null ? 0 : array.length; 9816 return length ? baseSlice(array, 1, length) : []; 9817 } 9818 9819 /** 9820 * Creates a slice of `array` with `n` elements taken from the beginning. 9821 * 9822 * @static 9823 * @memberOf _ 9824 * @since 0.1.0 9825 * @category Array 9826 * @param {Array} array The array to query. 9827 * @param {number} [n=1] The number of elements to take. 9828 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 9829 * @returns {Array} Returns the slice of `array`. 9830 * @example 9831 * 9832 * _.take([1, 2, 3]); 9833 * // => [1] 9834 * 9835 * _.take([1, 2, 3], 2); 9836 * // => [1, 2] 9837 * 9838 * _.take([1, 2, 3], 5); 9839 * // => [1, 2, 3] 9840 * 9841 * _.take([1, 2, 3], 0); 9842 * // => [] 9843 */ 9844 function take(array, n, guard) { 9845 if (!(array && array.length)) { 9846 return []; 9847 } 9848 n = (guard || n === undefined) ? 1 : toInteger(n); 9849 return baseSlice(array, 0, n < 0 ? 0 : n); 9850 } 9851 9852 /** 9853 * Creates a slice of `array` with `n` elements taken from the end. 9854 * 9855 * @static 9856 * @memberOf _ 9857 * @since 3.0.0 9858 * @category Array 9859 * @param {Array} array The array to query. 9860 * @param {number} [n=1] The number of elements to take. 9861 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 9862 * @returns {Array} Returns the slice of `array`. 9863 * @example 9864 * 9865 * _.takeRight([1, 2, 3]); 9866 * // => [3] 9867 * 9868 * _.takeRight([1, 2, 3], 2); 9869 * // => [2, 3] 9870 * 9871 * _.takeRight([1, 2, 3], 5); 9872 * // => [1, 2, 3] 9873 * 9874 * _.takeRight([1, 2, 3], 0); 9875 * // => [] 9876 */ 9877 function takeRight(array, n, guard) { 9878 var length = array == null ? 0 : array.length; 9879 if (!length) { 9880 return []; 9881 } 9882 n = (guard || n === undefined) ? 1 : toInteger(n); 9883 n = length - n; 9884 return baseSlice(array, n < 0 ? 0 : n, length); 9885 } 9886 9887 /** 9888 * Creates a slice of `array` with elements taken from the end. Elements are 9889 * taken until `predicate` returns falsey. The predicate is invoked with 9890 * three arguments: (value, index, array). 9891 * 9892 * @static 9893 * @memberOf _ 9894 * @since 3.0.0 9895 * @category Array 9896 * @param {Array} array The array to query. 9897 * @param {Function} [predicate=_.identity] The function invoked per iteration. 9898 * @returns {Array} Returns the slice of `array`. 9899 * @example 9900 * 9901 * var users = [ 9902 * { 'user': 'barney', 'active': true }, 9903 * { 'user': 'fred', 'active': false }, 9904 * { 'user': 'pebbles', 'active': false } 9905 * ]; 9906 * 9907 * _.takeRightWhile(users, function(o) { return !o.active; }); 9908 * // => objects for ['fred', 'pebbles'] 9909 * 9910 * // The `_.matches` iteratee shorthand. 9911 * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false }); 9912 * // => objects for ['pebbles'] 9913 * 9914 * // The `_.matchesProperty` iteratee shorthand. 9915 * _.takeRightWhile(users, ['active', false]); 9916 * // => objects for ['fred', 'pebbles'] 9917 * 9918 * // The `_.property` iteratee shorthand. 9919 * _.takeRightWhile(users, 'active'); 9920 * // => [] 9921 */ 9922 function takeRightWhile(array, predicate) { 9923 return (array && array.length) 9924 ? baseWhile(array, getIteratee(predicate, 3), false, true) 9925 : []; 9926 } 9927 9928 /** 9929 * Creates a slice of `array` with elements taken from the beginning. Elements 9930 * are taken until `predicate` returns falsey. The predicate is invoked with 9931 * three arguments: (value, index, array). 9932 * 9933 * @static 9934 * @memberOf _ 9935 * @since 3.0.0 9936 * @category Array 9937 * @param {Array} array The array to query. 9938 * @param {Function} [predicate=_.identity] The function invoked per iteration. 9939 * @returns {Array} Returns the slice of `array`. 9940 * @example 9941 * 9942 * var users = [ 9943 * { 'user': 'barney', 'active': false }, 9944 * { 'user': 'fred', 'active': false }, 9945 * { 'user': 'pebbles', 'active': true } 9946 * ]; 9947 * 9948 * _.takeWhile(users, function(o) { return !o.active; }); 9949 * // => objects for ['barney', 'fred'] 9950 * 9951 * // The `_.matches` iteratee shorthand. 9952 * _.takeWhile(users, { 'user': 'barney', 'active': false }); 9953 * // => objects for ['barney'] 9954 * 9955 * // The `_.matchesProperty` iteratee shorthand. 9956 * _.takeWhile(users, ['active', false]); 9957 * // => objects for ['barney', 'fred'] 9958 * 9959 * // The `_.property` iteratee shorthand. 9960 * _.takeWhile(users, 'active'); 9961 * // => [] 9962 */ 9963 function takeWhile(array, predicate) { 9964 return (array && array.length) 9965 ? baseWhile(array, getIteratee(predicate, 3)) 9966 : []; 9967 } 9968 9969 /** 9970 * Creates an array of unique values, in order, from all given arrays using 9971 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) 9972 * for equality comparisons. 9973 * 9974 * @static 9975 * @memberOf _ 9976 * @since 0.1.0 9977 * @category Array 9978 * @param {...Array} [arrays] The arrays to inspect. 9979 * @returns {Array} Returns the new array of combined values. 9980 * @example 9981 * 9982 * _.union([2], [1, 2]); 9983 * // => [2, 1] 9984 */ 9985 var union = baseRest(function(arrays) { 9986 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true)); 9987 }); 9988 9989 /** 9990 * This method is like `_.union` except that it accepts `iteratee` which is 9991 * invoked for each element of each `arrays` to generate the criterion by 9992 * which uniqueness is computed. Result values are chosen from the first 9993 * array in which the value occurs. The iteratee is invoked with one argument: 9994 * (value). 9995 * 9996 * @static 9997 * @memberOf _ 9998 * @since 4.0.0 9999 * @category Array 10000 * @param {...Array} [arrays] The arrays to inspect. 10001 * @param {Function} [iteratee=_.identity] The iteratee invoked per element. 10002 * @returns {Array} Returns the new array of combined values. 10003 * @example 10004 * 10005 * _.unionBy([2.1], [1.2, 2.3], Math.floor); 10006 * // => [2.1, 1.2] 10007 * 10008 * // The `_.property` iteratee shorthand. 10009 * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); 10010 * // => [{ 'x': 1 }, { 'x': 2 }] 10011 */ 10012 var unionBy = baseRest(function(arrays) { 10013 var iteratee = last(arrays); 10014 if (isArrayLikeObject(iteratee)) { 10015 iteratee = undefined; 10016 } 10017 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)); 10018 }); 10019 10020 /** 10021 * This method is like `_.union` except that it accepts `comparator` which 10022 * is invoked to compare elements of `arrays`. Result values are chosen from 10023 * the first array in which the value occurs. The comparator is invoked 10024 * with two arguments: (arrVal, othVal). 10025 * 10026 * @static 10027 * @memberOf _ 10028 * @since 4.0.0 10029 * @category Array 10030 * @param {...Array} [arrays] The arrays to inspect. 10031 * @param {Function} [comparator] The comparator invoked per element. 10032 * @returns {Array} Returns the new array of combined values. 10033 * @example 10034 * 10035 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; 10036 * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; 10037 * 10038 * _.unionWith(objects, others, _.isEqual); 10039 * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] 10040 */ 10041 var unionWith = baseRest(function(arrays) { 10042 var comparator = last(arrays); 10043 comparator = typeof comparator == 'function' ? comparator : undefined; 10044 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator); 10045 }); 10046 10047 /** 10048 * Creates a duplicate-free version of an array, using 10049 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) 10050 * for equality comparisons, in which only the first occurrence of each element 10051 * is kept. The order of result values is determined by the order they occur 10052 * in the array. 10053 * 10054 * @static 10055 * @memberOf _ 10056 * @since 0.1.0 10057 * @category Array 10058 * @param {Array} array The array to inspect. 10059 * @returns {Array} Returns the new duplicate free array. 10060 * @example 10061 * 10062 * _.uniq([2, 1, 2]); 10063 * // => [2, 1] 10064 */ 10065 function uniq(array) { 10066 return (array && array.length) ? baseUniq(array) : []; 10067 } 10068 10069 /** 10070 * This method is like `_.uniq` except that it accepts `iteratee` which is 10071 * invoked for each element in `array` to generate the criterion by which 10072 * uniqueness is computed. The order of result values is determined by the 10073 * order they occur in the array. The iteratee is invoked with one argument: 10074 * (value). 10075 * 10076 * @static 10077 * @memberOf _ 10078 * @since 4.0.0 10079 * @category Array 10080 * @param {Array} array The array to inspect. 10081 * @param {Function} [iteratee=_.identity] The iteratee invoked per element. 10082 * @returns {Array} Returns the new duplicate free array. 10083 * @example 10084 * 10085 * _.uniqBy([2.1, 1.2, 2.3], Math.floor); 10086 * // => [2.1, 1.2] 10087 * 10088 * // The `_.property` iteratee shorthand. 10089 * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); 10090 * // => [{ 'x': 1 }, { 'x': 2 }] 10091 */ 10092 function uniqBy(array, iteratee) { 10093 return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : []; 10094 } 10095 10096 /** 10097 * This method is like `_.uniq` except that it accepts `comparator` which 10098 * is invoked to compare elements of `array`. The order of result values is 10099 * determined by the order they occur in the array.The comparator is invoked 10100 * with two arguments: (arrVal, othVal). 10101 * 10102 * @static 10103 * @memberOf _ 10104 * @since 4.0.0 10105 * @category Array 10106 * @param {Array} array The array to inspect. 10107 * @param {Function} [comparator] The comparator invoked per element. 10108 * @returns {Array} Returns the new duplicate free array. 10109 * @example 10110 * 10111 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }]; 10112 * 10113 * _.uniqWith(objects, _.isEqual); 10114 * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }] 10115 */ 10116 function uniqWith(array, comparator) { 10117 comparator = typeof comparator == 'function' ? comparator : undefined; 10118 return (array && array.length) ? baseUniq(array, undefined, comparator) : []; 10119 } 10120 10121 /** 10122 * This method is like `_.zip` except that it accepts an array of grouped 10123 * elements and creates an array regrouping the elements to their pre-zip 10124 * configuration. 10125 * 10126 * @static 10127 * @memberOf _ 10128 * @since 1.2.0 10129 * @category Array 10130 * @param {Array} array The array of grouped elements to process. 10131 * @returns {Array} Returns the new array of regrouped elements. 10132 * @example 10133 * 10134 * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]); 10135 * // => [['a', 1, true], ['b', 2, false]] 10136 * 10137 * _.unzip(zipped); 10138 * // => [['a', 'b'], [1, 2], [true, false]] 10139 */ 10140 function unzip(array) { 10141 if (!(array && array.length)) { 10142 return []; 10143 } 10144 var length = 0; 10145 array = arrayFilter(array, function(group) { 10146 if (isArrayLikeObject(group)) { 10147 length = nativeMax(group.length, length); 10148 return true; 10149 } 10150 }); 10151 return baseTimes(length, function(index) { 10152 return arrayMap(array, baseProperty(index)); 10153 }); 10154 } 10155 10156 /** 10157 * This method is like `_.unzip` except that it accepts `iteratee` to specify 10158 * how regrouped values should be combined. The iteratee is invoked with the 10159 * elements of each group: (...group). 10160 * 10161 * @static 10162 * @memberOf _ 10163 * @since 3.8.0 10164 * @category Array 10165 * @param {Array} array The array of grouped elements to process. 10166 * @param {Function} [iteratee=_.identity] The function to combine 10167 * regrouped values. 10168 * @returns {Array} Returns the new array of regrouped elements. 10169 * @example 10170 * 10171 * var zipped = _.zip([1, 2], [10, 20], [100, 200]); 10172 * // => [[1, 10, 100], [2, 20, 200]] 10173 * 10174 * _.unzipWith(zipped, _.add); 10175 * // => [3, 30, 300] 10176 */ 10177 function unzipWith(array, iteratee) { 10178 if (!(array && array.length)) { 10179 return []; 10180 } 10181 var result = unzip(array); 10182 if (iteratee == null) { 10183 return result; 10184 } 10185 return arrayMap(result, function(group) { 10186 return apply(iteratee, undefined, group); 10187 }); 10188 } 10189 10190 /** 10191 * Creates an array excluding all given values using 10192 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) 10193 * for equality comparisons. 10194 * 10195 * **Note:** Unlike `_.pull`, this method returns a new array. 10196 * 10197 * @static 10198 * @memberOf _ 10199 * @since 0.1.0 10200 * @category Array 10201 * @param {Array} array The array to inspect. 10202 * @param {...*} [values] The values to exclude. 10203 * @returns {Array} Returns the new array of filtered values. 10204 * @see _.difference, _.xor 10205 * @example 10206 * 10207 * _.without([2, 1, 2, 3], 1, 2); 10208 * // => [3] 10209 */ 10210 var without = baseRest(function(array, values) { 10211 return isArrayLikeObject(array) 10212 ? baseDifference(array, values) 10213 : []; 10214 }); 10215 10216 /** 10217 * Creates an array of unique values that is the 10218 * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) 10219 * of the given arrays. The order of result values is determined by the order 10220 * they occur in the arrays. 10221 * 10222 * @static 10223 * @memberOf _ 10224 * @since 2.4.0 10225 * @category Array 10226 * @param {...Array} [arrays] The arrays to inspect. 10227 * @returns {Array} Returns the new array of filtered values. 10228 * @see _.difference, _.without 10229 * @example 10230 * 10231 * _.xor([2, 1], [2, 3]); 10232 * // => [1, 3] 10233 */ 10234 var xor = baseRest(function(arrays) { 10235 return baseXor(arrayFilter(arrays, isArrayLikeObject)); 10236 }); 10237 10238 /** 10239 * This method is like `_.xor` except that it accepts `iteratee` which is 10240 * invoked for each element of each `arrays` to generate the criterion by 10241 * which by which they're compared. The order of result values is determined 10242 * by the order they occur in the arrays. The iteratee is invoked with one 10243 * argument: (value). 10244 * 10245 * @static 10246 * @memberOf _ 10247 * @since 4.0.0 10248 * @category Array 10249 * @param {...Array} [arrays] The arrays to inspect. 10250 * @param {Function} [iteratee=_.identity] The iteratee invoked per element. 10251 * @returns {Array} Returns the new array of filtered values. 10252 * @example 10253 * 10254 * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor); 10255 * // => [1.2, 3.4] 10256 * 10257 * // The `_.property` iteratee shorthand. 10258 * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); 10259 * // => [{ 'x': 2 }] 10260 */ 10261 var xorBy = baseRest(function(arrays) { 10262 var iteratee = last(arrays); 10263 if (isArrayLikeObject(iteratee)) { 10264 iteratee = undefined; 10265 } 10266 return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2)); 10267 }); 10268 10269 /** 10270 * This method is like `_.xor` except that it accepts `comparator` which is 10271 * invoked to compare elements of `arrays`. The order of result values is 10272 * determined by the order they occur in the arrays. The comparator is invoked 10273 * with two arguments: (arrVal, othVal). 10274 * 10275 * @static 10276 * @memberOf _ 10277 * @since 4.0.0 10278 * @category Array 10279 * @param {...Array} [arrays] The arrays to inspect. 10280 * @param {Function} [comparator] The comparator invoked per element. 10281 * @returns {Array} Returns the new array of filtered values. 10282 * @example 10283 * 10284 * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; 10285 * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; 10286 * 10287 * _.xorWith(objects, others, _.isEqual); 10288 * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] 10289 */ 10290 var xorWith = baseRest(function(arrays) { 10291 var comparator = last(arrays); 10292 comparator = typeof comparator == 'function' ? comparator : undefined; 10293 return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator); 10294 }); 10295 10296 /** 10297 * Creates an array of grouped elements, the first of which contains the 10298 * first elements of the given arrays, the second of which contains the 10299 * second elements of the given arrays, and so on. 10300 * 10301 * @static 10302 * @memberOf _ 10303 * @since 0.1.0 10304 * @category Array 10305 * @param {...Array} [arrays] The arrays to process. 10306 * @returns {Array} Returns the new array of grouped elements. 10307 * @example 10308 * 10309 * _.zip(['a', 'b'], [1, 2], [true, false]); 10310 * // => [['a', 1, true], ['b', 2, false]] 10311 */ 10312 var zip = baseRest(unzip); 10313 10314 /** 10315 * This method is like `_.fromPairs` except that it accepts two arrays, 10316 * one of property identifiers and one of corresponding values. 10317 * 10318 * @static 10319 * @memberOf _ 10320 * @since 0.4.0 10321 * @category Array 10322 * @param {Array} [props=[]] The property identifiers. 10323 * @param {Array} [values=[]] The property values. 10324 * @returns {Object} Returns the new object. 10325 * @example 10326 * 10327 * _.zipObject(['a', 'b'], [1, 2]); 10328 * // => { 'a': 1, 'b': 2 } 10329 */ 10330 function zipObject(props, values) { 10331 return baseZipObject(props || [], values || [], assignValue); 10332 } 10333 10334 /** 10335 * This method is like `_.zipObject` except that it supports property paths. 10336 * 10337 * @static 10338 * @memberOf _ 10339 * @since 4.1.0 10340 * @category Array 10341 * @param {Array} [props=[]] The property identifiers. 10342 * @param {Array} [values=[]] The property values. 10343 * @returns {Object} Returns the new object. 10344 * @example 10345 * 10346 * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]); 10347 * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } } 10348 */ 10349 function zipObjectDeep(props, values) { 10350 return baseZipObject(props || [], values || [], baseSet); 10351 } 10352 10353 /** 10354 * This method is like `_.zip` except that it accepts `iteratee` to specify 10355 * how grouped values should be combined. The iteratee is invoked with the 10356 * elements of each group: (...group). 10357 * 10358 * @static 10359 * @memberOf _ 10360 * @since 3.8.0 10361 * @category Array 10362 * @param {...Array} [arrays] The arrays to process. 10363 * @param {Function} [iteratee=_.identity] The function to combine 10364 * grouped values. 10365 * @returns {Array} Returns the new array of grouped elements. 10366 * @example 10367 * 10368 * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) { 10369 * return a + b + c; 10370 * }); 10371 * // => [111, 222] 10372 */ 10373 var zipWith = baseRest(function(arrays) { 10374 var length = arrays.length, 10375 iteratee = length > 1 ? arrays[length - 1] : undefined; 10376 10377 iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined; 10378 return unzipWith(arrays, iteratee); 10379 }); 10380 10381 /*------------------------------------------------------------------------*/ 10382 10383 /** 10384 * Creates a `lodash` wrapper instance that wraps `value` with explicit method 10385 * chain sequences enabled. The result of such sequences must be unwrapped 10386 * with `_#value`. 10387 * 10388 * @static 10389 * @memberOf _ 10390 * @since 1.3.0 10391 * @category Seq 10392 * @param {*} value The value to wrap. 10393 * @returns {Object} Returns the new `lodash` wrapper instance. 10394 * @example 10395 * 10396 * var users = [ 10397 * { 'user': 'barney', 'age': 36 }, 10398 * { 'user': 'fred', 'age': 40 }, 10399 * { 'user': 'pebbles', 'age': 1 } 10400 * ]; 10401 * 10402 * var youngest = _ 10403 * .chain(users) 10404 * .sortBy('age') 10405 * .map(function(o) { 10406 * return o.user + ' is ' + o.age; 10407 * }) 10408 * .head() 10409 * .value(); 10410 * // => 'pebbles is 1' 10411 */ 10412 function chain(value) { 10413 var result = lodash(value); 10414 result.__chain__ = true; 10415 return result; 10416 } 10417 10418 /** 10419 * This method invokes `interceptor` and returns `value`. The interceptor 10420 * is invoked with one argument; (value). The purpose of this method is to 10421 * "tap into" a method chain sequence in order to modify intermediate results. 10422 * 10423 * @static 10424 * @memberOf _ 10425 * @since 0.1.0 10426 * @category Seq 10427 * @param {*} value The value to provide to `interceptor`. 10428 * @param {Function} interceptor The function to invoke. 10429 * @returns {*} Returns `value`. 10430 * @example 10431 * 10432 * _([1, 2, 3]) 10433 * .tap(function(array) { 10434 * // Mutate input array. 10435 * array.pop(); 10436 * }) 10437 * .reverse() 10438 * .value(); 10439 * // => [2, 1] 10440 */ 10441 function tap(value, interceptor) { 10442 interceptor(value); 10443 return value; 10444 } 10445 10446 /** 10447 * This method is like `_.tap` except that it returns the result of `interceptor`. 10448 * The purpose of this method is to "pass thru" values replacing intermediate 10449 * results in a method chain sequence. 10450 * 10451 * @static 10452 * @memberOf _ 10453 * @since 3.0.0 10454 * @category Seq 10455 * @param {*} value The value to provide to `interceptor`. 10456 * @param {Function} interceptor The function to invoke. 10457 * @returns {*} Returns the result of `interceptor`. 10458 * @example 10459 * 10460 * _(' abc ') 10461 * .chain() 10462 * .trim() 10463 * .thru(function(value) { 10464 * return [value]; 10465 * }) 10466 * .value(); 10467 * // => ['abc'] 10468 */ 10469 function thru(value, interceptor) { 10470 return interceptor(value); 10471 } 10472 10473 /** 10474 * This method is the wrapper version of `_.at`. 10475 * 10476 * @name at 10477 * @memberOf _ 10478 * @since 1.0.0 10479 * @category Seq 10480 * @param {...(string|string[])} [paths] The property paths to pick. 10481 * @returns {Object} Returns the new `lodash` wrapper instance. 10482 * @example 10483 * 10484 * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; 10485 * 10486 * _(object).at(['a[0].b.c', 'a[1]']).value(); 10487 * // => [3, 4] 10488 */ 10489 var wrapperAt = flatRest(function(paths) { 10490 var length = paths.length, 10491 start = length ? paths[0] : 0, 10492 value = this.__wrapped__, 10493 interceptor = function(object) { return baseAt(object, paths); }; 10494 10495 if (length > 1 || this.__actions__.length || 10496 !(value instanceof LazyWrapper) || !isIndex(start)) { 10497 return this.thru(interceptor); 10498 } 10499 value = value.slice(start, +start + (length ? 1 : 0)); 10500 value.__actions__.push({ 10501 'func': thru, 10502 'args': [interceptor], 10503 'thisArg': undefined 10504 }); 10505 return new LodashWrapper(value, this.__chain__).thru(function(array) { 10506 if (length && !array.length) { 10507 array.push(undefined); 10508 } 10509 return array; 10510 }); 10511 }); 10512 10513 /** 10514 * Creates a `lodash` wrapper instance with explicit method chain sequences enabled. 10515 * 10516 * @name chain 10517 * @memberOf _ 10518 * @since 0.1.0 10519 * @category Seq 10520 * @returns {Object} Returns the new `lodash` wrapper instance. 10521 * @example 10522 * 10523 * var users = [ 10524 * { 'user': 'barney', 'age': 36 }, 10525 * { 'user': 'fred', 'age': 40 } 10526 * ]; 10527 * 10528 * // A sequence without explicit chaining. 10529 * _(users).head(); 10530 * // => { 'user': 'barney', 'age': 36 } 10531 * 10532 * // A sequence with explicit chaining. 10533 * _(users) 10534 * .chain() 10535 * .head() 10536 * .pick('user') 10537 * .value(); 10538 * // => { 'user': 'barney' } 10539 */ 10540 function wrapperChain() { 10541 return chain(this); 10542 } 10543 10544 /** 10545 * Executes the chain sequence and returns the wrapped result. 10546 * 10547 * @name commit 10548 * @memberOf _ 10549 * @since 3.2.0 10550 * @category Seq 10551 * @returns {Object} Returns the new `lodash` wrapper instance. 10552 * @example 10553 * 10554 * var array = [1, 2]; 10555 * var wrapped = _(array).push(3); 10556 * 10557 * console.log(array); 10558 * // => [1, 2] 10559 * 10560 * wrapped = wrapped.commit(); 10561 * console.log(array); 10562 * // => [1, 2, 3] 10563 * 10564 * wrapped.last(); 10565 * // => 3 10566 * 10567 * console.log(array); 10568 * // => [1, 2, 3] 10569 */ 10570 function wrapperCommit() { 10571 return new LodashWrapper(this.value(), this.__chain__); 10572 } 10573 10574 /** 10575 * Gets the next value on a wrapped object following the 10576 * [iterator protocol](https://mdn.io/iteration_protocols#iterator). 10577 * 10578 * @name next 10579 * @memberOf _ 10580 * @since 4.0.0 10581 * @category Seq 10582 * @returns {Object} Returns the next iterator value. 10583 * @example 10584 * 10585 * var wrapped = _([1, 2]); 10586 * 10587 * wrapped.next(); 10588 * // => { 'done': false, 'value': 1 } 10589 * 10590 * wrapped.next(); 10591 * // => { 'done': false, 'value': 2 } 10592 * 10593 * wrapped.next(); 10594 * // => { 'done': true, 'value': undefined } 10595 */ 10596 function wrapperNext() { 10597 if (this.__values__ === undefined) { 10598 this.__values__ = toArray(this.value()); 10599 } 10600 var done = this.__index__ >= this.__values__.length, 10601 value = done ? undefined : this.__values__[this.__index__++]; 10602 10603 return { 'done': done, 'value': value }; 10604 } 10605 10606 /** 10607 * Enables the wrapper to be iterable. 10608 * 10609 * @name Symbol.iterator 10610 * @memberOf _ 10611 * @since 4.0.0 10612 * @category Seq 10613 * @returns {Object} Returns the wrapper object. 10614 * @example 10615 * 10616 * var wrapped = _([1, 2]); 10617 * 10618 * wrapped[Symbol.iterator]() === wrapped; 10619 * // => true 10620 * 10621 * Array.from(wrapped); 10622 * // => [1, 2] 10623 */ 10624 function wrapperToIterator() { 10625 return this; 10626 } 10627 10628 /** 10629 * Creates a clone of the chain sequence planting `value` as the wrapped value. 10630 * 10631 * @name plant 10632 * @memberOf _ 10633 * @since 3.2.0 10634 * @category Seq 10635 * @param {*} value The value to plant. 10636 * @returns {Object} Returns the new `lodash` wrapper instance. 10637 * @example 10638 * 10639 * function square(n) { 10640 * return n * n; 10641 * } 10642 * 10643 * var wrapped = _([1, 2]).map(square); 10644 * var other = wrapped.plant([3, 4]); 10645 * 10646 * other.value(); 10647 * // => [9, 16] 10648 * 10649 * wrapped.value(); 10650 * // => [1, 4] 10651 */ 10652 function wrapperPlant(value) { 10653 var result, 10654 parent = this; 10655 10656 while (parent instanceof baseLodash) { 10657 var clone = wrapperClone(parent); 10658 clone.__index__ = 0; 10659 clone.__values__ = undefined; 10660 if (result) { 10661 previous.__wrapped__ = clone; 10662 } else { 10663 result = clone; 10664 } 10665 var previous = clone; 10666 parent = parent.__wrapped__; 10667 } 10668 previous.__wrapped__ = value; 10669 return result; 10670 } 10671 10672 /** 10673 * This method is the wrapper version of `_.reverse`. 10674 * 10675 * **Note:** This method mutates the wrapped array. 10676 * 10677 * @name reverse 10678 * @memberOf _ 10679 * @since 0.1.0 10680 * @category Seq 10681 * @returns {Object} Returns the new `lodash` wrapper instance. 10682 * @example 10683 * 10684 * var array = [1, 2, 3]; 10685 * 10686 * _(array).reverse().value() 10687 * // => [3, 2, 1] 10688 * 10689 * console.log(array); 10690 * // => [3, 2, 1] 10691 */ 10692 function wrapperReverse() { 10693 var value = this.__wrapped__; 10694 if (value instanceof LazyWrapper) { 10695 var wrapped = value; 10696 if (this.__actions__.length) { 10697 wrapped = new LazyWrapper(this); 10698 } 10699 wrapped = wrapped.reverse(); 10700 wrapped.__actions__.push({ 10701 'func': thru, 10702 'args': [reverse], 10703 'thisArg': undefined 10704 }); 10705 return new LodashWrapper(wrapped, this.__chain__); 10706 } 10707 return this.thru(reverse); 10708 } 10709 10710 /** 10711 * Executes the chain sequence to resolve the unwrapped value. 10712 * 10713 * @name value 10714 * @memberOf _ 10715 * @since 0.1.0 10716 * @alias toJSON, valueOf 10717 * @category Seq 10718 * @returns {*} Returns the resolved unwrapped value. 10719 * @example 10720 * 10721 * _([1, 2, 3]).value(); 10722 * // => [1, 2, 3] 10723 */ 10724 function wrapperValue() { 10725 return baseWrapperValue(this.__wrapped__, this.__actions__); 10726 } 10727 10728 /*------------------------------------------------------------------------*/ 10729 10730 /** 10731 * Creates an object composed of keys generated from the results of running 10732 * each element of `collection` thru `iteratee`. The corresponding value of 10733 * each key is the number of times the key was returned by `iteratee`. The 10734 * iteratee is invoked with one argument: (value). 10735 * 10736 * @static 10737 * @memberOf _ 10738 * @since 0.5.0 10739 * @category Collection 10740 * @param {Array|Object} collection The collection to iterate over. 10741 * @param {Function} [iteratee=_.identity] The iteratee to transform keys. 10742 * @returns {Object} Returns the composed aggregate object. 10743 * @example 10744 * 10745 * _.countBy([6.1, 4.2, 6.3], Math.floor); 10746 * // => { '4': 1, '6': 2 } 10747 * 10748 * // The `_.property` iteratee shorthand. 10749 * _.countBy(['one', 'two', 'three'], 'length'); 10750 * // => { '3': 2, '5': 1 } 10751 */ 10752 var countBy = createAggregator(function(result, value, key) { 10753 if (hasOwnProperty.call(result, key)) { 10754 ++result[key]; 10755 } else { 10756 baseAssignValue(result, key, 1); 10757 } 10758 }); 10759 10760 /** 10761 * Checks if `predicate` returns truthy for **all** elements of `collection`. 10762 * Iteration is stopped once `predicate` returns falsey. The predicate is 10763 * invoked with three arguments: (value, index|key, collection). 10764 * 10765 * **Note:** This method returns `true` for 10766 * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because 10767 * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of 10768 * elements of empty collections. 10769 * 10770 * @static 10771 * @memberOf _ 10772 * @since 0.1.0 10773 * @category Collection 10774 * @param {Array|Object} collection The collection to iterate over. 10775 * @param {Function} [predicate=_.identity] The function invoked per iteration. 10776 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 10777 * @returns {boolean} Returns `true` if all elements pass the predicate check, 10778 * else `false`. 10779 * @example 10780 * 10781 * _.every([true, 1, null, 'yes'], Boolean); 10782 * // => false 10783 * 10784 * var users = [ 10785 * { 'user': 'barney', 'age': 36, 'active': false }, 10786 * { 'user': 'fred', 'age': 40, 'active': false } 10787 * ]; 10788 * 10789 * // The `_.matches` iteratee shorthand. 10790 * _.every(users, { 'user': 'barney', 'active': false }); 10791 * // => false 10792 * 10793 * // The `_.matchesProperty` iteratee shorthand. 10794 * _.every(users, ['active', false]); 10795 * // => true 10796 * 10797 * // The `_.property` iteratee shorthand. 10798 * _.every(users, 'active'); 10799 * // => false 10800 */ 10801 function every(collection, predicate, guard) { 10802 var func = isArray(collection) ? arrayEvery : baseEvery; 10803 if (guard && isIterateeCall(collection, predicate, guard)) { 10804 predicate = undefined; 10805 } 10806 return func(collection, getIteratee(predicate, 3)); 10807 } 10808 10809 /** 10810 * Iterates over elements of `collection`, returning an array of all elements 10811 * `predicate` returns truthy for. The predicate is invoked with three 10812 * arguments: (value, index|key, collection). 10813 * 10814 * **Note:** Unlike `_.remove`, this method returns a new array. 10815 * 10816 * @static 10817 * @memberOf _ 10818 * @since 0.1.0 10819 * @category Collection 10820 * @param {Array|Object} collection The collection to iterate over. 10821 * @param {Function} [predicate=_.identity] The function invoked per iteration. 10822 * @returns {Array} Returns the new filtered array. 10823 * @see _.reject 10824 * @example 10825 * 10826 * var users = [ 10827 * { 'user': 'barney', 'age': 36, 'active': true }, 10828 * { 'user': 'fred', 'age': 40, 'active': false } 10829 * ]; 10830 * 10831 * _.filter(users, function(o) { return !o.active; }); 10832 * // => objects for ['fred'] 10833 * 10834 * // The `_.matches` iteratee shorthand. 10835 * _.filter(users, { 'age': 36, 'active': true }); 10836 * // => objects for ['barney'] 10837 * 10838 * // The `_.matchesProperty` iteratee shorthand. 10839 * _.filter(users, ['active', false]); 10840 * // => objects for ['fred'] 10841 * 10842 * // The `_.property` iteratee shorthand. 10843 * _.filter(users, 'active'); 10844 * // => objects for ['barney'] 10845 * 10846 * // Combining several predicates using `_.overEvery` or `_.overSome`. 10847 * _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]])); 10848 * // => objects for ['fred', 'barney'] 10849 */ 10850 function filter(collection, predicate) { 10851 var func = isArray(collection) ? arrayFilter : baseFilter; 10852 return func(collection, getIteratee(predicate, 3)); 10853 } 10854 10855 /** 10856 * Iterates over elements of `collection`, returning the first element 10857 * `predicate` returns truthy for. The predicate is invoked with three 10858 * arguments: (value, index|key, collection). 10859 * 10860 * @static 10861 * @memberOf _ 10862 * @since 0.1.0 10863 * @category Collection 10864 * @param {Array|Object} collection The collection to inspect. 10865 * @param {Function} [predicate=_.identity] The function invoked per iteration. 10866 * @param {number} [fromIndex=0] The index to search from. 10867 * @returns {*} Returns the matched element, else `undefined`. 10868 * @example 10869 * 10870 * var users = [ 10871 * { 'user': 'barney', 'age': 36, 'active': true }, 10872 * { 'user': 'fred', 'age': 40, 'active': false }, 10873 * { 'user': 'pebbles', 'age': 1, 'active': true } 10874 * ]; 10875 * 10876 * _.find(users, function(o) { return o.age < 40; }); 10877 * // => object for 'barney' 10878 * 10879 * // The `_.matches` iteratee shorthand. 10880 * _.find(users, { 'age': 1, 'active': true }); 10881 * // => object for 'pebbles' 10882 * 10883 * // The `_.matchesProperty` iteratee shorthand. 10884 * _.find(users, ['active', false]); 10885 * // => object for 'fred' 10886 * 10887 * // The `_.property` iteratee shorthand. 10888 * _.find(users, 'active'); 10889 * // => object for 'barney' 10890 */ 10891 var find = createFind(findIndex); 10892 10893 /** 10894 * This method is like `_.find` except that it iterates over elements of 10895 * `collection` from right to left. 10896 * 10897 * @static 10898 * @memberOf _ 10899 * @since 2.0.0 10900 * @category Collection 10901 * @param {Array|Object} collection The collection to inspect. 10902 * @param {Function} [predicate=_.identity] The function invoked per iteration. 10903 * @param {number} [fromIndex=collection.length-1] The index to search from. 10904 * @returns {*} Returns the matched element, else `undefined`. 10905 * @example 10906 * 10907 * _.findLast([1, 2, 3, 4], function(n) { 10908 * return n % 2 == 1; 10909 * }); 10910 * // => 3 10911 */ 10912 var findLast = createFind(findLastIndex); 10913 10914 /** 10915 * Creates a flattened array of values by running each element in `collection` 10916 * thru `iteratee` and flattening the mapped results. The iteratee is invoked 10917 * with three arguments: (value, index|key, collection). 10918 * 10919 * @static 10920 * @memberOf _ 10921 * @since 4.0.0 10922 * @category Collection 10923 * @param {Array|Object} collection The collection to iterate over. 10924 * @param {Function} [iteratee=_.identity] The function invoked per iteration. 10925 * @returns {Array} Returns the new flattened array. 10926 * @example 10927 * 10928 * function duplicate(n) { 10929 * return [n, n]; 10930 * } 10931 * 10932 * _.flatMap([1, 2], duplicate); 10933 * // => [1, 1, 2, 2] 10934 */ 10935 function flatMap(collection, iteratee) { 10936 return baseFlatten(map(collection, iteratee), 1); 10937 } 10938 10939 /** 10940 * This method is like `_.flatMap` except that it recursively flattens the 10941 * mapped results. 10942 * 10943 * @static 10944 * @memberOf _ 10945 * @since 4.7.0 10946 * @category Collection 10947 * @param {Array|Object} collection The collection to iterate over. 10948 * @param {Function} [iteratee=_.identity] The function invoked per iteration. 10949 * @returns {Array} Returns the new flattened array. 10950 * @example 10951 * 10952 * function duplicate(n) { 10953 * return [[[n, n]]]; 10954 * } 10955 * 10956 * _.flatMapDeep([1, 2], duplicate); 10957 * // => [1, 1, 2, 2] 10958 */ 10959 function flatMapDeep(collection, iteratee) { 10960 return baseFlatten(map(collection, iteratee), INFINITY); 10961 } 10962 10963 /** 10964 * This method is like `_.flatMap` except that it recursively flattens the 10965 * mapped results up to `depth` times. 10966 * 10967 * @static 10968 * @memberOf _ 10969 * @since 4.7.0 10970 * @category Collection 10971 * @param {Array|Object} collection The collection to iterate over. 10972 * @param {Function} [iteratee=_.identity] The function invoked per iteration. 10973 * @param {number} [depth=1] The maximum recursion depth. 10974 * @returns {Array} Returns the new flattened array. 10975 * @example 10976 * 10977 * function duplicate(n) { 10978 * return [[[n, n]]]; 10979 * } 10980 * 10981 * _.flatMapDepth([1, 2], duplicate, 2); 10982 * // => [[1, 1], [2, 2]] 10983 */ 10984 function flatMapDepth(collection, iteratee, depth) { 10985 depth = depth === undefined ? 1 : toInteger(depth); 10986 return baseFlatten(map(collection, iteratee), depth); 10987 } 10988 10989 /** 10990 * Iterates over elements of `collection` and invokes `iteratee` for each element. 10991 * The iteratee is invoked with three arguments: (value, index|key, collection). 10992 * Iteratee functions may exit iteration early by explicitly returning `false`. 10993 * 10994 * **Note:** As with other "Collections" methods, objects with a "length" 10995 * property are iterated like arrays. To avoid this behavior use `_.forIn` 10996 * or `_.forOwn` for object iteration. 10997 * 10998 * @static 10999 * @memberOf _ 11000 * @since 0.1.0 11001 * @alias each 11002 * @category Collection 11003 * @param {Array|Object} collection The collection to iterate over. 11004 * @param {Function} [iteratee=_.identity] The function invoked per iteration. 11005 * @returns {Array|Object} Returns `collection`. 11006 * @see _.forEachRight 11007 * @example 11008 * 11009 * _.forEach([1, 2], function(value) { 11010 * console.log(value); 11011 * }); 11012 * // => Logs `1` then `2`. 11013 * 11014 * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { 11015 * console.log(key); 11016 * }); 11017 * // => Logs 'a' then 'b' (iteration order is not guaranteed). 11018 */ 11019 function forEach(collection, iteratee) { 11020 var func = isArray(collection) ? arrayEach : baseEach; 11021 return func(collection, getIteratee(iteratee, 3)); 11022 } 11023 11024 /** 11025 * This method is like `_.forEach` except that it iterates over elements of 11026 * `collection` from right to left. 11027 * 11028 * @static 11029 * @memberOf _ 11030 * @since 2.0.0 11031 * @alias eachRight 11032 * @category Collection 11033 * @param {Array|Object} collection The collection to iterate over. 11034 * @param {Function} [iteratee=_.identity] The function invoked per iteration. 11035 * @returns {Array|Object} Returns `collection`. 11036 * @see _.forEach 11037 * @example 11038 * 11039 * _.forEachRight([1, 2], function(value) { 11040 * console.log(value); 11041 * }); 11042 * // => Logs `2` then `1`. 11043 */ 11044 function forEachRight(collection, iteratee) { 11045 var func = isArray(collection) ? arrayEachRight : baseEachRight; 11046 return func(collection, getIteratee(iteratee, 3)); 11047 } 11048 11049 /**
vendor: 4,136 bytes, lines 11050-11157
11050 * Creates an object composed of keys generated from the results of running 11051 * each element of `collection` thru `iteratee`. The order of grouped values 11052 * is determined by the order they occur in `collection`. The corresponding 11053 * value of each key is an array of elements responsible for generating the 11054 * key. The iteratee is invoked with one argument: (value). 11055 * 11056 * @static 11057 * @memberOf _ 11058 * @since 0.1.0 11059 * @category Collection 11060 * @param {Array|Object} collection The collection to iterate over. 11061 * @param {Function} [iteratee=_.identity] The iteratee to transform keys. 11062 * @returns {Object} Returns the composed aggregate object. 11063 * @example 11064 * 11065 * _.groupBy([6.1, 4.2, 6.3], Math.floor); 11066 * // => { '4': [4.2], '6': [6.1, 6.3] } 11067 * 11068 * // The `_.property` iteratee shorthand. 11069 * _.groupBy(['one', 'two', 'three'], 'length'); 11070 * // => { '3': ['one', 'two'], '5': ['three'] } 11071 */ 11072 var groupBy = createAggregator(function(result, value, key) { 11073 if (hasOwnProperty.call(result, key)) { 11074 result[key].push(value); 11075 } else { 11076 baseAssignValue(result, key, [value]); 11077 } 11078 }); 11079 11080 /** 11081 * Checks if `value` is in `collection`. If `collection` is a string, it's 11082 * checked for a substring of `value`, otherwise 11083 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) 11084 * is used for equality comparisons. If `fromIndex` is negative, it's used as 11085 * the offset from the end of `collection`. 11086 * 11087 * @static 11088 * @memberOf _ 11089 * @since 0.1.0 11090 * @category Collection 11091 * @param {Array|Object|string} collection The collection to inspect. 11092 * @param {*} value The value to search for. 11093 * @param {number} [fromIndex=0] The index to search from. 11094 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. 11095 * @returns {boolean} Returns `true` if `value` is found, else `false`. 11096 * @example 11097 * 11098 * _.includes([1, 2, 3], 1); 11099 * // => true 11100 * 11101 * _.includes([1, 2, 3], 1, 2); 11102 * // => false 11103 * 11104 * _.includes({ 'a': 1, 'b': 2 }, 1); 11105 * // => true 11106 * 11107 * _.includes('abcd', 'bc'); 11108 * // => true 11109 */ 11110 function includes(collection, value, fromIndex, guard) { 11111 collection = isArrayLike(collection) ? collection : values(collection); 11112 fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0; 11113 11114 var length = collection.length; 11115 if (fromIndex < 0) { 11116 fromIndex = nativeMax(length + fromIndex, 0); 11117 } 11118 return isString(collection) 11119 ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1) 11120 : (!!length && baseIndexOf(collection, value, fromIndex) > -1); 11121 } 11122 11123 /** 11124 * Invokes the method at `path` of each element in `collection`, returning 11125 * an array of the results of each invoked method. Any additional arguments 11126 * are provided to each invoked method. If `path` is a function, it's invoked 11127 * for, and `this` bound to, each element in `collection`. 11128 * 11129 * @static 11130 * @memberOf _ 11131 * @since 4.0.0 11132 * @category Collection 11133 * @param {Array|Object} collection The collection to iterate over. 11134 * @param {Array|Function|string} path The path of the method to invoke or 11135 * the function invoked per iteration. 11136 * @param {...*} [args] The arguments to invoke each method with. 11137 * @returns {Array} Returns the array of results. 11138 * @example 11139 * 11140 * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort'); 11141 * // => [[1, 5, 7], [1, 2, 3]] 11142 * 11143 * _.invokeMap([123, 456], String.prototype.split, ''); 11144 * // => [['1', '2', '3'], ['4', '5', '6']] 11145 */ 11146 var invokeMap = baseRest(function(collection, path, args) { 11147 var index = -1, 11148 isFunc = typeof path == 'function', 11149 result = isArrayLike(collection) ? Array(collection.length) : []; 11150 11151 baseEach(collection, function(value) { 11152 result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args); 11153 }); 11154 return result; 11155 }); 11156 11157 /**
vendor: 68,500 bytes, lines 11158-13272
11158 * Creates an object composed of keys generated from the results of running 11159 * each element of `collection` thru `iteratee`. The corresponding value of 11160 * each key is the last element responsible for generating the key. The 11161 * iteratee is invoked with one argument: (value). 11162 * 11163 * @static 11164 * @memberOf _ 11165 * @since 4.0.0 11166 * @category Collection 11167 * @param {Array|Object} collection The collection to iterate over. 11168 * @param {Function} [iteratee=_.identity] The iteratee to transform keys. 11169 * @returns {Object} Returns the composed aggregate object. 11170 * @example 11171 * 11172 * var array = [ 11173 * { 'dir': 'left', 'code': 97 }, 11174 * { 'dir': 'right', 'code': 100 } 11175 * ]; 11176 * 11177 * _.keyBy(array, function(o) { 11178 * return String.fromCharCode(o.code); 11179 * }); 11180 * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } 11181 * 11182 * _.keyBy(array, 'dir'); 11183 * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } 11184 */ 11185 var keyBy = createAggregator(function(result, value, key) { 11186 baseAssignValue(result, key, value); 11187 }); 11188 11189 /** 11190 * Creates an array of values by running each element in `collection` thru 11191 * `iteratee`. The iteratee is invoked with three arguments: 11192 * (value, index|key, collection). 11193 * 11194 * Many lodash methods are guarded to work as iteratees for methods like 11195 * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. 11196 * 11197 * The guarded methods are: 11198 * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, 11199 * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`, 11200 * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`, 11201 * `template`, `trim`, `trimEnd`, `trimStart`, and `words` 11202 * 11203 * @static 11204 * @memberOf _ 11205 * @since 0.1.0 11206 * @category Collection 11207 * @param {Array|Object} collection The collection to iterate over. 11208 * @param {Function} [iteratee=_.identity] The function invoked per iteration. 11209 * @returns {Array} Returns the new mapped array. 11210 * @example 11211 * 11212 * function square(n) { 11213 * return n * n; 11214 * } 11215 * 11216 * _.map([4, 8], square); 11217 * // => [16, 64] 11218 * 11219 * _.map({ 'a': 4, 'b': 8 }, square); 11220 * // => [16, 64] (iteration order is not guaranteed) 11221 * 11222 * var users = [ 11223 * { 'user': 'barney' }, 11224 * { 'user': 'fred' } 11225 * ]; 11226 * 11227 * // The `_.property` iteratee shorthand. 11228 * _.map(users, 'user'); 11229 * // => ['barney', 'fred'] 11230 */ 11231 function map(collection, iteratee) { 11232 var func = isArray(collection) ? arrayMap : baseMap; 11233 return func(collection, getIteratee(iteratee, 3)); 11234 } 11235 11236 /** 11237 * This method is like `_.sortBy` except that it allows specifying the sort 11238 * orders of the iteratees to sort by. If `orders` is unspecified, all values 11239 * are sorted in ascending order. Otherwise, specify an order of "desc" for 11240 * descending or "asc" for ascending sort order of corresponding values. 11241 * 11242 * @static 11243 * @memberOf _ 11244 * @since 4.0.0 11245 * @category Collection 11246 * @param {Array|Object} collection The collection to iterate over. 11247 * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]] 11248 * The iteratees to sort by. 11249 * @param {string[]} [orders] The sort orders of `iteratees`. 11250 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. 11251 * @returns {Array} Returns the new sorted array. 11252 * @example 11253 * 11254 * var users = [ 11255 * { 'user': 'fred', 'age': 48 }, 11256 * { 'user': 'barney', 'age': 34 }, 11257 * { 'user': 'fred', 'age': 40 }, 11258 * { 'user': 'barney', 'age': 36 } 11259 * ]; 11260 * 11261 * // Sort by `user` in ascending order and by `age` in descending order. 11262 * _.orderBy(users, ['user', 'age'], ['asc', 'desc']); 11263 * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] 11264 */ 11265 function orderBy(collection, iteratees, orders, guard) { 11266 if (collection == null) { 11267 return []; 11268 } 11269 if (!isArray(iteratees)) { 11270 iteratees = iteratees == null ? [] : [iteratees]; 11271 } 11272 orders = guard ? undefined : orders; 11273 if (!isArray(orders)) { 11274 orders = orders == null ? [] : [orders]; 11275 } 11276 return baseOrderBy(collection, iteratees, orders); 11277 } 11278 11279 /** 11280 * Creates an array of elements split into two groups, the first of which 11281 * contains elements `predicate` returns truthy for, the second of which 11282 * contains elements `predicate` returns falsey for. The predicate is 11283 * invoked with one argument: (value). 11284 * 11285 * @static 11286 * @memberOf _ 11287 * @since 3.0.0 11288 * @category Collection 11289 * @param {Array|Object} collection The collection to iterate over. 11290 * @param {Function} [predicate=_.identity] The function invoked per iteration. 11291 * @returns {Array} Returns the array of grouped elements. 11292 * @example 11293 * 11294 * var users = [ 11295 * { 'user': 'barney', 'age': 36, 'active': false }, 11296 * { 'user': 'fred', 'age': 40, 'active': true }, 11297 * { 'user': 'pebbles', 'age': 1, 'active': false } 11298 * ]; 11299 * 11300 * _.partition(users, function(o) { return o.active; }); 11301 * // => objects for [['fred'], ['barney', 'pebbles']] 11302 * 11303 * // The `_.matches` iteratee shorthand. 11304 * _.partition(users, { 'age': 1, 'active': false }); 11305 * // => objects for [['pebbles'], ['barney', 'fred']] 11306 * 11307 * // The `_.matchesProperty` iteratee shorthand. 11308 * _.partition(users, ['active', false]); 11309 * // => objects for [['barney', 'pebbles'], ['fred']] 11310 * 11311 * // The `_.property` iteratee shorthand. 11312 * _.partition(users, 'active'); 11313 * // => objects for [['fred'], ['barney', 'pebbles']] 11314 */ 11315 var partition = createAggregator(function(result, value, key) { 11316 result[key ? 0 : 1].push(value); 11317 }, function() { return [[], []]; }); 11318 11319 /** 11320 * Reduces `collection` to a value which is the accumulated result of running 11321 * each element in `collection` thru `iteratee`, where each successive 11322 * invocation is supplied the return value of the previous. If `accumulator` 11323 * is not given, the first element of `collection` is used as the initial 11324 * value. The iteratee is invoked with four arguments: 11325 * (accumulator, value, index|key, collection). 11326 * 11327 * Many lodash methods are guarded to work as iteratees for methods like 11328 * `_.reduce`, `_.reduceRight`, and `_.transform`. 11329 * 11330 * The guarded methods are: 11331 * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`, 11332 * and `sortBy` 11333 * 11334 * @static 11335 * @memberOf _ 11336 * @since 0.1.0 11337 * @category Collection 11338 * @param {Array|Object} collection The collection to iterate over. 11339 * @param {Function} [iteratee=_.identity] The function invoked per iteration. 11340 * @param {*} [accumulator] The initial value. 11341 * @returns {*} Returns the accumulated value. 11342 * @see _.reduceRight 11343 * @example 11344 * 11345 * _.reduce([1, 2], function(sum, n) { 11346 * return sum + n; 11347 * }, 0); 11348 * // => 3 11349 * 11350 * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { 11351 * (result[value] || (result[value] = [])).push(key); 11352 * return result; 11353 * }, {}); 11354 * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed) 11355 */ 11356 function reduce(collection, iteratee, accumulator) { 11357 var func = isArray(collection) ? arrayReduce : baseReduce, 11358 initAccum = arguments.length < 3; 11359 11360 return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach); 11361 } 11362 11363 /** 11364 * This method is like `_.reduce` except that it iterates over elements of 11365 * `collection` from right to left. 11366 * 11367 * @static 11368 * @memberOf _ 11369 * @since 0.1.0 11370 * @category Collection 11371 * @param {Array|Object} collection The collection to iterate over. 11372 * @param {Function} [iteratee=_.identity] The function invoked per iteration. 11373 * @param {*} [accumulator] The initial value. 11374 * @returns {*} Returns the accumulated value. 11375 * @see _.reduce 11376 * @example 11377 * 11378 * var array = [[0, 1], [2, 3], [4, 5]]; 11379 * 11380 * _.reduceRight(array, function(flattened, other) { 11381 * return flattened.concat(other); 11382 * }, []); 11383 * // => [4, 5, 2, 3, 0, 1] 11384 */ 11385 function reduceRight(collection, iteratee, accumulator) { 11386 var func = isArray(collection) ? arrayReduceRight : baseReduce, 11387 initAccum = arguments.length < 3; 11388 11389 return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight); 11390 } 11391 11392 /** 11393 * The opposite of `_.filter`; this method returns the elements of `collection` 11394 * that `predicate` does **not** return truthy for. 11395 * 11396 * @static 11397 * @memberOf _ 11398 * @since 0.1.0 11399 * @category Collection 11400 * @param {Array|Object} collection The collection to iterate over. 11401 * @param {Function} [predicate=_.identity] The function invoked per iteration. 11402 * @returns {Array} Returns the new filtered array. 11403 * @see _.filter 11404 * @example 11405 * 11406 * var users = [ 11407 * { 'user': 'barney', 'age': 36, 'active': false }, 11408 * { 'user': 'fred', 'age': 40, 'active': true } 11409 * ]; 11410 * 11411 * _.reject(users, function(o) { return !o.active; }); 11412 * // => objects for ['fred'] 11413 * 11414 * // The `_.matches` iteratee shorthand. 11415 * _.reject(users, { 'age': 40, 'active': true }); 11416 * // => objects for ['barney'] 11417 * 11418 * // The `_.matchesProperty` iteratee shorthand. 11419 * _.reject(users, ['active', false]); 11420 * // => objects for ['fred'] 11421 * 11422 * // The `_.property` iteratee shorthand. 11423 * _.reject(users, 'active'); 11424 * // => objects for ['barney'] 11425 */ 11426 function reject(collection, predicate) { 11427 var func = isArray(collection) ? arrayFilter : baseFilter; 11428 return func(collection, negate(getIteratee(predicate, 3))); 11429 } 11430 11431 /** 11432 * Gets a random element from `collection`. 11433 * 11434 * @static 11435 * @memberOf _ 11436 * @since 2.0.0 11437 * @category Collection 11438 * @param {Array|Object} collection The collection to sample. 11439 * @returns {*} Returns the random element. 11440 * @example 11441 * 11442 * _.sample([1, 2, 3, 4]); 11443 * // => 2 11444 */ 11445 function sample(collection) { 11446 var func = isArray(collection) ? arraySample : baseSample; 11447 return func(collection); 11448 } 11449 11450 /** 11451 * Gets `n` random elements at unique keys from `collection` up to the 11452 * size of `collection`. 11453 * 11454 * @static 11455 * @memberOf _ 11456 * @since 4.0.0 11457 * @category Collection 11458 * @param {Array|Object} collection The collection to sample. 11459 * @param {number} [n=1] The number of elements to sample. 11460 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 11461 * @returns {Array} Returns the random elements. 11462 * @example 11463 * 11464 * _.sampleSize([1, 2, 3], 2); 11465 * // => [3, 1] 11466 * 11467 * _.sampleSize([1, 2, 3], 4); 11468 * // => [2, 3, 1] 11469 */ 11470 function sampleSize(collection, n, guard) { 11471 if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) { 11472 n = 1; 11473 } else { 11474 n = toInteger(n); 11475 } 11476 var func = isArray(collection) ? arraySampleSize : baseSampleSize; 11477 return func(collection, n); 11478 } 11479 11480 /** 11481 * Creates an array of shuffled values, using a version of the 11482 * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle). 11483 * 11484 * @static 11485 * @memberOf _ 11486 * @since 0.1.0 11487 * @category Collection 11488 * @param {Array|Object} collection The collection to shuffle. 11489 * @returns {Array} Returns the new shuffled array. 11490 * @example 11491 * 11492 * _.shuffle([1, 2, 3, 4]); 11493 * // => [4, 1, 3, 2] 11494 */ 11495 function shuffle(collection) { 11496 var func = isArray(collection) ? arrayShuffle : baseShuffle; 11497 return func(collection); 11498 } 11499 11500 /** 11501 * Gets the size of `collection` by returning its length for array-like 11502 * values or the number of own enumerable string keyed properties for objects. 11503 * 11504 * @static 11505 * @memberOf _ 11506 * @since 0.1.0 11507 * @category Collection 11508 * @param {Array|Object|string} collection The collection to inspect. 11509 * @returns {number} Returns the collection size. 11510 * @example 11511 * 11512 * _.size([1, 2, 3]); 11513 * // => 3 11514 * 11515 * _.size({ 'a': 1, 'b': 2 }); 11516 * // => 2 11517 * 11518 * _.size('pebbles'); 11519 * // => 7 11520 */ 11521 function size(collection) { 11522 if (collection == null) { 11523 return 0; 11524 } 11525 if (isArrayLike(collection)) { 11526 return isString(collection) ? stringSize(collection) : collection.length; 11527 } 11528 var tag = getTag(collection); 11529 if (tag == mapTag || tag == setTag) { 11530 return collection.size; 11531 } 11532 return baseKeys(collection).length; 11533 } 11534 11535 /** 11536 * Checks if `predicate` returns truthy for **any** element of `collection`. 11537 * Iteration is stopped once `predicate` returns truthy. The predicate is 11538 * invoked with three arguments: (value, index|key, collection). 11539 * 11540 * @static 11541 * @memberOf _ 11542 * @since 0.1.0 11543 * @category Collection 11544 * @param {Array|Object} collection The collection to iterate over. 11545 * @param {Function} [predicate=_.identity] The function invoked per iteration. 11546 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 11547 * @returns {boolean} Returns `true` if any element passes the predicate check, 11548 * else `false`. 11549 * @example 11550 * 11551 * _.some([null, 0, 'yes', false], Boolean); 11552 * // => true 11553 * 11554 * var users = [ 11555 * { 'user': 'barney', 'active': true }, 11556 * { 'user': 'fred', 'active': false } 11557 * ]; 11558 * 11559 * // The `_.matches` iteratee shorthand. 11560 * _.some(users, { 'user': 'barney', 'active': false }); 11561 * // => false 11562 * 11563 * // The `_.matchesProperty` iteratee shorthand. 11564 * _.some(users, ['active', false]); 11565 * // => true 11566 * 11567 * // The `_.property` iteratee shorthand. 11568 * _.some(users, 'active'); 11569 * // => true 11570 */ 11571 function some(collection, predicate, guard) { 11572 var func = isArray(collection) ? arraySome : baseSome; 11573 if (guard && isIterateeCall(collection, predicate, guard)) { 11574 predicate = undefined; 11575 } 11576 return func(collection, getIteratee(predicate, 3)); 11577 } 11578 11579 /** 11580 * Creates an array of elements, sorted in ascending order by the results of 11581 * running each element in a collection thru each iteratee. This method 11582 * performs a stable sort, that is, it preserves the original sort order of 11583 * equal elements. The iteratees are invoked with one argument: (value). 11584 * 11585 * @static 11586 * @memberOf _ 11587 * @since 0.1.0 11588 * @category Collection 11589 * @param {Array|Object} collection The collection to iterate over. 11590 * @param {...(Function|Function[])} [iteratees=[_.identity]] 11591 * The iteratees to sort by. 11592 * @returns {Array} Returns the new sorted array. 11593 * @example 11594 * 11595 * var users = [ 11596 * { 'user': 'fred', 'age': 48 }, 11597 * { 'user': 'barney', 'age': 36 }, 11598 * { 'user': 'fred', 'age': 30 }, 11599 * { 'user': 'barney', 'age': 34 } 11600 * ]; 11601 * 11602 * _.sortBy(users, [function(o) { return o.user; }]); 11603 * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]] 11604 * 11605 * _.sortBy(users, ['user', 'age']); 11606 * // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]] 11607 */ 11608 var sortBy = baseRest(function(collection, iteratees) { 11609 if (collection == null) { 11610 return []; 11611 } 11612 var length = iteratees.length; 11613 if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) { 11614 iteratees = []; 11615 } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) { 11616 iteratees = [iteratees[0]]; 11617 } 11618 return baseOrderBy(collection, baseFlatten(iteratees, 1), []); 11619 }); 11620 11621 /*------------------------------------------------------------------------*/ 11622 11623 /** 11624 * Gets the timestamp of the number of milliseconds that have elapsed since 11625 * the Unix epoch (1 January 1970 00:00:00 UTC). 11626 * 11627 * @static 11628 * @memberOf _ 11629 * @since 2.4.0 11630 * @category Date 11631 * @returns {number} Returns the timestamp. 11632 * @example 11633 * 11634 * _.defer(function(stamp) { 11635 * console.log(_.now() - stamp); 11636 * }, _.now()); 11637 * // => Logs the number of milliseconds it took for the deferred invocation. 11638 */ 11639 var now = ctxNow || function() { 11640 return root.Date.now(); 11641 }; 11642 11643 /*------------------------------------------------------------------------*/ 11644 11645 /** 11646 * The opposite of `_.before`; this method creates a function that invokes 11647 * `func` once it's called `n` or more times. 11648 * 11649 * @static 11650 * @memberOf _ 11651 * @since 0.1.0 11652 * @category Function 11653 * @param {number} n The number of calls before `func` is invoked. 11654 * @param {Function} func The function to restrict. 11655 * @returns {Function} Returns the new restricted function. 11656 * @example 11657 * 11658 * var saves = ['profile', 'settings']; 11659 * 11660 * var done = _.after(saves.length, function() { 11661 * console.log('done saving!'); 11662 * }); 11663 * 11664 * _.forEach(saves, function(type) { 11665 * asyncSave({ 'type': type, 'complete': done }); 11666 * }); 11667 * // => Logs 'done saving!' after the two async saves have completed. 11668 */ 11669 function after(n, func) { 11670 if (typeof func != 'function') { 11671 throw new TypeError(FUNC_ERROR_TEXT); 11672 } 11673 n = toInteger(n); 11674 return function() { 11675 if (--n < 1) { 11676 return func.apply(this, arguments); 11677 } 11678 }; 11679 } 11680 11681 /** 11682 * Creates a function that invokes `func`, with up to `n` arguments, 11683 * ignoring any additional arguments. 11684 * 11685 * @static 11686 * @memberOf _ 11687 * @since 3.0.0 11688 * @category Function 11689 * @param {Function} func The function to cap arguments for. 11690 * @param {number} [n=func.length] The arity cap. 11691 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 11692 * @returns {Function} Returns the new capped function. 11693 * @example 11694 * 11695 * _.map(['6', '8', '10'], _.ary(parseInt, 1)); 11696 * // => [6, 8, 10] 11697 */ 11698 function ary(func, n, guard) { 11699 n = guard ? undefined : n; 11700 n = (func && n == null) ? func.length : n; 11701 return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n); 11702 } 11703 11704 /** 11705 * Creates a function that invokes `func`, with the `this` binding and arguments 11706 * of the created function, while it's called less than `n` times. Subsequent 11707 * calls to the created function return the result of the last `func` invocation. 11708 * 11709 * @static 11710 * @memberOf _ 11711 * @since 3.0.0 11712 * @category Function 11713 * @param {number} n The number of calls at which `func` is no longer invoked. 11714 * @param {Function} func The function to restrict. 11715 * @returns {Function} Returns the new restricted function. 11716 * @example 11717 * 11718 * jQuery(element).on('click', _.before(5, addContactToList)); 11719 * // => Allows adding up to 4 contacts to the list. 11720 */ 11721 function before(n, func) { 11722 var result; 11723 if (typeof func != 'function') { 11724 throw new TypeError(FUNC_ERROR_TEXT); 11725 } 11726 n = toInteger(n); 11727 return function() { 11728 if (--n > 0) { 11729 result = func.apply(this, arguments); 11730 } 11731 if (n <= 1) { 11732 func = undefined; 11733 } 11734 return result; 11735 }; 11736 } 11737 11738 /** 11739 * Creates a function that invokes `func` with the `this` binding of `thisArg` 11740 * and `partials` prepended to the arguments it receives. 11741 * 11742 * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, 11743 * may be used as a placeholder for partially applied arguments. 11744 * 11745 * **Note:** Unlike native `Function#bind`, this method doesn't set the "length" 11746 * property of bound functions. 11747 * 11748 * @static 11749 * @memberOf _ 11750 * @since 0.1.0 11751 * @category Function 11752 * @param {Function} func The function to bind. 11753 * @param {*} thisArg The `this` binding of `func`. 11754 * @param {...*} [partials] The arguments to be partially applied. 11755 * @returns {Function} Returns the new bound function. 11756 * @example 11757 * 11758 * function greet(greeting, punctuation) { 11759 * return greeting + ' ' + this.user + punctuation; 11760 * } 11761 * 11762 * var object = { 'user': 'fred' }; 11763 * 11764 * var bound = _.bind(greet, object, 'hi'); 11765 * bound('!'); 11766 * // => 'hi fred!' 11767 * 11768 * // Bound with placeholders. 11769 * var bound = _.bind(greet, object, _, '!'); 11770 * bound('hi'); 11771 * // => 'hi fred!' 11772 */ 11773 var bind = baseRest(function(func, thisArg, partials) { 11774 var bitmask = WRAP_BIND_FLAG; 11775 if (partials.length) { 11776 var holders = replaceHolders(partials, getHolder(bind)); 11777 bitmask |= WRAP_PARTIAL_FLAG; 11778 } 11779 return createWrap(func, bitmask, thisArg, partials, holders); 11780 }); 11781 11782 /** 11783 * Creates a function that invokes the method at `object[key]` with `partials` 11784 * prepended to the arguments it receives. 11785 * 11786 * This method differs from `_.bind` by allowing bound functions to reference 11787 * methods that may be redefined or don't yet exist. See 11788 * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern) 11789 * for more details. 11790 * 11791 * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic 11792 * builds, may be used as a placeholder for partially applied arguments. 11793 * 11794 * @static 11795 * @memberOf _ 11796 * @since 0.10.0 11797 * @category Function 11798 * @param {Object} object The object to invoke the method on. 11799 * @param {string} key The key of the method. 11800 * @param {...*} [partials] The arguments to be partially applied. 11801 * @returns {Function} Returns the new bound function. 11802 * @example 11803 * 11804 * var object = { 11805 * 'user': 'fred', 11806 * 'greet': function(greeting, punctuation) { 11807 * return greeting + ' ' + this.user + punctuation; 11808 * } 11809 * }; 11810 * 11811 * var bound = _.bindKey(object, 'greet', 'hi'); 11812 * bound('!'); 11813 * // => 'hi fred!' 11814 * 11815 * object.greet = function(greeting, punctuation) { 11816 * return greeting + 'ya ' + this.user + punctuation; 11817 * }; 11818 * 11819 * bound('!'); 11820 * // => 'hiya fred!' 11821 * 11822 * // Bound with placeholders. 11823 * var bound = _.bindKey(object, 'greet', _, '!'); 11824 * bound('hi'); 11825 * // => 'hiya fred!' 11826 */ 11827 var bindKey = baseRest(function(object, key, partials) { 11828 var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG; 11829 if (partials.length) { 11830 var holders = replaceHolders(partials, getHolder(bindKey)); 11831 bitmask |= WRAP_PARTIAL_FLAG; 11832 } 11833 return createWrap(key, bitmask, object, partials, holders); 11834 }); 11835 11836 /** 11837 * Creates a function that accepts arguments of `func` and either invokes 11838 * `func` returning its result, if at least `arity` number of arguments have 11839 * been provided, or returns a function that accepts the remaining `func` 11840 * arguments, and so on. The arity of `func` may be specified if `func.length` 11841 * is not sufficient. 11842 * 11843 * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds, 11844 * may be used as a placeholder for provided arguments. 11845 * 11846 * **Note:** This method doesn't set the "length" property of curried functions. 11847 * 11848 * @static 11849 * @memberOf _ 11850 * @since 2.0.0 11851 * @category Function 11852 * @param {Function} func The function to curry. 11853 * @param {number} [arity=func.length] The arity of `func`. 11854 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 11855 * @returns {Function} Returns the new curried function. 11856 * @example 11857 * 11858 * var abc = function(a, b, c) { 11859 * return [a, b, c]; 11860 * }; 11861 * 11862 * var curried = _.curry(abc); 11863 * 11864 * curried(1)(2)(3); 11865 * // => [1, 2, 3] 11866 * 11867 * curried(1, 2)(3); 11868 * // => [1, 2, 3] 11869 * 11870 * curried(1, 2, 3); 11871 * // => [1, 2, 3] 11872 * 11873 * // Curried with placeholders. 11874 * curried(1)(_, 3)(2); 11875 * // => [1, 2, 3] 11876 */ 11877 function curry(func, arity, guard) { 11878 arity = guard ? undefined : arity; 11879 var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity); 11880 result.placeholder = curry.placeholder; 11881 return result; 11882 } 11883 11884 /** 11885 * This method is like `_.curry` except that arguments are applied to `func` 11886 * in the manner of `_.partialRight` instead of `_.partial`. 11887 * 11888 * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic 11889 * builds, may be used as a placeholder for provided arguments. 11890 * 11891 * **Note:** This method doesn't set the "length" property of curried functions. 11892 * 11893 * @static 11894 * @memberOf _ 11895 * @since 3.0.0 11896 * @category Function 11897 * @param {Function} func The function to curry. 11898 * @param {number} [arity=func.length] The arity of `func`. 11899 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 11900 * @returns {Function} Returns the new curried function. 11901 * @example 11902 * 11903 * var abc = function(a, b, c) { 11904 * return [a, b, c]; 11905 * }; 11906 * 11907 * var curried = _.curryRight(abc); 11908 * 11909 * curried(3)(2)(1); 11910 * // => [1, 2, 3] 11911 * 11912 * curried(2, 3)(1); 11913 * // => [1, 2, 3] 11914 * 11915 * curried(1, 2, 3); 11916 * // => [1, 2, 3] 11917 * 11918 * // Curried with placeholders. 11919 * curried(3)(1, _)(2); 11920 * // => [1, 2, 3] 11921 */ 11922 function curryRight(func, arity, guard) { 11923 arity = guard ? undefined : arity; 11924 var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity); 11925 result.placeholder = curryRight.placeholder; 11926 return result; 11927 } 11928 11929 /** 11930 * Creates a debounced function that delays invoking `func` until after `wait` 11931 * milliseconds have elapsed since the last time the debounced function was 11932 * invoked. The debounced function comes with a `cancel` method to cancel 11933 * delayed `func` invocations and a `flush` method to immediately invoke them. 11934 * Provide `options` to indicate whether `func` should be invoked on the 11935 * leading and/or trailing edge of the `wait` timeout. The `func` is invoked 11936 * with the last arguments provided to the debounced function. Subsequent 11937 * calls to the debounced function return the result of the last `func` 11938 * invocation. 11939 * 11940 * **Note:** If `leading` and `trailing` options are `true`, `func` is 11941 * invoked on the trailing edge of the timeout only if the debounced function 11942 * is invoked more than once during the `wait` timeout. 11943 * 11944 * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred 11945 * until to the next tick, similar to `setTimeout` with a timeout of `0`. 11946 * 11947 * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) 11948 * for details over the differences between `_.debounce` and `_.throttle`. 11949 * 11950 * @static 11951 * @memberOf _ 11952 * @since 0.1.0 11953 * @category Function 11954 * @param {Function} func The function to debounce. 11955 * @param {number} [wait=0] The number of milliseconds to delay. 11956 * @param {Object} [options={}] The options object. 11957 * @param {boolean} [options.leading=false] 11958 * Specify invoking on the leading edge of the timeout. 11959 * @param {number} [options.maxWait] 11960 * The maximum time `func` is allowed to be delayed before it's invoked. 11961 * @param {boolean} [options.trailing=true] 11962 * Specify invoking on the trailing edge of the timeout. 11963 * @returns {Function} Returns the new debounced function. 11964 * @example 11965 * 11966 * // Avoid costly calculations while the window size is in flux. 11967 * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); 11968 * 11969 * // Invoke `sendMail` when clicked, debouncing subsequent calls. 11970 * jQuery(element).on('click', _.debounce(sendMail, 300, { 11971 * 'leading': true, 11972 * 'trailing': false 11973 * })); 11974 * 11975 * // Ensure `batchLog` is invoked once after 1 second of debounced calls. 11976 * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); 11977 * var source = new EventSource('/stream'); 11978 * jQuery(source).on('message', debounced); 11979 * 11980 * // Cancel the trailing debounced invocation. 11981 * jQuery(window).on('popstate', debounced.cancel); 11982 */ 11983 function debounce(func, wait, options) { 11984 var lastArgs, 11985 lastThis, 11986 maxWait, 11987 result, 11988 timerId, 11989 lastCallTime, 11990 lastInvokeTime = 0, 11991 leading = false, 11992 maxing = false, 11993 trailing = true; 11994 11995 if (typeof func != 'function') { 11996 throw new TypeError(FUNC_ERROR_TEXT); 11997 } 11998 wait = toNumber(wait) || 0; 11999 if (isObject(options)) { 12000 leading = !!options.leading; 12001 maxing = 'maxWait' in options; 12002 maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; 12003 trailing = 'trailing' in options ? !!options.trailing : trailing; 12004 } 12005 12006 function invokeFunc(time) { 12007 var args = lastArgs, 12008 thisArg = lastThis; 12009 12010 lastArgs = lastThis = undefined; 12011 lastInvokeTime = time; 12012 result = func.apply(thisArg, args); 12013 return result; 12014 } 12015 12016 function leadingEdge(time) { 12017 // Reset any `maxWait` timer. 12018 lastInvokeTime = time; 12019 // Start the timer for the trailing edge. 12020 timerId = setTimeout(timerExpired, wait); 12021 // Invoke the leading edge. 12022 return leading ? invokeFunc(time) : result; 12023 } 12024 12025 function remainingWait(time) { 12026 var timeSinceLastCall = time - lastCallTime, 12027 timeSinceLastInvoke = time - lastInvokeTime, 12028 timeWaiting = wait - timeSinceLastCall; 12029 12030 return maxing 12031 ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) 12032 : timeWaiting; 12033 } 12034 12035 function shouldInvoke(time) { 12036 var timeSinceLastCall = time - lastCallTime, 12037 timeSinceLastInvoke = time - lastInvokeTime; 12038 12039 // Either this is the first call, activity has stopped and we're at the 12040 // trailing edge, the system time has gone backwards and we're treating 12041 // it as the trailing edge, or we've hit the `maxWait` limit. 12042 return (lastCallTime === undefined || (timeSinceLastCall >= wait) || 12043 (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); 12044 } 12045 12046 function timerExpired() { 12047 var time = now(); 12048 if (shouldInvoke(time)) { 12049 return trailingEdge(time); 12050 } 12051 // Restart the timer. 12052 timerId = setTimeout(timerExpired, remainingWait(time)); 12053 } 12054 12055 function trailingEdge(time) { 12056 timerId = undefined; 12057 12058 // Only invoke if we have `lastArgs` which means `func` has been 12059 // debounced at least once. 12060 if (trailing && lastArgs) { 12061 return invokeFunc(time); 12062 } 12063 lastArgs = lastThis = undefined; 12064 return result; 12065 } 12066 12067 function cancel() { 12068 if (timerId !== undefined) { 12069 clearTimeout(timerId); 12070 } 12071 lastInvokeTime = 0; 12072 lastArgs = lastCallTime = lastThis = timerId = undefined; 12073 } 12074 12075 function flush() { 12076 return timerId === undefined ? result : trailingEdge(now()); 12077 } 12078 12079 function debounced() { 12080 var time = now(), 12081 isInvoking = shouldInvoke(time); 12082 12083 lastArgs = arguments; 12084 lastThis = this; 12085 lastCallTime = time; 12086 12087 if (isInvoking) { 12088 if (timerId === undefined) { 12089 return leadingEdge(lastCallTime); 12090 } 12091 if (maxing) { 12092 // Handle invocations in a tight loop. 12093 clearTimeout(timerId); 12094 timerId = setTimeout(timerExpired, wait); 12095 return invokeFunc(lastCallTime); 12096 } 12097 } 12098 if (timerId === undefined) { 12099 timerId = setTimeout(timerExpired, wait); 12100 } 12101 return result; 12102 } 12103 debounced.cancel = cancel; 12104 debounced.flush = flush; 12105 return debounced; 12106 } 12107 12108 /** 12109 * Defers invoking the `func` until the current call stack has cleared. Any 12110 * additional arguments are provided to `func` when it's invoked. 12111 * 12112 * @static 12113 * @memberOf _ 12114 * @since 0.1.0 12115 * @category Function 12116 * @param {Function} func The function to defer. 12117 * @param {...*} [args] The arguments to invoke `func` with. 12118 * @returns {number} Returns the timer id. 12119 * @example 12120 * 12121 * _.defer(function(text) { 12122 * console.log(text); 12123 * }, 'deferred'); 12124 * // => Logs 'deferred' after one millisecond. 12125 */ 12126 var defer = baseRest(function(func, args) { 12127 return baseDelay(func, 1, args); 12128 }); 12129 12130 /** 12131 * Invokes `func` after `wait` milliseconds. Any additional arguments are 12132 * provided to `func` when it's invoked. 12133 * 12134 * @static 12135 * @memberOf _ 12136 * @since 0.1.0 12137 * @category Function 12138 * @param {Function} func The function to delay. 12139 * @param {number} wait The number of milliseconds to delay invocation. 12140 * @param {...*} [args] The arguments to invoke `func` with. 12141 * @returns {number} Returns the timer id. 12142 * @example 12143 * 12144 * _.delay(function(text) { 12145 * console.log(text); 12146 * }, 1000, 'later'); 12147 * // => Logs 'later' after one second. 12148 */ 12149 var delay = baseRest(function(func, wait, args) { 12150 return baseDelay(func, toNumber(wait) || 0, args); 12151 }); 12152 12153 /** 12154 * Creates a function that invokes `func` with arguments reversed. 12155 * 12156 * @static 12157 * @memberOf _ 12158 * @since 4.0.0 12159 * @category Function 12160 * @param {Function} func The function to flip arguments for. 12161 * @returns {Function} Returns the new flipped function. 12162 * @example 12163 * 12164 * var flipped = _.flip(function() { 12165 * return _.toArray(arguments); 12166 * }); 12167 * 12168 * flipped('a', 'b', 'c', 'd'); 12169 * // => ['d', 'c', 'b', 'a'] 12170 */ 12171 function flip(func) { 12172 return createWrap(func, WRAP_FLIP_FLAG); 12173 } 12174 12175 /** 12176 * Creates a function that memoizes the result of `func`. If `resolver` is 12177 * provided, it determines the cache key for storing the result based on the 12178 * arguments provided to the memoized function. By default, the first argument 12179 * provided to the memoized function is used as the map cache key. The `func` 12180 * is invoked with the `this` binding of the memoized function. 12181 * 12182 * **Note:** The cache is exposed as the `cache` property on the memoized 12183 * function. Its creation may be customized by replacing the `_.memoize.Cache` 12184 * constructor with one whose instances implement the 12185 * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) 12186 * method interface of `clear`, `delete`, `get`, `has`, and `set`. 12187 * 12188 * @static 12189 * @memberOf _ 12190 * @since 0.1.0 12191 * @category Function 12192 * @param {Function} func The function to have its output memoized. 12193 * @param {Function} [resolver] The function to resolve the cache key. 12194 * @returns {Function} Returns the new memoized function. 12195 * @example 12196 * 12197 * var object = { 'a': 1, 'b': 2 }; 12198 * var other = { 'c': 3, 'd': 4 }; 12199 * 12200 * var values = _.memoize(_.values); 12201 * values(object); 12202 * // => [1, 2] 12203 * 12204 * values(other); 12205 * // => [3, 4] 12206 * 12207 * object.a = 2; 12208 * values(object); 12209 * // => [1, 2] 12210 * 12211 * // Modify the result cache. 12212 * values.cache.set(object, ['a', 'b']); 12213 * values(object); 12214 * // => ['a', 'b'] 12215 * 12216 * // Replace `_.memoize.Cache`. 12217 * _.memoize.Cache = WeakMap; 12218 */ 12219 function memoize(func, resolver) { 12220 if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) { 12221 throw new TypeError(FUNC_ERROR_TEXT); 12222 } 12223 var memoized = function() { 12224 var args = arguments, 12225 key = resolver ? resolver.apply(this, args) : args[0], 12226 cache = memoized.cache; 12227 12228 if (cache.has(key)) { 12229 return cache.get(key); 12230 } 12231 var result = func.apply(this, args); 12232 memoized.cache = cache.set(key, result) || cache; 12233 return result; 12234 }; 12235 memoized.cache = new (memoize.Cache || MapCache); 12236 return memoized; 12237 } 12238 12239 // Expose `MapCache`. 12240 memoize.Cache = MapCache; 12241 12242 /** 12243 * Creates a function that negates the result of the predicate `func`. The 12244 * `func` predicate is invoked with the `this` binding and arguments of the 12245 * created function. 12246 * 12247 * @static 12248 * @memberOf _ 12249 * @since 3.0.0 12250 * @category Function 12251 * @param {Function} predicate The predicate to negate. 12252 * @returns {Function} Returns the new negated function. 12253 * @example 12254 * 12255 * function isEven(n) { 12256 * return n % 2 == 0; 12257 * } 12258 * 12259 * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); 12260 * // => [1, 3, 5] 12261 */ 12262 function negate(predicate) { 12263 if (typeof predicate != 'function') { 12264 throw new TypeError(FUNC_ERROR_TEXT); 12265 } 12266 return function() { 12267 var args = arguments; 12268 switch (args.length) { 12269 case 0: return !predicate.call(this); 12270 case 1: return !predicate.call(this, args[0]); 12271 case 2: return !predicate.call(this, args[0], args[1]); 12272 case 3: return !predicate.call(this, args[0], args[1], args[2]); 12273 } 12274 return !predicate.apply(this, args); 12275 }; 12276 } 12277 12278 /** 12279 * Creates a function that is restricted to invoking `func` once. Repeat calls 12280 * to the function return the value of the first invocation. The `func` is 12281 * invoked with the `this` binding and arguments of the created function. 12282 * 12283 * @static 12284 * @memberOf _ 12285 * @since 0.1.0 12286 * @category Function 12287 * @param {Function} func The function to restrict. 12288 * @returns {Function} Returns the new restricted function. 12289 * @example 12290 * 12291 * var initialize = _.once(createApplication); 12292 * initialize(); 12293 * initialize(); 12294 * // => `createApplication` is invoked once 12295 */ 12296 function once(func) { 12297 return before(2, func); 12298 } 12299 12300 /** 12301 * Creates a function that invokes `func` with its arguments transformed. 12302 * 12303 * @static 12304 * @since 4.0.0 12305 * @memberOf _ 12306 * @category Function 12307 * @param {Function} func The function to wrap. 12308 * @param {...(Function|Function[])} [transforms=[_.identity]] 12309 * The argument transforms. 12310 * @returns {Function} Returns the new function. 12311 * @example 12312 * 12313 * function doubled(n) { 12314 * return n * 2; 12315 * } 12316 * 12317 * function square(n) { 12318 * return n * n; 12319 * } 12320 * 12321 * var func = _.overArgs(function(x, y) { 12322 * return [x, y]; 12323 * }, [square, doubled]); 12324 * 12325 * func(9, 3); 12326 * // => [81, 6] 12327 * 12328 * func(10, 5); 12329 * // => [100, 10] 12330 */ 12331 var overArgs = castRest(function(func, transforms) { 12332 transforms = (transforms.length == 1 && isArray(transforms[0])) 12333 ? arrayMap(transforms[0], baseUnary(getIteratee())) 12334 : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee())); 12335 12336 var funcsLength = transforms.length; 12337 return baseRest(function(args) { 12338 var index = -1, 12339 length = nativeMin(args.length, funcsLength); 12340 12341 while (++index < length) { 12342 args[index] = transforms[index].call(this, args[index]); 12343 } 12344 return apply(func, this, args); 12345 }); 12346 }); 12347 12348 /** 12349 * Creates a function that invokes `func` with `partials` prepended to the 12350 * arguments it receives. This method is like `_.bind` except it does **not** 12351 * alter the `this` binding. 12352 * 12353 * The `_.partial.placeholder` value, which defaults to `_` in monolithic 12354 * builds, may be used as a placeholder for partially applied arguments. 12355 * 12356 * **Note:** This method doesn't set the "length" property of partially 12357 * applied functions. 12358 * 12359 * @static 12360 * @memberOf _ 12361 * @since 0.2.0 12362 * @category Function 12363 * @param {Function} func The function to partially apply arguments to. 12364 * @param {...*} [partials] The arguments to be partially applied. 12365 * @returns {Function} Returns the new partially applied function. 12366 * @example 12367 * 12368 * function greet(greeting, name) { 12369 * return greeting + ' ' + name; 12370 * } 12371 * 12372 * var sayHelloTo = _.partial(greet, 'hello'); 12373 * sayHelloTo('fred'); 12374 * // => 'hello fred' 12375 * 12376 * // Partially applied with placeholders. 12377 * var greetFred = _.partial(greet, _, 'fred'); 12378 * greetFred('hi'); 12379 * // => 'hi fred' 12380 */ 12381 var partial = baseRest(function(func, partials) { 12382 var holders = replaceHolders(partials, getHolder(partial)); 12383 return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders); 12384 }); 12385 12386 /** 12387 * This method is like `_.partial` except that partially applied arguments 12388 * are appended to the arguments it receives. 12389 * 12390 * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic 12391 * builds, may be used as a placeholder for partially applied arguments. 12392 * 12393 * **Note:** This method doesn't set the "length" property of partially 12394 * applied functions. 12395 * 12396 * @static 12397 * @memberOf _ 12398 * @since 1.0.0 12399 * @category Function 12400 * @param {Function} func The function to partially apply arguments to. 12401 * @param {...*} [partials] The arguments to be partially applied. 12402 * @returns {Function} Returns the new partially applied function. 12403 * @example 12404 * 12405 * function greet(greeting, name) { 12406 * return greeting + ' ' + name; 12407 * } 12408 * 12409 * var greetFred = _.partialRight(greet, 'fred'); 12410 * greetFred('hi'); 12411 * // => 'hi fred' 12412 * 12413 * // Partially applied with placeholders. 12414 * var sayHelloTo = _.partialRight(greet, 'hello', _); 12415 * sayHelloTo('fred'); 12416 * // => 'hello fred' 12417 */ 12418 var partialRight = baseRest(function(func, partials) { 12419 var holders = replaceHolders(partials, getHolder(partialRight)); 12420 return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders); 12421 }); 12422 12423 /** 12424 * Creates a function that invokes `func` with arguments arranged according 12425 * to the specified `indexes` where the argument value at the first index is 12426 * provided as the first argument, the argument value at the second index is 12427 * provided as the second argument, and so on. 12428 * 12429 * @static 12430 * @memberOf _ 12431 * @since 3.0.0 12432 * @category Function 12433 * @param {Function} func The function to rearrange arguments for. 12434 * @param {...(number|number[])} indexes The arranged argument indexes. 12435 * @returns {Function} Returns the new function. 12436 * @example 12437 * 12438 * var rearged = _.rearg(function(a, b, c) { 12439 * return [a, b, c]; 12440 * }, [2, 0, 1]); 12441 * 12442 * rearged('b', 'c', 'a') 12443 * // => ['a', 'b', 'c'] 12444 */ 12445 var rearg = flatRest(function(func, indexes) { 12446 return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes); 12447 }); 12448 12449 /** 12450 * Creates a function that invokes `func` with the `this` binding of the 12451 * created function and arguments from `start` and beyond provided as 12452 * an array. 12453 * 12454 * **Note:** This method is based on the 12455 * [rest parameter](https://mdn.io/rest_parameters). 12456 * 12457 * @static 12458 * @memberOf _ 12459 * @since 4.0.0 12460 * @category Function 12461 * @param {Function} func The function to apply a rest parameter to. 12462 * @param {number} [start=func.length-1] The start position of the rest parameter. 12463 * @returns {Function} Returns the new function. 12464 * @example 12465 * 12466 * var say = _.rest(function(what, names) { 12467 * return what + ' ' + _.initial(names).join(', ') + 12468 * (_.size(names) > 1 ? ', & ' : '') + _.last(names); 12469 * }); 12470 * 12471 * say('hello', 'fred', 'barney', 'pebbles'); 12472 * // => 'hello fred, barney, & pebbles' 12473 */ 12474 function rest(func, start) { 12475 if (typeof func != 'function') { 12476 throw new TypeError(FUNC_ERROR_TEXT); 12477 } 12478 start = start === undefined ? start : toInteger(start); 12479 return baseRest(func, start); 12480 } 12481 12482 /** 12483 * Creates a function that invokes `func` with the `this` binding of the 12484 * create function and an array of arguments much like 12485 * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply). 12486 * 12487 * **Note:** This method is based on the 12488 * [spread operator](https://mdn.io/spread_operator). 12489 * 12490 * @static 12491 * @memberOf _ 12492 * @since 3.2.0 12493 * @category Function 12494 * @param {Function} func The function to spread arguments over. 12495 * @param {number} [start=0] The start position of the spread. 12496 * @returns {Function} Returns the new function. 12497 * @example 12498 * 12499 * var say = _.spread(function(who, what) { 12500 * return who + ' says ' + what; 12501 * }); 12502 * 12503 * say(['fred', 'hello']); 12504 * // => 'fred says hello' 12505 * 12506 * var numbers = Promise.all([ 12507 * Promise.resolve(40), 12508 * Promise.resolve(36) 12509 * ]); 12510 * 12511 * numbers.then(_.spread(function(x, y) { 12512 * return x + y; 12513 * })); 12514 * // => a Promise of 76 12515 */ 12516 function spread(func, start) { 12517 if (typeof func != 'function') { 12518 throw new TypeError(FUNC_ERROR_TEXT); 12519 } 12520 start = start == null ? 0 : nativeMax(toInteger(start), 0); 12521 return baseRest(function(args) { 12522 var array = args[start], 12523 otherArgs = castSlice(args, 0, start); 12524 12525 if (array) { 12526 arrayPush(otherArgs, array); 12527 } 12528 return apply(func, this, otherArgs); 12529 }); 12530 } 12531 12532 /** 12533 * Creates a throttled function that only invokes `func` at most once per 12534 * every `wait` milliseconds. The throttled function comes with a `cancel` 12535 * method to cancel delayed `func` invocations and a `flush` method to 12536 * immediately invoke them. Provide `options` to indicate whether `func` 12537 * should be invoked on the leading and/or trailing edge of the `wait` 12538 * timeout. The `func` is invoked with the last arguments provided to the 12539 * throttled function. Subsequent calls to the throttled function return the 12540 * result of the last `func` invocation. 12541 * 12542 * **Note:** If `leading` and `trailing` options are `true`, `func` is 12543 * invoked on the trailing edge of the timeout only if the throttled function 12544 * is invoked more than once during the `wait` timeout. 12545 * 12546 * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred 12547 * until to the next tick, similar to `setTimeout` with a timeout of `0`. 12548 * 12549 * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) 12550 * for details over the differences between `_.throttle` and `_.debounce`. 12551 * 12552 * @static 12553 * @memberOf _ 12554 * @since 0.1.0 12555 * @category Function 12556 * @param {Function} func The function to throttle. 12557 * @param {number} [wait=0] The number of milliseconds to throttle invocations to. 12558 * @param {Object} [options={}] The options object. 12559 * @param {boolean} [options.leading=true] 12560 * Specify invoking on the leading edge of the timeout. 12561 * @param {boolean} [options.trailing=true] 12562 * Specify invoking on the trailing edge of the timeout. 12563 * @returns {Function} Returns the new throttled function. 12564 * @example 12565 * 12566 * // Avoid excessively updating the position while scrolling. 12567 * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); 12568 * 12569 * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes. 12570 * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); 12571 * jQuery(element).on('click', throttled); 12572 * 12573 * // Cancel the trailing throttled invocation. 12574 * jQuery(window).on('popstate', throttled.cancel); 12575 */ 12576 function throttle(func, wait, options) { 12577 var leading = true, 12578 trailing = true; 12579 12580 if (typeof func != 'function') { 12581 throw new TypeError(FUNC_ERROR_TEXT); 12582 } 12583 if (isObject(options)) { 12584 leading = 'leading' in options ? !!options.leading : leading; 12585 trailing = 'trailing' in options ? !!options.trailing : trailing; 12586 } 12587 return debounce(func, wait, { 12588 'leading': leading, 12589 'maxWait': wait, 12590 'trailing': trailing 12591 }); 12592 } 12593 12594 /** 12595 * Creates a function that accepts up to one argument, ignoring any 12596 * additional arguments. 12597 * 12598 * @static 12599 * @memberOf _ 12600 * @since 4.0.0 12601 * @category Function 12602 * @param {Function} func The function to cap arguments for. 12603 * @returns {Function} Returns the new capped function. 12604 * @example 12605 * 12606 * _.map(['6', '8', '10'], _.unary(parseInt)); 12607 * // => [6, 8, 10] 12608 */ 12609 function unary(func) { 12610 return ary(func, 1); 12611 } 12612 12613 /** 12614 * Creates a function that provides `value` to `wrapper` as its first 12615 * argument. Any additional arguments provided to the function are appended 12616 * to those provided to the `wrapper`. The wrapper is invoked with the `this` 12617 * binding of the created function. 12618 * 12619 * @static 12620 * @memberOf _ 12621 * @since 0.1.0 12622 * @category Function 12623 * @param {*} value The value to wrap. 12624 * @param {Function} [wrapper=identity] The wrapper function. 12625 * @returns {Function} Returns the new function. 12626 * @example 12627 * 12628 * var p = _.wrap(_.escape, function(func, text) { 12629 * return '<p>' + func(text) + '</p>'; 12630 * }); 12631 * 12632 * p('fred, barney, & pebbles'); 12633 * // => '<p>fred, barney, & pebbles</p>' 12634 */ 12635 function wrap(value, wrapper) { 12636 return partial(castFunction(wrapper), value); 12637 } 12638 12639 /*------------------------------------------------------------------------*/ 12640 12641 /** 12642 * Casts `value` as an array if it's not one. 12643 * 12644 * @static 12645 * @memberOf _ 12646 * @since 4.4.0 12647 * @category Lang 12648 * @param {*} value The value to inspect. 12649 * @returns {Array} Returns the cast array. 12650 * @example 12651 * 12652 * _.castArray(1); 12653 * // => [1] 12654 * 12655 * _.castArray({ 'a': 1 }); 12656 * // => [{ 'a': 1 }] 12657 * 12658 * _.castArray('abc'); 12659 * // => ['abc'] 12660 * 12661 * _.castArray(null); 12662 * // => [null] 12663 * 12664 * _.castArray(undefined); 12665 * // => [undefined] 12666 * 12667 * _.castArray(); 12668 * // => [] 12669 * 12670 * var array = [1, 2, 3]; 12671 * console.log(_.castArray(array) === array); 12672 * // => true 12673 */ 12674 function castArray() { 12675 if (!arguments.length) { 12676 return []; 12677 } 12678 var value = arguments[0]; 12679 return isArray(value) ? value : [value]; 12680 } 12681 12682 /** 12683 * Creates a shallow clone of `value`. 12684 * 12685 * **Note:** This method is loosely based on the 12686 * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) 12687 * and supports cloning arrays, array buffers, booleans, date objects, maps, 12688 * numbers, `Object` objects, regexes, sets, strings, symbols, and typed 12689 * arrays. The own enumerable properties of `arguments` objects are cloned 12690 * as plain objects. An empty object is returned for uncloneable values such 12691 * as error objects, functions, DOM nodes, and WeakMaps. 12692 * 12693 * @static 12694 * @memberOf _ 12695 * @since 0.1.0 12696 * @category Lang 12697 * @param {*} value The value to clone. 12698 * @returns {*} Returns the cloned value. 12699 * @see _.cloneDeep 12700 * @example 12701 * 12702 * var objects = [{ 'a': 1 }, { 'b': 2 }]; 12703 * 12704 * var shallow = _.clone(objects); 12705 * console.log(shallow[0] === objects[0]); 12706 * // => true 12707 */ 12708 function clone(value) { 12709 return baseClone(value, CLONE_SYMBOLS_FLAG); 12710 } 12711 12712 /** 12713 * This method is like `_.clone` except that it accepts `customizer` which 12714 * is invoked to produce the cloned value. If `customizer` returns `undefined`, 12715 * cloning is handled by the method instead. The `customizer` is invoked with 12716 * up to four arguments; (value [, index|key, object, stack]). 12717 * 12718 * @static 12719 * @memberOf _ 12720 * @since 4.0.0 12721 * @category Lang 12722 * @param {*} value The value to clone. 12723 * @param {Function} [customizer] The function to customize cloning. 12724 * @returns {*} Returns the cloned value. 12725 * @see _.cloneDeepWith 12726 * @example 12727 * 12728 * function customizer(value) { 12729 * if (_.isElement(value)) { 12730 * return value.cloneNode(false); 12731 * } 12732 * } 12733 * 12734 * var el = _.cloneWith(document.body, customizer); 12735 * 12736 * console.log(el === document.body); 12737 * // => false 12738 * console.log(el.nodeName); 12739 * // => 'BODY' 12740 * console.log(el.childNodes.length); 12741 * // => 0 12742 */ 12743 function cloneWith(value, customizer) { 12744 customizer = typeof customizer == 'function' ? customizer : undefined; 12745 return baseClone(value, CLONE_SYMBOLS_FLAG, customizer); 12746 } 12747 12748 /** 12749 * This method is like `_.clone` except that it recursively clones `value`. 12750 * 12751 * @static 12752 * @memberOf _ 12753 * @since 1.0.0 12754 * @category Lang 12755 * @param {*} value The value to recursively clone. 12756 * @returns {*} Returns the deep cloned value. 12757 * @see _.clone 12758 * @example 12759 * 12760 * var objects = [{ 'a': 1 }, { 'b': 2 }]; 12761 * 12762 * var deep = _.cloneDeep(objects); 12763 * console.log(deep[0] === objects[0]); 12764 * // => false 12765 */ 12766 function cloneDeep(value) { 12767 return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG); 12768 } 12769 12770 /** 12771 * This method is like `_.cloneWith` except that it recursively clones `value`. 12772 * 12773 * @static 12774 * @memberOf _ 12775 * @since 4.0.0 12776 * @category Lang 12777 * @param {*} value The value to recursively clone. 12778 * @param {Function} [customizer] The function to customize cloning. 12779 * @returns {*} Returns the deep cloned value. 12780 * @see _.cloneWith 12781 * @example 12782 * 12783 * function customizer(value) { 12784 * if (_.isElement(value)) { 12785 * return value.cloneNode(true); 12786 * } 12787 * } 12788 * 12789 * var el = _.cloneDeepWith(document.body, customizer); 12790 * 12791 * console.log(el === document.body); 12792 * // => false 12793 * console.log(el.nodeName); 12794 * // => 'BODY' 12795 * console.log(el.childNodes.length); 12796 * // => 20 12797 */ 12798 function cloneDeepWith(value, customizer) { 12799 customizer = typeof customizer == 'function' ? customizer : undefined; 12800 return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer); 12801 } 12802 12803 /** 12804 * Checks if `object` conforms to `source` by invoking the predicate 12805 * properties of `source` with the corresponding property values of `object`. 12806 * 12807 * **Note:** This method is equivalent to `_.conforms` when `source` is 12808 * partially applied. 12809 * 12810 * @static 12811 * @memberOf _ 12812 * @since 4.14.0 12813 * @category Lang 12814 * @param {Object} object The object to inspect. 12815 * @param {Object} source The object of property predicates to conform to. 12816 * @returns {boolean} Returns `true` if `object` conforms, else `false`. 12817 * @example 12818 * 12819 * var object = { 'a': 1, 'b': 2 }; 12820 * 12821 * _.conformsTo(object, { 'b': function(n) { return n > 1; } }); 12822 * // => true 12823 * 12824 * _.conformsTo(object, { 'b': function(n) { return n > 2; } }); 12825 * // => false 12826 */ 12827 function conformsTo(object, source) { 12828 return source == null || baseConformsTo(object, source, keys(source)); 12829 } 12830 12831 /** 12832 * Performs a 12833 * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) 12834 * comparison between two values to determine if they are equivalent. 12835 * 12836 * @static 12837 * @memberOf _ 12838 * @since 4.0.0 12839 * @category Lang 12840 * @param {*} value The value to compare. 12841 * @param {*} other The other value to compare. 12842 * @returns {boolean} Returns `true` if the values are equivalent, else `false`. 12843 * @example 12844 * 12845 * var object = { 'a': 1 }; 12846 * var other = { 'a': 1 }; 12847 * 12848 * _.eq(object, object); 12849 * // => true 12850 * 12851 * _.eq(object, other); 12852 * // => false 12853 * 12854 * _.eq('a', 'a'); 12855 * // => true 12856 * 12857 * _.eq('a', Object('a')); 12858 * // => false 12859 * 12860 * _.eq(NaN, NaN); 12861 * // => true 12862 */ 12863 function eq(value, other) { 12864 return value === other || (value !== value && other !== other); 12865 } 12866 12867 /** 12868 * Checks if `value` is greater than `other`. 12869 * 12870 * @static 12871 * @memberOf _ 12872 * @since 3.9.0 12873 * @category Lang 12874 * @param {*} value The value to compare. 12875 * @param {*} other The other value to compare. 12876 * @returns {boolean} Returns `true` if `value` is greater than `other`, 12877 * else `false`. 12878 * @see _.lt 12879 * @example 12880 * 12881 * _.gt(3, 1); 12882 * // => true 12883 * 12884 * _.gt(3, 3); 12885 * // => false 12886 * 12887 * _.gt(1, 3); 12888 * // => false 12889 */ 12890 var gt = createRelationalOperation(baseGt); 12891 12892 /** 12893 * Checks if `value` is greater than or equal to `other`. 12894 * 12895 * @static 12896 * @memberOf _ 12897 * @since 3.9.0 12898 * @category Lang 12899 * @param {*} value The value to compare. 12900 * @param {*} other The other value to compare. 12901 * @returns {boolean} Returns `true` if `value` is greater than or equal to 12902 * `other`, else `false`. 12903 * @see _.lte 12904 * @example 12905 * 12906 * _.gte(3, 1); 12907 * // => true 12908 * 12909 * _.gte(3, 3); 12910 * // => true 12911 * 12912 * _.gte(1, 3); 12913 * // => false 12914 */ 12915 var gte = createRelationalOperation(function(value, other) { 12916 return value >= other; 12917 }); 12918 12919 /** 12920 * Checks if `value` is likely an `arguments` object. 12921 * 12922 * @static 12923 * @memberOf _ 12924 * @since 0.1.0 12925 * @category Lang 12926 * @param {*} value The value to check. 12927 * @returns {boolean} Returns `true` if `value` is an `arguments` object, 12928 * else `false`. 12929 * @example 12930 * 12931 * _.isArguments(function() { return arguments; }()); 12932 * // => true 12933 * 12934 * _.isArguments([1, 2, 3]); 12935 * // => false 12936 */ 12937 var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { 12938 return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && 12939 !propertyIsEnumerable.call(value, 'callee'); 12940 }; 12941 12942 /** 12943 * Checks if `value` is classified as an `Array` object. 12944 * 12945 * @static 12946 * @memberOf _ 12947 * @since 0.1.0 12948 * @category Lang 12949 * @param {*} value The value to check. 12950 * @returns {boolean} Returns `true` if `value` is an array, else `false`. 12951 * @example 12952 * 12953 * _.isArray([1, 2, 3]); 12954 * // => true 12955 * 12956 * _.isArray(document.body.children); 12957 * // => false 12958 * 12959 * _.isArray('abc'); 12960 * // => false 12961 * 12962 * _.isArray(_.noop); 12963 * // => false 12964 */ 12965 var isArray = Array.isArray; 12966 12967 /** 12968 * Checks if `value` is classified as an `ArrayBuffer` object. 12969 * 12970 * @static 12971 * @memberOf _ 12972 * @since 4.3.0 12973 * @category Lang 12974 * @param {*} value The value to check. 12975 * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. 12976 * @example 12977 * 12978 * _.isArrayBuffer(new ArrayBuffer(2)); 12979 * // => true 12980 * 12981 * _.isArrayBuffer(new Array(2)); 12982 * // => false 12983 */ 12984 var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer; 12985 12986 /** 12987 * Checks if `value` is array-like. A value is considered array-like if it's 12988 * not a function and has a `value.length` that's an integer greater than or 12989 * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. 12990 * 12991 * @static 12992 * @memberOf _ 12993 * @since 4.0.0 12994 * @category Lang 12995 * @param {*} value The value to check. 12996 * @returns {boolean} Returns `true` if `value` is array-like, else `false`. 12997 * @example 12998 * 12999 * _.isArrayLike([1, 2, 3]); 13000 * // => true 13001 * 13002 * _.isArrayLike(document.body.children); 13003 * // => true 13004 * 13005 * _.isArrayLike('abc'); 13006 * // => true 13007 * 13008 * _.isArrayLike(_.noop); 13009 * // => false 13010 */ 13011 function isArrayLike(value) { 13012 return value != null && isLength(value.length) && !isFunction(value); 13013 } 13014 13015 /** 13016 * This method is like `_.isArrayLike` except that it also checks if `value` 13017 * is an object. 13018 * 13019 * @static 13020 * @memberOf _ 13021 * @since 4.0.0 13022 * @category Lang 13023 * @param {*} value The value to check. 13024 * @returns {boolean} Returns `true` if `value` is an array-like object, 13025 * else `false`. 13026 * @example 13027 * 13028 * _.isArrayLikeObject([1, 2, 3]); 13029 * // => true 13030 * 13031 * _.isArrayLikeObject(document.body.children); 13032 * // => true 13033 * 13034 * _.isArrayLikeObject('abc'); 13035 * // => false 13036 * 13037 * _.isArrayLikeObject(_.noop); 13038 * // => false 13039 */ 13040 function isArrayLikeObject(value) { 13041 return isObjectLike(value) && isArrayLike(value); 13042 } 13043 13044 /** 13045 * Checks if `value` is classified as a boolean primitive or object. 13046 * 13047 * @static 13048 * @memberOf _ 13049 * @since 0.1.0 13050 * @category Lang 13051 * @param {*} value The value to check. 13052 * @returns {boolean} Returns `true` if `value` is a boolean, else `false`. 13053 * @example 13054 * 13055 * _.isBoolean(false); 13056 * // => true 13057 * 13058 * _.isBoolean(null); 13059 * // => false 13060 */ 13061 function isBoolean(value) { 13062 return value === true || value === false || 13063 (isObjectLike(value) && baseGetTag(value) == boolTag); 13064 } 13065 13066 /** 13067 * Checks if `value` is a buffer. 13068 * 13069 * @static 13070 * @memberOf _ 13071 * @since 4.3.0 13072 * @category Lang 13073 * @param {*} value The value to check. 13074 * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. 13075 * @example 13076 * 13077 * _.isBuffer(new Buffer(2)); 13078 * // => true 13079 * 13080 * _.isBuffer(new Uint8Array(2)); 13081 * // => false 13082 */ 13083 var isBuffer = nativeIsBuffer || stubFalse; 13084 13085 /** 13086 * Checks if `value` is classified as a `Date` object. 13087 * 13088 * @static 13089 * @memberOf _ 13090 * @since 0.1.0 13091 * @category Lang 13092 * @param {*} value The value to check. 13093 * @returns {boolean} Returns `true` if `value` is a date object, else `false`. 13094 * @example 13095 * 13096 * _.isDate(new Date); 13097 * // => true 13098 * 13099 * _.isDate('Mon April 23 2012'); 13100 * // => false 13101 */ 13102 var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate; 13103 13104 /** 13105 * Checks if `value` is likely a DOM element. 13106 * 13107 * @static 13108 * @memberOf _ 13109 * @since 0.1.0 13110 * @category Lang 13111 * @param {*} value The value to check. 13112 * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. 13113 * @example 13114 * 13115 * _.isElement(document.body); 13116 * // => true 13117 * 13118 * _.isElement('<body>'); 13119 * // => false 13120 */ 13121 function isElement(value) { 13122 return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value); 13123 } 13124 13125 /** 13126 * Checks if `value` is an empty object, collection, map, or set. 13127 * 13128 * Objects are considered empty if they have no own enumerable string keyed 13129 * properties. 13130 * 13131 * Array-like values such as `arguments` objects, arrays, buffers, strings, or 13132 * jQuery-like collections are considered empty if they have a `length` of `0`. 13133 * Similarly, maps and sets are considered empty if they have a `size` of `0`. 13134 * 13135 * @static 13136 * @memberOf _ 13137 * @since 0.1.0 13138 * @category Lang 13139 * @param {*} value The value to check. 13140 * @returns {boolean} Returns `true` if `value` is empty, else `false`. 13141 * @example 13142 * 13143 * _.isEmpty(null); 13144 * // => true 13145 * 13146 * _.isEmpty(true); 13147 * // => true 13148 * 13149 * _.isEmpty(1); 13150 * // => true 13151 * 13152 * _.isEmpty([1, 2, 3]); 13153 * // => false 13154 * 13155 * _.isEmpty({ 'a': 1 }); 13156 * // => false 13157 */ 13158 function isEmpty(value) { 13159 if (value == null) { 13160 return true; 13161 } 13162 if (isArrayLike(value) && 13163 (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' || 13164 isBuffer(value) || isTypedArray(value) || isArguments(value))) { 13165 return !value.length; 13166 } 13167 var tag = getTag(value); 13168 if (tag == mapTag || tag == setTag) { 13169 return !value.size; 13170 } 13171 if (isPrototype(value)) { 13172 return !baseKeys(value).length; 13173 } 13174 for (var key in value) { 13175 if (hasOwnProperty.call(value, key)) { 13176 return false; 13177 } 13178 } 13179 return true; 13180 } 13181 13182 /** 13183 * Performs a deep comparison between two values to determine if they are 13184 * equivalent. 13185 * 13186 * **Note:** This method supports comparing arrays, array buffers, booleans, 13187 * date objects, error objects, maps, numbers, `Object` objects, regexes, 13188 * sets, strings, symbols, and typed arrays. `Object` objects are compared 13189 * by their own, not inherited, enumerable properties. Functions and DOM 13190 * nodes are compared by strict equality, i.e. `===`. 13191 * 13192 * @static 13193 * @memberOf _ 13194 * @since 0.1.0 13195 * @category Lang 13196 * @param {*} value The value to compare. 13197 * @param {*} other The other value to compare. 13198 * @returns {boolean} Returns `true` if the values are equivalent, else `false`. 13199 * @example 13200 * 13201 * var object = { 'a': 1 }; 13202 * var other = { 'a': 1 }; 13203 * 13204 * _.isEqual(object, other); 13205 * // => true 13206 * 13207 * object === other; 13208 * // => false 13209 */ 13210 function isEqual(value, other) { 13211 return baseIsEqual(value, other); 13212 } 13213 13214 /** 13215 * This method is like `_.isEqual` except that it accepts `customizer` which 13216 * is invoked to compare values. If `customizer` returns `undefined`, comparisons 13217 * are handled by the method instead. The `customizer` is invoked with up to 13218 * six arguments: (objValue, othValue [, index|key, object, other, stack]). 13219 * 13220 * @static 13221 * @memberOf _ 13222 * @since 4.0.0 13223 * @category Lang 13224 * @param {*} value The value to compare. 13225 * @param {*} other The other value to compare. 13226 * @param {Function} [customizer] The function to customize comparisons. 13227 * @returns {boolean} Returns `true` if the values are equivalent, else `false`. 13228 * @example 13229 * 13230 * function isGreeting(value) { 13231 * return /^h(?:i|ello)$/.test(value); 13232 * } 13233 * 13234 * function customizer(objValue, othValue) { 13235 * if (isGreeting(objValue) && isGreeting(othValue)) { 13236 * return true; 13237 * } 13238 * } 13239 * 13240 * var array = ['hello', 'goodbye']; 13241 * var other = ['hi', 'goodbye']; 13242 * 13243 * _.isEqualWith(array, other, customizer); 13244 * // => true 13245 */ 13246 function isEqualWith(value, other, customizer) { 13247 customizer = typeof customizer == 'function' ? customizer : undefined; 13248 var result = customizer ? customizer(value, other) : undefined; 13249 return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result; 13250 } 13251 13252 /** 13253 * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, 13254 * `SyntaxError`, `TypeError`, or `URIError` object. 13255 * 13256 * @static 13257 * @memberOf _ 13258 * @since 3.0.0 13259 * @category Lang 13260 * @param {*} value The value to check. 13261 * @returns {boolean} Returns `true` if `value` is an error object, else `false`. 13262 * @example 13263 * 13264 * _.isError(new Error); 13265 * // => true 13266 * 13267 * _.isError(Error); 13268 * // => false 13269 */ 13270 function isError(value) { 13271 if (!isObjectLike(value)) { 13272 return false;
vendor: 6,607 bytes, lines 13273-13510
13273 } 13274 var tag = baseGetTag(value); 13275 return tag == errorTag || tag == domExcTag || 13276 (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value)); 13277 } 13278 13279 /** 13280 * Checks if `value` is a finite primitive number. 13281 * 13282 * **Note:** This method is based on 13283 * [`Number.isFinite`](https://mdn.io/Number/isFinite). 13284 * 13285 * @static 13286 * @memberOf _ 13287 * @since 0.1.0 13288 * @category Lang 13289 * @param {*} value The value to check. 13290 * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. 13291 * @example 13292 * 13293 * _.isFinite(3); 13294 * // => true 13295 * 13296 * _.isFinite(Number.MIN_VALUE); 13297 * // => true 13298 * 13299 * _.isFinite(Infinity); 13300 * // => false 13301 * 13302 * _.isFinite('3'); 13303 * // => false 13304 */ 13305 function isFinite(value) { 13306 return typeof value == 'number' && nativeIsFinite(value); 13307 } 13308 13309 /** 13310 * Checks if `value` is classified as a `Function` object. 13311 * 13312 * @static 13313 * @memberOf _ 13314 * @since 0.1.0 13315 * @category Lang 13316 * @param {*} value The value to check. 13317 * @returns {boolean} Returns `true` if `value` is a function, else `false`. 13318 * @example 13319 * 13320 * _.isFunction(_); 13321 * // => true 13322 * 13323 * _.isFunction(/abc/); 13324 * // => false 13325 */ 13326 function isFunction(value) { 13327 if (!isObject(value)) { 13328 return false; 13329 } 13330 // The use of `Object#toString` avoids issues with the `typeof` operator 13331 // in Safari 9 which returns 'object' for typed arrays and other constructors. 13332 var tag = baseGetTag(value); 13333 return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; 13334 } 13335 13336 /** 13337 * Checks if `value` is an integer. 13338 * 13339 * **Note:** This method is based on 13340 * [`Number.isInteger`](https://mdn.io/Number/isInteger). 13341 * 13342 * @static 13343 * @memberOf _ 13344 * @since 4.0.0 13345 * @category Lang 13346 * @param {*} value The value to check. 13347 * @returns {boolean} Returns `true` if `value` is an integer, else `false`. 13348 * @example 13349 * 13350 * _.isInteger(3); 13351 * // => true 13352 * 13353 * _.isInteger(Number.MIN_VALUE); 13354 * // => false 13355 * 13356 * _.isInteger(Infinity); 13357 * // => false 13358 * 13359 * _.isInteger('3'); 13360 * // => false 13361 */ 13362 function isInteger(value) { 13363 return typeof value == 'number' && value == toInteger(value); 13364 } 13365 13366 /** 13367 * Checks if `value` is a valid array-like length. 13368 * 13369 * **Note:** This method is loosely based on 13370 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). 13371 * 13372 * @static 13373 * @memberOf _ 13374 * @since 4.0.0 13375 * @category Lang 13376 * @param {*} value The value to check. 13377 * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. 13378 * @example 13379 * 13380 * _.isLength(3); 13381 * // => true 13382 * 13383 * _.isLength(Number.MIN_VALUE); 13384 * // => false 13385 * 13386 * _.isLength(Infinity); 13387 * // => false 13388 * 13389 * _.isLength('3'); 13390 * // => false 13391 */ 13392 function isLength(value) { 13393 return typeof value == 'number' && 13394 value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; 13395 } 13396 13397 /** 13398 * Checks if `value` is the 13399 * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) 13400 * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) 13401 * 13402 * @static 13403 * @memberOf _ 13404 * @since 0.1.0 13405 * @category Lang 13406 * @param {*} value The value to check. 13407 * @returns {boolean} Returns `true` if `value` is an object, else `false`. 13408 * @example 13409 * 13410 * _.isObject({}); 13411 * // => true 13412 * 13413 * _.isObject([1, 2, 3]); 13414 * // => true 13415 * 13416 * _.isObject(_.noop); 13417 * // => true 13418 * 13419 * _.isObject(null); 13420 * // => false 13421 */ 13422 function isObject(value) { 13423 var type = typeof value; 13424 return value != null && (type == 'object' || type == 'function'); 13425 } 13426 13427 /** 13428 * Checks if `value` is object-like. A value is object-like if it's not `null` 13429 * and has a `typeof` result of "object". 13430 * 13431 * @static 13432 * @memberOf _ 13433 * @since 4.0.0 13434 * @category Lang 13435 * @param {*} value The value to check. 13436 * @returns {boolean} Returns `true` if `value` is object-like, else `false`. 13437 * @example 13438 * 13439 * _.isObjectLike({}); 13440 * // => true 13441 * 13442 * _.isObjectLike([1, 2, 3]); 13443 * // => true 13444 * 13445 * _.isObjectLike(_.noop); 13446 * // => false 13447 * 13448 * _.isObjectLike(null); 13449 * // => false 13450 */ 13451 function isObjectLike(value) { 13452 return value != null && typeof value == 'object'; 13453 } 13454 13455 /** 13456 * Checks if `value` is classified as a `Map` object. 13457 * 13458 * @static 13459 * @memberOf _ 13460 * @since 4.3.0 13461 * @category Lang 13462 * @param {*} value The value to check. 13463 * @returns {boolean} Returns `true` if `value` is a map, else `false`. 13464 * @example 13465 * 13466 * _.isMap(new Map); 13467 * // => true 13468 * 13469 * _.isMap(new WeakMap); 13470 * // => false 13471 */ 13472 var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap; 13473 13474 /** 13475 * Performs a partial deep comparison between `object` and `source` to 13476 * determine if `object` contains equivalent property values. 13477 * 13478 * **Note:** This method is equivalent to `_.matches` when `source` is 13479 * partially applied. 13480 * 13481 * Partial comparisons will match empty array and empty object `source` 13482 * values against any array or object value, respectively. See `_.isEqual` 13483 * for a list of supported value comparisons. 13484 * 13485 * @static 13486 * @memberOf _ 13487 * @since 3.0.0 13488 * @category Lang 13489 * @param {Object} object The object to inspect. 13490 * @param {Object} source The object of property values to match. 13491 * @returns {boolean} Returns `true` if `object` is a match, else `false`. 13492 * @example 13493 * 13494 * var object = { 'a': 1, 'b': 2 }; 13495 * 13496 * _.isMatch(object, { 'b': 2 }); 13497 * // => true 13498 * 13499 * _.isMatch(object, { 'b': 1 }); 13500 * // => false 13501 */ 13502 function isMatch(object, source) { 13503 return object === source || baseIsMatch(object, source, getMatchData(source)); 13504 } 13505 13506 /** 13507 * This method is like `_.isMatch` except that it accepts `customizer` which 13508 * is invoked to compare values. If `customizer` returns `undefined`, comparisons 13509 * are handled by the method instead. The `customizer` is invoked with five 13510 * arguments: (objValue, srcValue, index|key, object, source).
vendor: 12,241 bytes, lines 13511-13976
13511 * 13512 * @static 13513 * @memberOf _ 13514 * @since 4.0.0 13515 * @category Lang 13516 * @param {Object} object The object to inspect. 13517 * @param {Object} source The object of property values to match. 13518 * @param {Function} [customizer] The function to customize comparisons. 13519 * @returns {boolean} Returns `true` if `object` is a match, else `false`. 13520 * @example 13521 * 13522 * function isGreeting(value) { 13523 * return /^h(?:i|ello)$/.test(value); 13524 * } 13525 * 13526 * function customizer(objValue, srcValue) { 13527 * if (isGreeting(objValue) && isGreeting(srcValue)) { 13528 * return true; 13529 * } 13530 * } 13531 * 13532 * var object = { 'greeting': 'hello' }; 13533 * var source = { 'greeting': 'hi' }; 13534 * 13535 * _.isMatchWith(object, source, customizer); 13536 * // => true 13537 */ 13538 function isMatchWith(object, source, customizer) { 13539 customizer = typeof customizer == 'function' ? customizer : undefined; 13540 return baseIsMatch(object, source, getMatchData(source), customizer); 13541 } 13542 13543 /** 13544 * Checks if `value` is `NaN`. 13545 * 13546 * **Note:** This method is based on 13547 * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as 13548 * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for 13549 * `undefined` and other non-number values. 13550 * 13551 * @static 13552 * @memberOf _ 13553 * @since 0.1.0 13554 * @category Lang 13555 * @param {*} value The value to check. 13556 * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. 13557 * @example 13558 * 13559 * _.isNaN(NaN); 13560 * // => true 13561 * 13562 * _.isNaN(new Number(NaN)); 13563 * // => true 13564 * 13565 * isNaN(undefined); 13566 * // => true 13567 * 13568 * _.isNaN(undefined); 13569 * // => false 13570 */ 13571 function isNaN(value) { 13572 // An `NaN` primitive is the only value that is not equal to itself. 13573 // Perform the `toStringTag` check first to avoid errors with some 13574 // ActiveX objects in IE. 13575 return isNumber(value) && value != +value; 13576 } 13577 13578 /** 13579 * Checks if `value` is a pristine native function. 13580 * 13581 * **Note:** This method can't reliably detect native functions in the presence 13582 * of the core-js package because core-js circumvents this kind of detection. 13583 * Despite multiple requests, the core-js maintainer has made it clear: any 13584 * attempt to fix the detection will be obstructed. As a result, we're left 13585 * with little choice but to throw an error. Unfortunately, this also affects 13586 * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill), 13587 * which rely on core-js. 13588 * 13589 * @static 13590 * @memberOf _ 13591 * @since 3.0.0 13592 * @category Lang 13593 * @param {*} value The value to check. 13594 * @returns {boolean} Returns `true` if `value` is a native function, 13595 * else `false`. 13596 * @example 13597 * 13598 * _.isNative(Array.prototype.push); 13599 * // => true 13600 * 13601 * _.isNative(_); 13602 * // => false 13603 */ 13604 function isNative(value) { 13605 if (isMaskable(value)) { 13606 throw new Error(CORE_ERROR_TEXT); 13607 } 13608 return baseIsNative(value); 13609 } 13610 13611 /** 13612 * Checks if `value` is `null`. 13613 * 13614 * @static 13615 * @memberOf _ 13616 * @since 0.1.0 13617 * @category Lang 13618 * @param {*} value The value to check. 13619 * @returns {boolean} Returns `true` if `value` is `null`, else `false`. 13620 * @example 13621 * 13622 * _.isNull(null); 13623 * // => true 13624 * 13625 * _.isNull(void 0); 13626 * // => false 13627 */ 13628 function isNull(value) { 13629 return value === null; 13630 } 13631 13632 /** 13633 * Checks if `value` is `null` or `undefined`. 13634 * 13635 * @static 13636 * @memberOf _ 13637 * @since 4.0.0 13638 * @category Lang 13639 * @param {*} value The value to check. 13640 * @returns {boolean} Returns `true` if `value` is nullish, else `false`. 13641 * @example 13642 * 13643 * _.isNil(null); 13644 * // => true 13645 * 13646 * _.isNil(void 0); 13647 * // => true 13648 * 13649 * _.isNil(NaN); 13650 * // => false 13651 */ 13652 function isNil(value) { 13653 return value == null; 13654 } 13655 13656 /** 13657 * Checks if `value` is classified as a `Number` primitive or object. 13658 * 13659 * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are 13660 * classified as numbers, use the `_.isFinite` method. 13661 * 13662 * @static 13663 * @memberOf _ 13664 * @since 0.1.0 13665 * @category Lang 13666 * @param {*} value The value to check. 13667 * @returns {boolean} Returns `true` if `value` is a number, else `false`. 13668 * @example 13669 * 13670 * _.isNumber(3); 13671 * // => true 13672 * 13673 * _.isNumber(Number.MIN_VALUE); 13674 * // => true 13675 * 13676 * _.isNumber(Infinity); 13677 * // => true 13678 * 13679 * _.isNumber('3'); 13680 * // => false 13681 */ 13682 function isNumber(value) { 13683 return typeof value == 'number' || 13684 (isObjectLike(value) && baseGetTag(value) == numberTag); 13685 } 13686 13687 /** 13688 * Checks if `value` is a plain object, that is, an object created by the 13689 * `Object` constructor or one with a `[[Prototype]]` of `null`. 13690 * 13691 * @static 13692 * @memberOf _ 13693 * @since 0.8.0 13694 * @category Lang 13695 * @param {*} value The value to check. 13696 * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. 13697 * @example 13698 * 13699 * function Foo() { 13700 * this.a = 1; 13701 * } 13702 * 13703 * _.isPlainObject(new Foo); 13704 * // => false 13705 * 13706 * _.isPlainObject([1, 2, 3]); 13707 * // => false 13708 * 13709 * _.isPlainObject({ 'x': 0, 'y': 0 }); 13710 * // => true 13711 * 13712 * _.isPlainObject(Object.create(null)); 13713 * // => true 13714 */ 13715 function isPlainObject(value) { 13716 if (!isObjectLike(value) || baseGetTag(value) != objectTag) { 13717 return false; 13718 } 13719 var proto = getPrototype(value); 13720 if (proto === null) { 13721 return true; 13722 } 13723 var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; 13724 return typeof Ctor == 'function' && Ctor instanceof Ctor && 13725 funcToString.call(Ctor) == objectCtorString; 13726 } 13727 13728 /** 13729 * Checks if `value` is classified as a `RegExp` object. 13730 * 13731 * @static 13732 * @memberOf _ 13733 * @since 0.1.0 13734 * @category Lang 13735 * @param {*} value The value to check. 13736 * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. 13737 * @example 13738 * 13739 * _.isRegExp(/abc/); 13740 * // => true 13741 * 13742 * _.isRegExp('/abc/'); 13743 * // => false 13744 */ 13745 var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp; 13746 13747 /** 13748 * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754 13749 * double precision number which isn't the result of a rounded unsafe integer. 13750 * 13751 * **Note:** This method is based on 13752 * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger). 13753 * 13754 * @static 13755 * @memberOf _ 13756 * @since 4.0.0 13757 * @category Lang 13758 * @param {*} value The value to check. 13759 * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`. 13760 * @example 13761 * 13762 * _.isSafeInteger(3); 13763 * // => true 13764 * 13765 * _.isSafeInteger(Number.MIN_VALUE); 13766 * // => false 13767 * 13768 * _.isSafeInteger(Infinity); 13769 * // => false 13770 * 13771 * _.isSafeInteger('3'); 13772 * // => false 13773 */ 13774 function isSafeInteger(value) { 13775 return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER; 13776 } 13777 13778 /** 13779 * Checks if `value` is classified as a `Set` object. 13780 * 13781 * @static 13782 * @memberOf _ 13783 * @since 4.3.0 13784 * @category Lang 13785 * @param {*} value The value to check. 13786 * @returns {boolean} Returns `true` if `value` is a set, else `false`. 13787 * @example 13788 * 13789 * _.isSet(new Set); 13790 * // => true 13791 * 13792 * _.isSet(new WeakSet); 13793 * // => false 13794 */ 13795 var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet; 13796 13797 /** 13798 * Checks if `value` is classified as a `String` primitive or object. 13799 * 13800 * @static 13801 * @since 0.1.0 13802 * @memberOf _ 13803 * @category Lang 13804 * @param {*} value The value to check. 13805 * @returns {boolean} Returns `true` if `value` is a string, else `false`. 13806 * @example 13807 * 13808 * _.isString('abc'); 13809 * // => true 13810 * 13811 * _.isString(1); 13812 * // => false 13813 */ 13814 function isString(value) { 13815 return typeof value == 'string' || 13816 (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag); 13817 } 13818 13819 /** 13820 * Checks if `value` is classified as a `Symbol` primitive or object. 13821 * 13822 * @static 13823 * @memberOf _ 13824 * @since 4.0.0 13825 * @category Lang 13826 * @param {*} value The value to check. 13827 * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. 13828 * @example 13829 * 13830 * _.isSymbol(Symbol.iterator); 13831 * // => true 13832 * 13833 * _.isSymbol('abc'); 13834 * // => false 13835 */ 13836 function isSymbol(value) { 13837 return typeof value == 'symbol' || 13838 (isObjectLike(value) && baseGetTag(value) == symbolTag); 13839 } 13840 13841 /** 13842 * Checks if `value` is classified as a typed array. 13843 * 13844 * @static 13845 * @memberOf _ 13846 * @since 3.0.0 13847 * @category Lang 13848 * @param {*} value The value to check. 13849 * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. 13850 * @example 13851 * 13852 * _.isTypedArray(new Uint8Array); 13853 * // => true 13854 * 13855 * _.isTypedArray([]); 13856 * // => false 13857 */ 13858 var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; 13859 13860 /** 13861 * Checks if `value` is `undefined`. 13862 * 13863 * @static 13864 * @since 0.1.0 13865 * @memberOf _ 13866 * @category Lang 13867 * @param {*} value The value to check. 13868 * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. 13869 * @example 13870 * 13871 * _.isUndefined(void 0); 13872 * // => true 13873 * 13874 * _.isUndefined(null); 13875 * // => false 13876 */ 13877 function isUndefined(value) { 13878 return value === undefined; 13879 } 13880 13881 /** 13882 * Checks if `value` is classified as a `WeakMap` object. 13883 * 13884 * @static 13885 * @memberOf _ 13886 * @since 4.3.0 13887 * @category Lang 13888 * @param {*} value The value to check. 13889 * @returns {boolean} Returns `true` if `value` is a weak map, else `false`. 13890 * @example 13891 * 13892 * _.isWeakMap(new WeakMap); 13893 * // => true 13894 * 13895 * _.isWeakMap(new Map); 13896 * // => false 13897 */ 13898 function isWeakMap(value) { 13899 return isObjectLike(value) && getTag(value) == weakMapTag; 13900 } 13901 13902 /** 13903 * Checks if `value` is classified as a `WeakSet` object. 13904 * 13905 * @static 13906 * @memberOf _ 13907 * @since 4.3.0 13908 * @category Lang 13909 * @param {*} value The value to check. 13910 * @returns {boolean} Returns `true` if `value` is a weak set, else `false`. 13911 * @example 13912 * 13913 * _.isWeakSet(new WeakSet); 13914 * // => true 13915 * 13916 * _.isWeakSet(new Set); 13917 * // => false 13918 */ 13919 function isWeakSet(value) { 13920 return isObjectLike(value) && baseGetTag(value) == weakSetTag; 13921 } 13922 13923 /** 13924 * Checks if `value` is less than `other`. 13925 * 13926 * @static 13927 * @memberOf _ 13928 * @since 3.9.0 13929 * @category Lang 13930 * @param {*} value The value to compare. 13931 * @param {*} other The other value to compare. 13932 * @returns {boolean} Returns `true` if `value` is less than `other`, 13933 * else `false`. 13934 * @see _.gt 13935 * @example 13936 * 13937 * _.lt(1, 3); 13938 * // => true 13939 * 13940 * _.lt(3, 3); 13941 * // => false 13942 * 13943 * _.lt(3, 1); 13944 * // => false 13945 */ 13946 var lt = createRelationalOperation(baseLt); 13947 13948 /** 13949 * Checks if `value` is less than or equal to `other`. 13950 * 13951 * @static 13952 * @memberOf _ 13953 * @since 3.9.0 13954 * @category Lang 13955 * @param {*} value The value to compare. 13956 * @param {*} other The other value to compare. 13957 * @returns {boolean} Returns `true` if `value` is less than or equal to 13958 * `other`, else `false`. 13959 * @see _.gte 13960 * @example 13961 * 13962 * _.lte(1, 3); 13963 * // => true 13964 * 13965 * _.lte(3, 3); 13966 * // => true 13967 * 13968 * _.lte(3, 1); 13969 * // => false 13970 */ 13971 var lte = createRelationalOperation(function(value, other) { 13972 return value <= other; 13973 }); 13974 13975 /** 13976 * Converts `value` to an array.
vendor: 11,756 bytes, lines 13977-14406
13977 * 13978 * @static 13979 * @since 0.1.0 13980 * @memberOf _ 13981 * @category Lang 13982 * @param {*} value The value to convert. 13983 * @returns {Array} Returns the converted array. 13984 * @example 13985 * 13986 * _.toArray({ 'a': 1, 'b': 2 }); 13987 * // => [1, 2] 13988 * 13989 * _.toArray('abc'); 13990 * // => ['a', 'b', 'c'] 13991 * 13992 * _.toArray(1); 13993 * // => [] 13994 * 13995 * _.toArray(null); 13996 * // => [] 13997 */ 13998 function toArray(value) { 13999 if (!value) { 14000 return []; 14001 } 14002 if (isArrayLike(value)) { 14003 return isString(value) ? stringToArray(value) : copyArray(value); 14004 } 14005 if (symIterator && value[symIterator]) { 14006 return iteratorToArray(value[symIterator]()); 14007 } 14008 var tag = getTag(value), 14009 func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values); 14010 14011 return func(value); 14012 } 14013 14014 /** 14015 * Converts `value` to a finite number. 14016 * 14017 * @static 14018 * @memberOf _ 14019 * @since 4.12.0 14020 * @category Lang 14021 * @param {*} value The value to convert. 14022 * @returns {number} Returns the converted number. 14023 * @example 14024 * 14025 * _.toFinite(3.2); 14026 * // => 3.2 14027 * 14028 * _.toFinite(Number.MIN_VALUE); 14029 * // => 5e-324 14030 * 14031 * _.toFinite(Infinity); 14032 * // => 1.7976931348623157e+308 14033 * 14034 * _.toFinite('3.2'); 14035 * // => 3.2 14036 */ 14037 function toFinite(value) { 14038 if (!value) { 14039 return value === 0 ? value : 0; 14040 } 14041 value = toNumber(value); 14042 if (value === INFINITY || value === -INFINITY) { 14043 var sign = (value < 0 ? -1 : 1); 14044 return sign * MAX_INTEGER; 14045 } 14046 return value === value ? value : 0; 14047 } 14048 14049 /** 14050 * Converts `value` to an integer. 14051 * 14052 * **Note:** This method is loosely based on 14053 * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). 14054 * 14055 * @static 14056 * @memberOf _ 14057 * @since 4.0.0 14058 * @category Lang 14059 * @param {*} value The value to convert. 14060 * @returns {number} Returns the converted integer. 14061 * @example 14062 * 14063 * _.toInteger(3.2); 14064 * // => 3 14065 * 14066 * _.toInteger(Number.MIN_VALUE); 14067 * // => 0 14068 * 14069 * _.toInteger(Infinity); 14070 * // => 1.7976931348623157e+308 14071 * 14072 * _.toInteger('3.2'); 14073 * // => 3 14074 */ 14075 function toInteger(value) { 14076 var result = toFinite(value), 14077 remainder = result % 1; 14078 14079 return result === result ? (remainder ? result - remainder : result) : 0; 14080 } 14081 14082 /** 14083 * Converts `value` to an integer suitable for use as the length of an 14084 * array-like object. 14085 * 14086 * **Note:** This method is based on 14087 * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). 14088 * 14089 * @static 14090 * @memberOf _ 14091 * @since 4.0.0 14092 * @category Lang 14093 * @param {*} value The value to convert. 14094 * @returns {number} Returns the converted integer. 14095 * @example 14096 * 14097 * _.toLength(3.2); 14098 * // => 3 14099 * 14100 * _.toLength(Number.MIN_VALUE); 14101 * // => 0 14102 * 14103 * _.toLength(Infinity); 14104 * // => 4294967295 14105 * 14106 * _.toLength('3.2'); 14107 * // => 3 14108 */ 14109 function toLength(value) { 14110 return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0; 14111 } 14112 14113 /** 14114 * Converts `value` to a number. 14115 * 14116 * @static 14117 * @memberOf _ 14118 * @since 4.0.0 14119 * @category Lang 14120 * @param {*} value The value to process. 14121 * @returns {number} Returns the number. 14122 * @example 14123 * 14124 * _.toNumber(3.2); 14125 * // => 3.2 14126 * 14127 * _.toNumber(Number.MIN_VALUE); 14128 * // => 5e-324 14129 * 14130 * _.toNumber(Infinity); 14131 * // => Infinity 14132 * 14133 * _.toNumber('3.2'); 14134 * // => 3.2 14135 */ 14136 function toNumber(value) { 14137 if (typeof value == 'number') { 14138 return value; 14139 } 14140 if (isSymbol(value)) { 14141 return NAN; 14142 } 14143 if (isObject(value)) { 14144 var other = typeof value.valueOf == 'function' ? value.valueOf() : value; 14145 value = isObject(other) ? (other + '') : other; 14146 } 14147 if (typeof value != 'string') { 14148 return value === 0 ? value : +value; 14149 } 14150 value = baseTrim(value); 14151 var isBinary = reIsBinary.test(value); 14152 return (isBinary || reIsOctal.test(value)) 14153 ? freeParseInt(value.slice(2), isBinary ? 2 : 8) 14154 : (reIsBadHex.test(value) ? NAN : +value); 14155 } 14156 14157 /** 14158 * Converts `value` to a plain object flattening inherited enumerable string 14159 * keyed properties of `value` to own properties of the plain object. 14160 * 14161 * @static 14162 * @memberOf _ 14163 * @since 3.0.0 14164 * @category Lang 14165 * @param {*} value The value to convert. 14166 * @returns {Object} Returns the converted plain object. 14167 * @example 14168 * 14169 * function Foo() { 14170 * this.b = 2; 14171 * } 14172 * 14173 * Foo.prototype.c = 3; 14174 * 14175 * _.assign({ 'a': 1 }, new Foo); 14176 * // => { 'a': 1, 'b': 2 } 14177 * 14178 * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); 14179 * // => { 'a': 1, 'b': 2, 'c': 3 } 14180 */ 14181 function toPlainObject(value) { 14182 return copyObject(value, keysIn(value)); 14183 } 14184 14185 /** 14186 * Converts `value` to a safe integer. A safe integer can be compared and 14187 * represented correctly. 14188 * 14189 * @static 14190 * @memberOf _ 14191 * @since 4.0.0 14192 * @category Lang 14193 * @param {*} value The value to convert. 14194 * @returns {number} Returns the converted integer. 14195 * @example 14196 * 14197 * _.toSafeInteger(3.2); 14198 * // => 3 14199 * 14200 * _.toSafeInteger(Number.MIN_VALUE); 14201 * // => 0 14202 * 14203 * _.toSafeInteger(Infinity); 14204 * // => 9007199254740991 14205 * 14206 * _.toSafeInteger('3.2'); 14207 * // => 3 14208 */ 14209 function toSafeInteger(value) { 14210 return value 14211 ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) 14212 : (value === 0 ? value : 0); 14213 } 14214 14215 /** 14216 * Converts `value` to a string. An empty string is returned for `null` 14217 * and `undefined` values. The sign of `-0` is preserved. 14218 * 14219 * @static 14220 * @memberOf _ 14221 * @since 4.0.0 14222 * @category Lang 14223 * @param {*} value The value to convert. 14224 * @returns {string} Returns the converted string. 14225 * @example 14226 * 14227 * _.toString(null); 14228 * // => '' 14229 * 14230 * _.toString(-0); 14231 * // => '-0' 14232 * 14233 * _.toString([1, 2, 3]); 14234 * // => '1,2,3' 14235 */ 14236 function toString(value) { 14237 return value == null ? '' : baseToString(value); 14238 } 14239 14240 /*------------------------------------------------------------------------*/ 14241 14242 /** 14243 * Assigns own enumerable string keyed properties of source objects to the 14244 * destination object. Source objects are applied from left to right. 14245 * Subsequent sources overwrite property assignments of previous sources. 14246 * 14247 * **Note:** This method mutates `object` and is loosely based on 14248 * [`Object.assign`](https://mdn.io/Object/assign). 14249 * 14250 * @static 14251 * @memberOf _ 14252 * @since 0.10.0 14253 * @category Object 14254 * @param {Object} object The destination object. 14255 * @param {...Object} [sources] The source objects. 14256 * @returns {Object} Returns `object`. 14257 * @see _.assignIn 14258 * @example 14259 * 14260 * function Foo() { 14261 * this.a = 1; 14262 * } 14263 * 14264 * function Bar() { 14265 * this.c = 3; 14266 * } 14267 * 14268 * Foo.prototype.b = 2; 14269 * Bar.prototype.d = 4; 14270 * 14271 * _.assign({ 'a': 0 }, new Foo, new Bar); 14272 * // => { 'a': 1, 'c': 3 } 14273 */ 14274 var assign = createAssigner(function(object, source) { 14275 if (isPrototype(source) || isArrayLike(source)) { 14276 copyObject(source, keys(source), object); 14277 return; 14278 } 14279 for (var key in source) { 14280 if (hasOwnProperty.call(source, key)) { 14281 assignValue(object, key, source[key]); 14282 } 14283 } 14284 }); 14285 14286 /** 14287 * This method is like `_.assign` except that it iterates over own and 14288 * inherited source properties. 14289 * 14290 * **Note:** This method mutates `object`. 14291 * 14292 * @static 14293 * @memberOf _ 14294 * @since 4.0.0 14295 * @alias extend 14296 * @category Object 14297 * @param {Object} object The destination object. 14298 * @param {...Object} [sources] The source objects. 14299 * @returns {Object} Returns `object`. 14300 * @see _.assign 14301 * @example 14302 * 14303 * function Foo() { 14304 * this.a = 1; 14305 * } 14306 * 14307 * function Bar() { 14308 * this.c = 3; 14309 * } 14310 * 14311 * Foo.prototype.b = 2; 14312 * Bar.prototype.d = 4; 14313 * 14314 * _.assignIn({ 'a': 0 }, new Foo, new Bar); 14315 * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } 14316 */ 14317 var assignIn = createAssigner(function(object, source) { 14318 copyObject(source, keysIn(source), object); 14319 }); 14320 14321 /** 14322 * This method is like `_.assignIn` except that it accepts `customizer` 14323 * which is invoked to produce the assigned values. If `customizer` returns 14324 * `undefined`, assignment is handled by the method instead. The `customizer` 14325 * is invoked with five arguments: (objValue, srcValue, key, object, source). 14326 * 14327 * **Note:** This method mutates `object`. 14328 * 14329 * @static 14330 * @memberOf _ 14331 * @since 4.0.0 14332 * @alias extendWith 14333 * @category Object 14334 * @param {Object} object The destination object. 14335 * @param {...Object} sources The source objects. 14336 * @param {Function} [customizer] The function to customize assigned values. 14337 * @returns {Object} Returns `object`. 14338 * @see _.assignWith 14339 * @example 14340 * 14341 * function customizer(objValue, srcValue) { 14342 * return _.isUndefined(objValue) ? srcValue : objValue; 14343 * } 14344 * 14345 * var defaults = _.partialRight(_.assignInWith, customizer); 14346 * 14347 * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); 14348 * // => { 'a': 1, 'b': 2 } 14349 */ 14350 var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { 14351 copyObject(source, keysIn(source), object, customizer); 14352 }); 14353 14354 /** 14355 * This method is like `_.assign` except that it accepts `customizer` 14356 * which is invoked to produce the assigned values. If `customizer` returns 14357 * `undefined`, assignment is handled by the method instead. The `customizer` 14358 * is invoked with five arguments: (objValue, srcValue, key, object, source). 14359 * 14360 * **Note:** This method mutates `object`. 14361 * 14362 * @static 14363 * @memberOf _ 14364 * @since 4.0.0 14365 * @category Object 14366 * @param {Object} object The destination object. 14367 * @param {...Object} sources The source objects. 14368 * @param {Function} [customizer] The function to customize assigned values. 14369 * @returns {Object} Returns `object`. 14370 * @see _.assignInWith 14371 * @example 14372 * 14373 * function customizer(objValue, srcValue) { 14374 * return _.isUndefined(objValue) ? srcValue : objValue; 14375 * } 14376 * 14377 * var defaults = _.partialRight(_.assignWith, customizer); 14378 * 14379 * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); 14380 * // => { 'a': 1, 'b': 2 } 14381 */ 14382 var assignWith = createAssigner(function(object, source, srcIndex, customizer) { 14383 copyObject(source, keys(source), object, customizer); 14384 }); 14385 14386 /** 14387 * Creates an array of values corresponding to `paths` of `object`. 14388 * 14389 * @static 14390 * @memberOf _ 14391 * @since 1.0.0 14392 * @category Object 14393 * @param {Object} object The object to iterate over. 14394 * @param {...(string|string[])} [paths] The property paths to pick. 14395 * @returns {Array} Returns the picked values. 14396 * @example 14397 * 14398 * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; 14399 * 14400 * _.at(object, ['a[0].b.c', 'a[1]']); 14401 * // => [3, 4] 14402 */ 14403 var at = flatRest(baseAt); 14404 14405 /** 14406 * Creates an object that inherits from the `prototype` object. If a
vendor: 13,619 bytes, lines 14407-14871
14407 * `properties` object is given, its own enumerable string keyed properties 14408 * are assigned to the created object. 14409 * 14410 * @static 14411 * @memberOf _ 14412 * @since 2.3.0 14413 * @category Object 14414 * @param {Object} prototype The object to inherit from. 14415 * @param {Object} [properties] The properties to assign to the object. 14416 * @returns {Object} Returns the new object. 14417 * @example 14418 * 14419 * function Shape() { 14420 * this.x = 0; 14421 * this.y = 0; 14422 * } 14423 * 14424 * function Circle() { 14425 * Shape.call(this); 14426 * } 14427 * 14428 * Circle.prototype = _.create(Shape.prototype, { 14429 * 'constructor': Circle 14430 * }); 14431 * 14432 * var circle = new Circle; 14433 * circle instanceof Circle; 14434 * // => true 14435 * 14436 * circle instanceof Shape; 14437 * // => true 14438 */ 14439 function create(prototype, properties) { 14440 var result = baseCreate(prototype); 14441 return properties == null ? result : baseAssign(result, properties); 14442 } 14443 14444 /** 14445 * Assigns own and inherited enumerable string keyed properties of source 14446 * objects to the destination object for all destination properties that 14447 * resolve to `undefined`. Source objects are applied from left to right. 14448 * Once a property is set, additional values of the same property are ignored. 14449 * 14450 * **Note:** This method mutates `object`. 14451 * 14452 * @static 14453 * @since 0.1.0 14454 * @memberOf _ 14455 * @category Object 14456 * @param {Object} object The destination object. 14457 * @param {...Object} [sources] The source objects. 14458 * @returns {Object} Returns `object`. 14459 * @see _.defaultsDeep 14460 * @example 14461 * 14462 * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); 14463 * // => { 'a': 1, 'b': 2 } 14464 */ 14465 var defaults = baseRest(function(object, sources) { 14466 object = Object(object); 14467 14468 var index = -1; 14469 var length = sources.length; 14470 var guard = length > 2 ? sources[2] : undefined; 14471 14472 if (guard && isIterateeCall(sources[0], sources[1], guard)) { 14473 length = 1; 14474 } 14475 14476 while (++index < length) { 14477 var source = sources[index]; 14478 var props = keysIn(source); 14479 var propsIndex = -1; 14480 var propsLength = props.length; 14481 14482 while (++propsIndex < propsLength) { 14483 var key = props[propsIndex]; 14484 var value = object[key]; 14485 14486 if (value === undefined || 14487 (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) { 14488 object[key] = source[key]; 14489 } 14490 } 14491 } 14492 14493 return object; 14494 }); 14495 14496 /** 14497 * This method is like `_.defaults` except that it recursively assigns 14498 * default properties. 14499 * 14500 * **Note:** This method mutates `object`. 14501 * 14502 * @static 14503 * @memberOf _ 14504 * @since 3.10.0 14505 * @category Object 14506 * @param {Object} object The destination object. 14507 * @param {...Object} [sources] The source objects. 14508 * @returns {Object} Returns `object`. 14509 * @see _.defaults 14510 * @example 14511 * 14512 * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } }); 14513 * // => { 'a': { 'b': 2, 'c': 3 } } 14514 */ 14515 var defaultsDeep = baseRest(function(args) { 14516 args.push(undefined, customDefaultsMerge); 14517 return apply(mergeWith, undefined, args); 14518 }); 14519 14520 /** 14521 * This method is like `_.find` except that it returns the key of the first 14522 * element `predicate` returns truthy for instead of the element itself. 14523 * 14524 * @static 14525 * @memberOf _ 14526 * @since 1.1.0 14527 * @category Object 14528 * @param {Object} object The object to inspect. 14529 * @param {Function} [predicate=_.identity] The function invoked per iteration. 14530 * @returns {string|undefined} Returns the key of the matched element, 14531 * else `undefined`. 14532 * @example 14533 * 14534 * var users = { 14535 * 'barney': { 'age': 36, 'active': true }, 14536 * 'fred': { 'age': 40, 'active': false }, 14537 * 'pebbles': { 'age': 1, 'active': true } 14538 * }; 14539 * 14540 * _.findKey(users, function(o) { return o.age < 40; }); 14541 * // => 'barney' (iteration order is not guaranteed) 14542 * 14543 * // The `_.matches` iteratee shorthand. 14544 * _.findKey(users, { 'age': 1, 'active': true }); 14545 * // => 'pebbles' 14546 * 14547 * // The `_.matchesProperty` iteratee shorthand. 14548 * _.findKey(users, ['active', false]); 14549 * // => 'fred' 14550 * 14551 * // The `_.property` iteratee shorthand. 14552 * _.findKey(users, 'active'); 14553 * // => 'barney' 14554 */ 14555 function findKey(object, predicate) { 14556 return baseFindKey(object, getIteratee(predicate, 3), baseForOwn); 14557 } 14558 14559 /** 14560 * This method is like `_.findKey` except that it iterates over elements of 14561 * a collection in the opposite order. 14562 * 14563 * @static 14564 * @memberOf _ 14565 * @since 2.0.0 14566 * @category Object 14567 * @param {Object} object The object to inspect. 14568 * @param {Function} [predicate=_.identity] The function invoked per iteration. 14569 * @returns {string|undefined} Returns the key of the matched element, 14570 * else `undefined`. 14571 * @example 14572 * 14573 * var users = { 14574 * 'barney': { 'age': 36, 'active': true }, 14575 * 'fred': { 'age': 40, 'active': false }, 14576 * 'pebbles': { 'age': 1, 'active': true } 14577 * }; 14578 * 14579 * _.findLastKey(users, function(o) { return o.age < 40; }); 14580 * // => returns 'pebbles' assuming `_.findKey` returns 'barney' 14581 * 14582 * // The `_.matches` iteratee shorthand. 14583 * _.findLastKey(users, { 'age': 36, 'active': true }); 14584 * // => 'barney' 14585 * 14586 * // The `_.matchesProperty` iteratee shorthand. 14587 * _.findLastKey(users, ['active', false]); 14588 * // => 'fred' 14589 * 14590 * // The `_.property` iteratee shorthand. 14591 * _.findLastKey(users, 'active'); 14592 * // => 'pebbles' 14593 */ 14594 function findLastKey(object, predicate) { 14595 return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight); 14596 } 14597 14598 /** 14599 * Iterates over own and inherited enumerable string keyed properties of an 14600 * object and invokes `iteratee` for each property. The iteratee is invoked 14601 * with three arguments: (value, key, object). Iteratee functions may exit 14602 * iteration early by explicitly returning `false`. 14603 * 14604 * @static 14605 * @memberOf _ 14606 * @since 0.3.0 14607 * @category Object 14608 * @param {Object} object The object to iterate over. 14609 * @param {Function} [iteratee=_.identity] The function invoked per iteration. 14610 * @returns {Object} Returns `object`. 14611 * @see _.forInRight 14612 * @example 14613 * 14614 * function Foo() { 14615 * this.a = 1; 14616 * this.b = 2; 14617 * } 14618 * 14619 * Foo.prototype.c = 3; 14620 * 14621 * _.forIn(new Foo, function(value, key) { 14622 * console.log(key); 14623 * }); 14624 * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed). 14625 */ 14626 function forIn(object, iteratee) { 14627 return object == null 14628 ? object 14629 : baseFor(object, getIteratee(iteratee, 3), keysIn); 14630 } 14631 14632 /** 14633 * This method is like `_.forIn` except that it iterates over properties of 14634 * `object` in the opposite order. 14635 * 14636 * @static 14637 * @memberOf _ 14638 * @since 2.0.0 14639 * @category Object 14640 * @param {Object} object The object to iterate over. 14641 * @param {Function} [iteratee=_.identity] The function invoked per iteration. 14642 * @returns {Object} Returns `object`. 14643 * @see _.forIn 14644 * @example 14645 * 14646 * function Foo() { 14647 * this.a = 1; 14648 * this.b = 2; 14649 * } 14650 * 14651 * Foo.prototype.c = 3; 14652 * 14653 * _.forInRight(new Foo, function(value, key) { 14654 * console.log(key); 14655 * }); 14656 * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'. 14657 */ 14658 function forInRight(object, iteratee) { 14659 return object == null 14660 ? object 14661 : baseForRight(object, getIteratee(iteratee, 3), keysIn); 14662 } 14663 14664 /** 14665 * Iterates over own enumerable string keyed properties of an object and 14666 * invokes `iteratee` for each property. The iteratee is invoked with three 14667 * arguments: (value, key, object). Iteratee functions may exit iteration 14668 * early by explicitly returning `false`. 14669 * 14670 * @static 14671 * @memberOf _ 14672 * @since 0.3.0 14673 * @category Object 14674 * @param {Object} object The object to iterate over. 14675 * @param {Function} [iteratee=_.identity] The function invoked per iteration. 14676 * @returns {Object} Returns `object`. 14677 * @see _.forOwnRight 14678 * @example 14679 * 14680 * function Foo() { 14681 * this.a = 1; 14682 * this.b = 2; 14683 * } 14684 * 14685 * Foo.prototype.c = 3; 14686 * 14687 * _.forOwn(new Foo, function(value, key) { 14688 * console.log(key); 14689 * }); 14690 * // => Logs 'a' then 'b' (iteration order is not guaranteed). 14691 */ 14692 function forOwn(object, iteratee) { 14693 return object && baseForOwn(object, getIteratee(iteratee, 3)); 14694 } 14695 14696 /** 14697 * This method is like `_.forOwn` except that it iterates over properties of 14698 * `object` in the opposite order. 14699 * 14700 * @static 14701 * @memberOf _ 14702 * @since 2.0.0 14703 * @category Object 14704 * @param {Object} object The object to iterate over. 14705 * @param {Function} [iteratee=_.identity] The function invoked per iteration. 14706 * @returns {Object} Returns `object`. 14707 * @see _.forOwn 14708 * @example 14709 * 14710 * function Foo() { 14711 * this.a = 1; 14712 * this.b = 2; 14713 * } 14714 * 14715 * Foo.prototype.c = 3; 14716 * 14717 * _.forOwnRight(new Foo, function(value, key) { 14718 * console.log(key); 14719 * }); 14720 * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'. 14721 */ 14722 function forOwnRight(object, iteratee) { 14723 return object && baseForOwnRight(object, getIteratee(iteratee, 3)); 14724 } 14725 14726 /** 14727 * Creates an array of function property names from own enumerable properties 14728 * of `object`. 14729 * 14730 * @static 14731 * @since 0.1.0 14732 * @memberOf _ 14733 * @category Object 14734 * @param {Object} object The object to inspect. 14735 * @returns {Array} Returns the function names. 14736 * @see _.functionsIn 14737 * @example 14738 * 14739 * function Foo() { 14740 * this.a = _.constant('a'); 14741 * this.b = _.constant('b'); 14742 * } 14743 * 14744 * Foo.prototype.c = _.constant('c'); 14745 * 14746 * _.functions(new Foo); 14747 * // => ['a', 'b'] 14748 */ 14749 function functions(object) { 14750 return object == null ? [] : baseFunctions(object, keys(object)); 14751 } 14752 14753 /** 14754 * Creates an array of function property names from own and inherited 14755 * enumerable properties of `object`. 14756 * 14757 * @static 14758 * @memberOf _ 14759 * @since 4.0.0 14760 * @category Object 14761 * @param {Object} object The object to inspect. 14762 * @returns {Array} Returns the function names. 14763 * @see _.functions 14764 * @example 14765 * 14766 * function Foo() { 14767 * this.a = _.constant('a'); 14768 * this.b = _.constant('b'); 14769 * } 14770 * 14771 * Foo.prototype.c = _.constant('c'); 14772 * 14773 * _.functionsIn(new Foo); 14774 * // => ['a', 'b', 'c'] 14775 */ 14776 function functionsIn(object) { 14777 return object == null ? [] : baseFunctions(object, keysIn(object)); 14778 } 14779 14780 /** 14781 * Gets the value at `path` of `object`. If the resolved value is 14782 * `undefined`, the `defaultValue` is returned in its place. 14783 * 14784 * @static 14785 * @memberOf _ 14786 * @since 3.7.0 14787 * @category Object 14788 * @param {Object} object The object to query. 14789 * @param {Array|string} path The path of the property to get. 14790 * @param {*} [defaultValue] The value returned for `undefined` resolved values. 14791 * @returns {*} Returns the resolved value. 14792 * @example 14793 * 14794 * var object = { 'a': [{ 'b': { 'c': 3 } }] }; 14795 * 14796 * _.get(object, 'a[0].b.c'); 14797 * // => 3 14798 * 14799 * _.get(object, ['a', '0', 'b', 'c']); 14800 * // => 3 14801 * 14802 * _.get(object, 'a.b.c', 'default'); 14803 * // => 'default' 14804 */ 14805 function get(object, path, defaultValue) { 14806 var result = object == null ? undefined : baseGet(object, path); 14807 return result === undefined ? defaultValue : result; 14808 } 14809 14810 /** 14811 * Checks if `path` is a direct property of `object`. 14812 * 14813 * @static 14814 * @since 0.1.0 14815 * @memberOf _ 14816 * @category Object 14817 * @param {Object} object The object to query. 14818 * @param {Array|string} path The path to check. 14819 * @returns {boolean} Returns `true` if `path` exists, else `false`. 14820 * @example 14821 * 14822 * var object = { 'a': { 'b': 2 } }; 14823 * var other = _.create({ 'a': _.create({ 'b': 2 }) }); 14824 * 14825 * _.has(object, 'a'); 14826 * // => true 14827 * 14828 * _.has(object, 'a.b'); 14829 * // => true 14830 * 14831 * _.has(object, ['a', 'b']); 14832 * // => true 14833 * 14834 * _.has(other, 'a'); 14835 * // => false 14836 */ 14837 function has(object, path) { 14838 return object != null && hasPath(object, path, baseHas); 14839 } 14840 14841 /** 14842 * Checks if `path` is a direct or inherited property of `object`. 14843 * 14844 * @static 14845 * @memberOf _ 14846 * @since 4.0.0 14847 * @category Object 14848 * @param {Object} object The object to query. 14849 * @param {Array|string} path The path to check. 14850 * @returns {boolean} Returns `true` if `path` exists, else `false`. 14851 * @example 14852 * 14853 * var object = _.create({ 'a': _.create({ 'b': 2 }) }); 14854 * 14855 * _.hasIn(object, 'a'); 14856 * // => true 14857 * 14858 * _.hasIn(object, 'a.b'); 14859 * // => true 14860 * 14861 * _.hasIn(object, ['a', 'b']); 14862 * // => true 14863 * 14864 * _.hasIn(object, 'b'); 14865 * // => false 14866 */ 14867 function hasIn(object, path) { 14868 return object != null && hasPath(object, path, baseHasIn); 14869 } 14870 14871 /**
vendor: 11,848 bytes, lines 14872-15242
14872 * Creates an object composed of the inverted keys and values of `object`. 14873 * If `object` contains duplicate values, subsequent values overwrite 14874 * property assignments of previous values. 14875 * 14876 * @static 14877 * @memberOf _ 14878 * @since 0.7.0 14879 * @category Object 14880 * @param {Object} object The object to invert. 14881 * @returns {Object} Returns the new inverted object. 14882 * @example 14883 * 14884 * var object = { 'a': 1, 'b': 2, 'c': 1 }; 14885 * 14886 * _.invert(object); 14887 * // => { '1': 'c', '2': 'b' } 14888 */ 14889 var invert = createInverter(function(result, value, key) { 14890 if (value != null && 14891 typeof value.toString != 'function') { 14892 value = nativeObjectToString.call(value); 14893 } 14894 14895 result[value] = key; 14896 }, constant(identity)); 14897 14898 /** 14899 * This method is like `_.invert` except that the inverted object is generated 14900 * from the results of running each element of `object` thru `iteratee`. The 14901 * corresponding inverted value of each inverted key is an array of keys 14902 * responsible for generating the inverted value. The iteratee is invoked 14903 * with one argument: (value). 14904 * 14905 * @static 14906 * @memberOf _ 14907 * @since 4.1.0 14908 * @category Object 14909 * @param {Object} object The object to invert. 14910 * @param {Function} [iteratee=_.identity] The iteratee invoked per element. 14911 * @returns {Object} Returns the new inverted object. 14912 * @example 14913 * 14914 * var object = { 'a': 1, 'b': 2, 'c': 1 }; 14915 * 14916 * _.invertBy(object); 14917 * // => { '1': ['a', 'c'], '2': ['b'] } 14918 * 14919 * _.invertBy(object, function(value) { 14920 * return 'group' + value; 14921 * }); 14922 * // => { 'group1': ['a', 'c'], 'group2': ['b'] } 14923 */ 14924 var invertBy = createInverter(function(result, value, key) { 14925 if (value != null && 14926 typeof value.toString != 'function') { 14927 value = nativeObjectToString.call(value); 14928 } 14929 14930 if (hasOwnProperty.call(result, value)) { 14931 result[value].push(key); 14932 } else { 14933 result[value] = [key]; 14934 } 14935 }, getIteratee); 14936 14937 /** 14938 * Invokes the method at `path` of `object`. 14939 * 14940 * @static 14941 * @memberOf _ 14942 * @since 4.0.0 14943 * @category Object 14944 * @param {Object} object The object to query. 14945 * @param {Array|string} path The path of the method to invoke. 14946 * @param {...*} [args] The arguments to invoke the method with. 14947 * @returns {*} Returns the result of the invoked method. 14948 * @example 14949 * 14950 * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] }; 14951 * 14952 * _.invoke(object, 'a[0].b.c.slice', 1, 3); 14953 * // => [2, 3] 14954 */ 14955 var invoke = baseRest(baseInvoke); 14956 14957 /** 14958 * Creates an array of the own enumerable property names of `object`. 14959 * 14960 * **Note:** Non-object values are coerced to objects. See the 14961 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) 14962 * for more details. 14963 * 14964 * @static 14965 * @since 0.1.0 14966 * @memberOf _ 14967 * @category Object 14968 * @param {Object} object The object to query. 14969 * @returns {Array} Returns the array of property names. 14970 * @example 14971 * 14972 * function Foo() { 14973 * this.a = 1; 14974 * this.b = 2; 14975 * } 14976 * 14977 * Foo.prototype.c = 3; 14978 * 14979 * _.keys(new Foo); 14980 * // => ['a', 'b'] (iteration order is not guaranteed) 14981 * 14982 * _.keys('hi'); 14983 * // => ['0', '1'] 14984 */ 14985 function keys(object) { 14986 return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); 14987 } 14988 14989 /** 14990 * Creates an array of the own and inherited enumerable property names of `object`. 14991 * 14992 * **Note:** Non-object values are coerced to objects. 14993 * 14994 * @static 14995 * @memberOf _ 14996 * @since 3.0.0 14997 * @category Object 14998 * @param {Object} object The object to query. 14999 * @returns {Array} Returns the array of property names. 15000 * @example 15001 * 15002 * function Foo() { 15003 * this.a = 1; 15004 * this.b = 2; 15005 * } 15006 * 15007 * Foo.prototype.c = 3; 15008 * 15009 * _.keysIn(new Foo); 15010 * // => ['a', 'b', 'c'] (iteration order is not guaranteed) 15011 */ 15012 function keysIn(object) { 15013 return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); 15014 } 15015 15016 /** 15017 * The opposite of `_.mapValues`; this method creates an object with the 15018 * same values as `object` and keys generated by running each own enumerable 15019 * string keyed property of `object` thru `iteratee`. The iteratee is invoked 15020 * with three arguments: (value, key, object). 15021 * 15022 * @static 15023 * @memberOf _ 15024 * @since 3.8.0 15025 * @category Object 15026 * @param {Object} object The object to iterate over. 15027 * @param {Function} [iteratee=_.identity] The function invoked per iteration. 15028 * @returns {Object} Returns the new mapped object. 15029 * @see _.mapValues 15030 * @example 15031 * 15032 * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) { 15033 * return key + value; 15034 * }); 15035 * // => { 'a1': 1, 'b2': 2 } 15036 */ 15037 function mapKeys(object, iteratee) { 15038 var result = {}; 15039 iteratee = getIteratee(iteratee, 3); 15040 15041 baseForOwn(object, function(value, key, object) { 15042 baseAssignValue(result, iteratee(value, key, object), value); 15043 }); 15044 return result; 15045 } 15046 15047 /** 15048 * Creates an object with the same keys as `object` and values generated 15049 * by running each own enumerable string keyed property of `object` thru 15050 * `iteratee`. The iteratee is invoked with three arguments: 15051 * (value, key, object). 15052 * 15053 * @static 15054 * @memberOf _ 15055 * @since 2.4.0 15056 * @category Object 15057 * @param {Object} object The object to iterate over. 15058 * @param {Function} [iteratee=_.identity] The function invoked per iteration. 15059 * @returns {Object} Returns the new mapped object. 15060 * @see _.mapKeys 15061 * @example 15062 * 15063 * var users = { 15064 * 'fred': { 'user': 'fred', 'age': 40 }, 15065 * 'pebbles': { 'user': 'pebbles', 'age': 1 } 15066 * }; 15067 * 15068 * _.mapValues(users, function(o) { return o.age; }); 15069 * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) 15070 * 15071 * // The `_.property` iteratee shorthand. 15072 * _.mapValues(users, 'age'); 15073 * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) 15074 */ 15075 function mapValues(object, iteratee) { 15076 var result = {}; 15077 iteratee = getIteratee(iteratee, 3); 15078 15079 baseForOwn(object, function(value, key, object) { 15080 baseAssignValue(result, key, iteratee(value, key, object)); 15081 }); 15082 return result; 15083 } 15084 15085 /** 15086 * This method is like `_.assign` except that it recursively merges own and 15087 * inherited enumerable string keyed properties of source objects into the 15088 * destination object. Source properties that resolve to `undefined` are 15089 * skipped if a destination value exists. Array and plain object properties 15090 * are merged recursively. Other objects and value types are overridden by 15091 * assignment. Source objects are applied from left to right. Subsequent 15092 * sources overwrite property assignments of previous sources. 15093 * 15094 * **Note:** This method mutates `object`. 15095 * 15096 * @static 15097 * @memberOf _ 15098 * @since 0.5.0 15099 * @category Object 15100 * @param {Object} object The destination object. 15101 * @param {...Object} [sources] The source objects. 15102 * @returns {Object} Returns `object`. 15103 * @example 15104 * 15105 * var object = { 15106 * 'a': [{ 'b': 2 }, { 'd': 4 }] 15107 * }; 15108 * 15109 * var other = { 15110 * 'a': [{ 'c': 3 }, { 'e': 5 }] 15111 * }; 15112 * 15113 * _.merge(object, other); 15114 * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } 15115 */ 15116 var merge = createAssigner(function(object, source, srcIndex) { 15117 baseMerge(object, source, srcIndex); 15118 }); 15119 15120 /** 15121 * This method is like `_.merge` except that it accepts `customizer` which 15122 * is invoked to produce the merged values of the destination and source 15123 * properties. If `customizer` returns `undefined`, merging is handled by the 15124 * method instead. The `customizer` is invoked with six arguments: 15125 * (objValue, srcValue, key, object, source, stack). 15126 * 15127 * **Note:** This method mutates `object`. 15128 * 15129 * @static 15130 * @memberOf _ 15131 * @since 4.0.0 15132 * @category Object 15133 * @param {Object} object The destination object. 15134 * @param {...Object} sources The source objects. 15135 * @param {Function} customizer The function to customize assigned values. 15136 * @returns {Object} Returns `object`. 15137 * @example 15138 * 15139 * function customizer(objValue, srcValue) { 15140 * if (_.isArray(objValue)) { 15141 * return objValue.concat(srcValue); 15142 * } 15143 * } 15144 * 15145 * var object = { 'a': [1], 'b': [2] }; 15146 * var other = { 'a': [3], 'b': [4] }; 15147 * 15148 * _.mergeWith(object, other, customizer); 15149 * // => { 'a': [1, 3], 'b': [2, 4] } 15150 */ 15151 var mergeWith = createAssigner(function(object, source, srcIndex, customizer) { 15152 baseMerge(object, source, srcIndex, customizer); 15153 }); 15154 15155 /** 15156 * The opposite of `_.pick`; this method creates an object composed of the 15157 * own and inherited enumerable property paths of `object` that are not omitted. 15158 * 15159 * **Note:** This method is considerably slower than `_.pick`. 15160 * 15161 * @static 15162 * @since 0.1.0 15163 * @memberOf _ 15164 * @category Object 15165 * @param {Object} object The source object. 15166 * @param {...(string|string[])} [paths] The property paths to omit. 15167 * @returns {Object} Returns the new object. 15168 * @example 15169 * 15170 * var object = { 'a': 1, 'b': '2', 'c': 3 }; 15171 * 15172 * _.omit(object, ['a', 'c']); 15173 * // => { 'b': '2' } 15174 */ 15175 var omit = flatRest(function(object, paths) { 15176 var result = {}; 15177 if (object == null) { 15178 return result; 15179 } 15180 var isDeep = false; 15181 paths = arrayMap(paths, function(path) { 15182 path = castPath(path, object); 15183 isDeep || (isDeep = path.length > 1); 15184 return path; 15185 }); 15186 copyObject(object, getAllKeysIn(object), result); 15187 if (isDeep) { 15188 result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone); 15189 } 15190 var length = paths.length; 15191 while (length--) { 15192 baseUnset(result, paths[length]); 15193 } 15194 return result; 15195 }); 15196 15197 /** 15198 * The opposite of `_.pickBy`; this method creates an object composed of 15199 * the own and inherited enumerable string keyed properties of `object` that 15200 * `predicate` doesn't return truthy for. The predicate is invoked with two 15201 * arguments: (value, key). 15202 * 15203 * @static 15204 * @memberOf _ 15205 * @since 4.0.0 15206 * @category Object 15207 * @param {Object} object The source object. 15208 * @param {Function} [predicate=_.identity] The function invoked per property. 15209 * @returns {Object} Returns the new object. 15210 * @example 15211 * 15212 * var object = { 'a': 1, 'b': '2', 'c': 3 }; 15213 * 15214 * _.omitBy(object, _.isNumber); 15215 * // => { 'b': '2' } 15216 */ 15217 function omitBy(object, predicate) { 15218 return pickBy(object, negate(getIteratee(predicate))); 15219 } 15220 15221 /** 15222 * Creates an object composed of the picked `object` properties. 15223 * 15224 * @static 15225 * @since 0.1.0 15226 * @memberOf _ 15227 * @category Object 15228 * @param {Object} object The source object. 15229 * @param {...(string|string[])} [paths] The property paths to pick. 15230 * @returns {Object} Returns the new object. 15231 * @example 15232 * 15233 * var object = { 'a': 1, 'b': '2', 'c': 3 }; 15234 * 15235 * _.pick(object, ['a', 'c']); 15236 * // => { 'a': 1, 'c': 3 } 15237 */ 15238 var pick = flatRest(function(object, paths) { 15239 return object == null ? {} : basePick(object, paths); 15240 }); 15241 15242 /**
vendor: 11,160 bytes, lines 15243-15581
15243 * Creates an object composed of the `object` properties `predicate` returns 15244 * truthy for. The predicate is invoked with two arguments: (value, key). 15245 * 15246 * @static 15247 * @memberOf _ 15248 * @since 4.0.0 15249 * @category Object 15250 * @param {Object} object The source object. 15251 * @param {Function} [predicate=_.identity] The function invoked per property. 15252 * @returns {Object} Returns the new object. 15253 * @example 15254 * 15255 * var object = { 'a': 1, 'b': '2', 'c': 3 }; 15256 * 15257 * _.pickBy(object, _.isNumber); 15258 * // => { 'a': 1, 'c': 3 } 15259 */ 15260 function pickBy(object, predicate) { 15261 if (object == null) { 15262 return {}; 15263 } 15264 var props = arrayMap(getAllKeysIn(object), function(prop) { 15265 return [prop]; 15266 }); 15267 predicate = getIteratee(predicate); 15268 return basePickBy(object, props, function(value, path) { 15269 return predicate(value, path[0]); 15270 }); 15271 } 15272 15273 /** 15274 * This method is like `_.get` except that if the resolved value is a 15275 * function it's invoked with the `this` binding of its parent object and 15276 * its result is returned. 15277 * 15278 * @static 15279 * @since 0.1.0 15280 * @memberOf _ 15281 * @category Object 15282 * @param {Object} object The object to query. 15283 * @param {Array|string} path The path of the property to resolve. 15284 * @param {*} [defaultValue] The value returned for `undefined` resolved values. 15285 * @returns {*} Returns the resolved value. 15286 * @example 15287 * 15288 * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] }; 15289 * 15290 * _.result(object, 'a[0].b.c1'); 15291 * // => 3 15292 * 15293 * _.result(object, 'a[0].b.c2'); 15294 * // => 4 15295 * 15296 * _.result(object, 'a[0].b.c3', 'default'); 15297 * // => 'default' 15298 * 15299 * _.result(object, 'a[0].b.c3', _.constant('default')); 15300 * // => 'default' 15301 */ 15302 function result(object, path, defaultValue) { 15303 path = castPath(path, object); 15304 15305 var index = -1, 15306 length = path.length; 15307 15308 // Ensure the loop is entered when path is empty. 15309 if (!length) { 15310 length = 1; 15311 object = undefined; 15312 } 15313 while (++index < length) { 15314 var value = object == null ? undefined : object[toKey(path[index])]; 15315 if (value === undefined) { 15316 index = length; 15317 value = defaultValue; 15318 } 15319 object = isFunction(value) ? value.call(object) : value; 15320 } 15321 return object; 15322 } 15323 15324 /** 15325 * Sets the value at `path` of `object`. If a portion of `path` doesn't exist, 15326 * it's created. Arrays are created for missing index properties while objects 15327 * are created for all other missing properties. Use `_.setWith` to customize 15328 * `path` creation. 15329 * 15330 * **Note:** This method mutates `object`. 15331 * 15332 * @static 15333 * @memberOf _ 15334 * @since 3.7.0 15335 * @category Object 15336 * @param {Object} object The object to modify. 15337 * @param {Array|string} path The path of the property to set. 15338 * @param {*} value The value to set. 15339 * @returns {Object} Returns `object`. 15340 * @example 15341 * 15342 * var object = { 'a': [{ 'b': { 'c': 3 } }] }; 15343 * 15344 * _.set(object, 'a[0].b.c', 4); 15345 * console.log(object.a[0].b.c); 15346 * // => 4 15347 * 15348 * _.set(object, ['x', '0', 'y', 'z'], 5); 15349 * console.log(object.x[0].y.z); 15350 * // => 5 15351 */ 15352 function set(object, path, value) { 15353 return object == null ? object : baseSet(object, path, value); 15354 } 15355 15356 /** 15357 * This method is like `_.set` except that it accepts `customizer` which is 15358 * invoked to produce the objects of `path`. If `customizer` returns `undefined` 15359 * path creation is handled by the method instead. The `customizer` is invoked 15360 * with three arguments: (nsValue, key, nsObject). 15361 * 15362 * **Note:** This method mutates `object`. 15363 * 15364 * @static 15365 * @memberOf _ 15366 * @since 4.0.0 15367 * @category Object 15368 * @param {Object} object The object to modify. 15369 * @param {Array|string} path The path of the property to set. 15370 * @param {*} value The value to set. 15371 * @param {Function} [customizer] The function to customize assigned values. 15372 * @returns {Object} Returns `object`. 15373 * @example 15374 * 15375 * var object = {}; 15376 * 15377 * _.setWith(object, '[0][1]', 'a', Object); 15378 * // => { '0': { '1': 'a' } } 15379 */ 15380 function setWith(object, path, value, customizer) { 15381 customizer = typeof customizer == 'function' ? customizer : undefined; 15382 return object == null ? object : baseSet(object, path, value, customizer); 15383 } 15384 15385 /** 15386 * Creates an array of own enumerable string keyed-value pairs for `object` 15387 * which can be consumed by `_.fromPairs`. If `object` is a map or set, its 15388 * entries are returned. 15389 * 15390 * @static 15391 * @memberOf _ 15392 * @since 4.0.0 15393 * @alias entries 15394 * @category Object 15395 * @param {Object} object The object to query. 15396 * @returns {Array} Returns the key-value pairs. 15397 * @example 15398 * 15399 * function Foo() { 15400 * this.a = 1; 15401 * this.b = 2; 15402 * } 15403 * 15404 * Foo.prototype.c = 3; 15405 * 15406 * _.toPairs(new Foo); 15407 * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed) 15408 */ 15409 var toPairs = createToPairs(keys); 15410 15411 /** 15412 * Creates an array of own and inherited enumerable string keyed-value pairs 15413 * for `object` which can be consumed by `_.fromPairs`. If `object` is a map 15414 * or set, its entries are returned. 15415 * 15416 * @static 15417 * @memberOf _ 15418 * @since 4.0.0 15419 * @alias entriesIn 15420 * @category Object 15421 * @param {Object} object The object to query. 15422 * @returns {Array} Returns the key-value pairs. 15423 * @example 15424 * 15425 * function Foo() { 15426 * this.a = 1; 15427 * this.b = 2; 15428 * } 15429 * 15430 * Foo.prototype.c = 3; 15431 * 15432 * _.toPairsIn(new Foo); 15433 * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed) 15434 */ 15435 var toPairsIn = createToPairs(keysIn); 15436 15437 /** 15438 * An alternative to `_.reduce`; this method transforms `object` to a new 15439 * `accumulator` object which is the result of running each of its own 15440 * enumerable string keyed properties thru `iteratee`, with each invocation 15441 * potentially mutating the `accumulator` object. If `accumulator` is not 15442 * provided, a new object with the same `[[Prototype]]` will be used. The 15443 * iteratee is invoked with four arguments: (accumulator, value, key, object). 15444 * Iteratee functions may exit iteration early by explicitly returning `false`. 15445 * 15446 * @static 15447 * @memberOf _ 15448 * @since 1.3.0 15449 * @category Object 15450 * @param {Object} object The object to iterate over. 15451 * @param {Function} [iteratee=_.identity] The function invoked per iteration. 15452 * @param {*} [accumulator] The custom accumulator value. 15453 * @returns {*} Returns the accumulated value. 15454 * @example 15455 * 15456 * _.transform([2, 3, 4], function(result, n) { 15457 * result.push(n *= n); 15458 * return n % 2 == 0; 15459 * }, []); 15460 * // => [4, 9] 15461 * 15462 * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { 15463 * (result[value] || (result[value] = [])).push(key); 15464 * }, {}); 15465 * // => { '1': ['a', 'c'], '2': ['b'] } 15466 */ 15467 function transform(object, iteratee, accumulator) { 15468 var isArr = isArray(object), 15469 isArrLike = isArr || isBuffer(object) || isTypedArray(object); 15470 15471 iteratee = getIteratee(iteratee, 4); 15472 if (accumulator == null) { 15473 var Ctor = object && object.constructor; 15474 if (isArrLike) { 15475 accumulator = isArr ? new Ctor : []; 15476 } 15477 else if (isObject(object)) { 15478 accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {}; 15479 } 15480 else { 15481 accumulator = {}; 15482 } 15483 } 15484 (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) { 15485 return iteratee(accumulator, value, index, object); 15486 }); 15487 return accumulator; 15488 } 15489 15490 /** 15491 * Removes the property at `path` of `object`. 15492 * 15493 * **Note:** This method mutates `object`. 15494 * 15495 * @static 15496 * @memberOf _ 15497 * @since 4.0.0 15498 * @category Object 15499 * @param {Object} object The object to modify. 15500 * @param {Array|string} path The path of the property to unset. 15501 * @returns {boolean} Returns `true` if the property is deleted, else `false`. 15502 * @example 15503 * 15504 * var object = { 'a': [{ 'b': { 'c': 7 } }] }; 15505 * _.unset(object, 'a[0].b.c'); 15506 * // => true 15507 * 15508 * console.log(object); 15509 * // => { 'a': [{ 'b': {} }] }; 15510 * 15511 * _.unset(object, ['a', '0', 'b', 'c']); 15512 * // => true 15513 * 15514 * console.log(object); 15515 * // => { 'a': [{ 'b': {} }] }; 15516 */ 15517 function unset(object, path) { 15518 return object == null ? true : baseUnset(object, path); 15519 } 15520 15521 /** 15522 * This method is like `_.set` except that accepts `updater` to produce the 15523 * value to set. Use `_.updateWith` to customize `path` creation. The `updater` 15524 * is invoked with one argument: (value). 15525 * 15526 * **Note:** This method mutates `object`. 15527 * 15528 * @static 15529 * @memberOf _ 15530 * @since 4.6.0 15531 * @category Object 15532 * @param {Object} object The object to modify. 15533 * @param {Array|string} path The path of the property to set. 15534 * @param {Function} updater The function to produce the updated value. 15535 * @returns {Object} Returns `object`. 15536 * @example 15537 * 15538 * var object = { 'a': [{ 'b': { 'c': 3 } }] }; 15539 * 15540 * _.update(object, 'a[0].b.c', function(n) { return n * n; }); 15541 * console.log(object.a[0].b.c); 15542 * // => 9 15543 * 15544 * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; }); 15545 * console.log(object.x[0].y.z); 15546 * // => 0 15547 */ 15548 function update(object, path, updater) { 15549 return object == null ? object : baseUpdate(object, path, castFunction(updater)); 15550 } 15551 15552 /** 15553 * This method is like `_.update` except that it accepts `customizer` which is 15554 * invoked to produce the objects of `path`. If `customizer` returns `undefined` 15555 * path creation is handled by the method instead. The `customizer` is invoked 15556 * with three arguments: (nsValue, key, nsObject). 15557 * 15558 * **Note:** This method mutates `object`. 15559 * 15560 * @static 15561 * @memberOf _ 15562 * @since 4.6.0 15563 * @category Object 15564 * @param {Object} object The object to modify. 15565 * @param {Array|string} path The path of the property to set. 15566 * @param {Function} updater The function to produce the updated value. 15567 * @param {Function} [customizer] The function to customize assigned values. 15568 * @returns {Object} Returns `object`. 15569 * @example 15570 * 15571 * var object = {}; 15572 * 15573 * _.updateWith(object, '[0][1]', _.constant('a'), Object); 15574 * // => { '0': { '1': 'a' } } 15575 */ 15576 function updateWith(object, path, updater, customizer) { 15577 customizer = typeof customizer == 'function' ? customizer : undefined; 15578 return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer); 15579 } 15580 15581 /**
vendor: 1,263 bytes, lines 15582-15631
15582 * Creates an array of the own enumerable string keyed property values of `object`. 15583 * 15584 * **Note:** Non-object values are coerced to objects. 15585 * 15586 * @static 15587 * @since 0.1.0 15588 * @memberOf _ 15589 * @category Object 15590 * @param {Object} object The object to query. 15591 * @returns {Array} Returns the array of property values. 15592 * @example 15593 * 15594 * function Foo() { 15595 * this.a = 1; 15596 * this.b = 2; 15597 * } 15598 * 15599 * Foo.prototype.c = 3; 15600 * 15601 * _.values(new Foo); 15602 * // => [1, 2] (iteration order is not guaranteed) 15603 * 15604 * _.values('hi'); 15605 * // => ['h', 'i'] 15606 */ 15607 function values(object) { 15608 return object == null ? [] : baseValues(object, keys(object)); 15609 } 15610 15611 /** 15612 * Creates an array of the own and inherited enumerable string keyed property 15613 * values of `object`. 15614 * 15615 * **Note:** Non-object values are coerced to objects. 15616 * 15617 * @static 15618 * @memberOf _ 15619 * @since 3.0.0 15620 * @category Object 15621 * @param {Object} object The object to query. 15622 * @returns {Array} Returns the array of property values. 15623 * @example 15624 * 15625 * function Foo() { 15626 * this.a = 1; 15627 * this.b = 2; 15628 * } 15629 * 15630 * Foo.prototype.c = 3; 15631 *
vendor: 9,679 bytes, lines 15632-15952
15632 * _.valuesIn(new Foo); 15633 * // => [1, 2, 3] (iteration order is not guaranteed) 15634 */ 15635 function valuesIn(object) { 15636 return object == null ? [] : baseValues(object, keysIn(object)); 15637 } 15638 15639 /*------------------------------------------------------------------------*/ 15640 15641 /** 15642 * Clamps `number` within the inclusive `lower` and `upper` bounds. 15643 * 15644 * @static 15645 * @memberOf _ 15646 * @since 4.0.0 15647 * @category Number 15648 * @param {number} number The number to clamp. 15649 * @param {number} [lower] The lower bound. 15650 * @param {number} upper The upper bound. 15651 * @returns {number} Returns the clamped number. 15652 * @example 15653 * 15654 * _.clamp(-10, -5, 5); 15655 * // => -5 15656 * 15657 * _.clamp(10, -5, 5); 15658 * // => 5 15659 */ 15660 function clamp(number, lower, upper) { 15661 if (upper === undefined) { 15662 upper = lower; 15663 lower = undefined; 15664 } 15665 if (upper !== undefined) { 15666 upper = toNumber(upper); 15667 upper = upper === upper ? upper : 0; 15668 } 15669 if (lower !== undefined) { 15670 lower = toNumber(lower); 15671 lower = lower === lower ? lower : 0; 15672 } 15673 return baseClamp(toNumber(number), lower, upper); 15674 } 15675 15676 /** 15677 * Checks if `n` is between `start` and up to, but not including, `end`. If 15678 * `end` is not specified, it's set to `start` with `start` then set to `0`. 15679 * If `start` is greater than `end` the params are swapped to support 15680 * negative ranges. 15681 * 15682 * @static 15683 * @memberOf _ 15684 * @since 3.3.0 15685 * @category Number 15686 * @param {number} number The number to check. 15687 * @param {number} [start=0] The start of the range. 15688 * @param {number} end The end of the range. 15689 * @returns {boolean} Returns `true` if `number` is in the range, else `false`. 15690 * @see _.range, _.rangeRight 15691 * @example 15692 * 15693 * _.inRange(3, 2, 4); 15694 * // => true 15695 * 15696 * _.inRange(4, 8); 15697 * // => true 15698 * 15699 * _.inRange(4, 2); 15700 * // => false 15701 * 15702 * _.inRange(2, 2); 15703 * // => false 15704 * 15705 * _.inRange(1.2, 2); 15706 * // => true 15707 * 15708 * _.inRange(5.2, 4); 15709 * // => false 15710 * 15711 * _.inRange(-3, -2, -6); 15712 * // => true 15713 */ 15714 function inRange(number, start, end) { 15715 start = toFinite(start); 15716 if (end === undefined) { 15717 end = start; 15718 start = 0; 15719 } else { 15720 end = toFinite(end); 15721 } 15722 number = toNumber(number); 15723 return baseInRange(number, start, end); 15724 } 15725 15726 /** 15727 * Produces a random number between the inclusive `lower` and `upper` bounds. 15728 * If only one argument is provided a number between `0` and the given number 15729 * is returned. If `floating` is `true`, or either `lower` or `upper` are 15730 * floats, a floating-point number is returned instead of an integer. 15731 * 15732 * **Note:** JavaScript follows the IEEE-754 standard for resolving 15733 * floating-point values which can produce unexpected results. 15734 * 15735 * @static 15736 * @memberOf _ 15737 * @since 0.7.0 15738 * @category Number 15739 * @param {number} [lower=0] The lower bound. 15740 * @param {number} [upper=1] The upper bound. 15741 * @param {boolean} [floating] Specify returning a floating-point number. 15742 * @returns {number} Returns the random number. 15743 * @example 15744 * 15745 * _.random(0, 5); 15746 * // => an integer between 0 and 5 15747 * 15748 * _.random(5); 15749 * // => also an integer between 0 and 5 15750 * 15751 * _.random(5, true); 15752 * // => a floating-point number between 0 and 5 15753 * 15754 * _.random(1.2, 5.2); 15755 * // => a floating-point number between 1.2 and 5.2 15756 */ 15757 function random(lower, upper, floating) { 15758 if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) { 15759 upper = floating = undefined; 15760 } 15761 if (floating === undefined) { 15762 if (typeof upper == 'boolean') { 15763 floating = upper; 15764 upper = undefined; 15765 } 15766 else if (typeof lower == 'boolean') { 15767 floating = lower; 15768 lower = undefined; 15769 } 15770 } 15771 if (lower === undefined && upper === undefined) { 15772 lower = 0; 15773 upper = 1; 15774 } 15775 else { 15776 lower = toFinite(lower); 15777 if (upper === undefined) { 15778 upper = lower; 15779 lower = 0; 15780 } else { 15781 upper = toFinite(upper); 15782 } 15783 } 15784 if (lower > upper) { 15785 var temp = lower; 15786 lower = upper; 15787 upper = temp; 15788 } 15789 if (floating || lower % 1 || upper % 1) { 15790 var rand = nativeRandom(); 15791 return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper); 15792 } 15793 return baseRandom(lower, upper); 15794 } 15795 15796 /*------------------------------------------------------------------------*/ 15797 15798 /** 15799 * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase). 15800 * 15801 * @static 15802 * @memberOf _ 15803 * @since 3.0.0 15804 * @category String 15805 * @param {string} [string=''] The string to convert. 15806 * @returns {string} Returns the camel cased string. 15807 * @example 15808 * 15809 * _.camelCase('Foo Bar'); 15810 * // => 'fooBar' 15811 * 15812 * _.camelCase('--foo-bar--'); 15813 * // => 'fooBar' 15814 * 15815 * _.camelCase('__FOO_BAR__'); 15816 * // => 'fooBar' 15817 */ 15818 var camelCase = createCompounder(function(result, word, index) { 15819 word = word.toLowerCase(); 15820 return result + (index ? capitalize(word) : word); 15821 }); 15822 15823 /** 15824 * Converts the first character of `string` to upper case and the remaining 15825 * to lower case. 15826 * 15827 * @static 15828 * @memberOf _ 15829 * @since 3.0.0 15830 * @category String 15831 * @param {string} [string=''] The string to capitalize. 15832 * @returns {string} Returns the capitalized string. 15833 * @example 15834 * 15835 * _.capitalize('FRED'); 15836 * // => 'Fred' 15837 */ 15838 function capitalize(string) { 15839 return upperFirst(toString(string).toLowerCase()); 15840 } 15841 15842 /** 15843 * Deburrs `string` by converting 15844 * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) 15845 * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A) 15846 * letters to basic Latin letters and removing 15847 * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). 15848 * 15849 * @static 15850 * @memberOf _ 15851 * @since 3.0.0 15852 * @category String 15853 * @param {string} [string=''] The string to deburr. 15854 * @returns {string} Returns the deburred string. 15855 * @example 15856 * 15857 * _.deburr('déjà vu'); 15858 * // => 'deja vu' 15859 */ 15860 function deburr(string) { 15861 string = toString(string); 15862 return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ''); 15863 } 15864 15865 /** 15866 * Checks if `string` ends with the given target string. 15867 * 15868 * @static 15869 * @memberOf _ 15870 * @since 3.0.0 15871 * @category String 15872 * @param {string} [string=''] The string to inspect. 15873 * @param {string} [target] The string to search for. 15874 * @param {number} [position=string.length] The position to search up to. 15875 * @returns {boolean} Returns `true` if `string` ends with `target`, 15876 * else `false`. 15877 * @example 15878 * 15879 * _.endsWith('abc', 'c'); 15880 * // => true 15881 * 15882 * _.endsWith('abc', 'b'); 15883 * // => false 15884 * 15885 * _.endsWith('abc', 'b', 2); 15886 * // => true 15887 */ 15888 function endsWith(string, target, position) { 15889 string = toString(string); 15890 target = baseToString(target); 15891 15892 var length = string.length; 15893 position = position === undefined 15894 ? length 15895 : baseClamp(toInteger(position), 0, length); 15896 15897 var end = position; 15898 position -= target.length; 15899 return position >= 0 && string.slice(position, end) == target; 15900 } 15901 15902 /** 15903 * Converts the characters "&", "<", ">", '"', and "'" in `string` to their 15904 * corresponding HTML entities. 15905 * 15906 * **Note:** No other characters are escaped. To escape additional 15907 * characters use a third-party library like [_he_](https://mths.be/he). 15908 * 15909 * Though the ">" character is escaped for symmetry, characters like 15910 * ">" and "/" don't need escaping in HTML and have no special meaning 15911 * unless they're part of a tag or unquoted attribute value. See 15912 * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) 15913 * (under "semi-related fun fact") for more details. 15914 * 15915 * When working with HTML you should always 15916 * [quote attribute values](http://wonko.com/post/html-escaping) to reduce 15917 * XSS vectors. 15918 * 15919 * @static 15920 * @since 0.1.0 15921 * @memberOf _ 15922 * @category String 15923 * @param {string} [string=''] The string to escape. 15924 * @returns {string} Returns the escaped string. 15925 * @example 15926 * 15927 * _.escape('fred, barney, & pebbles'); 15928 * // => 'fred, barney, & pebbles' 15929 */ 15930 function escape(string) { 15931 string = toString(string); 15932 return (string && reHasUnescapedHtml.test(string)) 15933 ? string.replace(reUnescapedHtml, escapeHtmlChar) 15934 : string; 15935 } 15936 15937 /** 15938 * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+", 15939 * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`. 15940 * 15941 * @static 15942 * @memberOf _ 15943 * @since 3.0.0 15944 * @category String 15945 * @param {string} [string=''] The string to escape. 15946 * @returns {string} Returns the escaped string. 15947 * @example 15948 * 15949 * _.escapeRegExp('[lodash](https://lodash.com/)'); 15950 * // => '\[lodash\]\(https://lodash\.com/\)' 15951 */ 15952 function escapeRegExp(string) {
vendor: 4,658 bytes, lines 15953-16122
15953 string = toString(string); 15954 return (string && reHasRegExpChar.test(string)) 15955 ? string.replace(reRegExpChar, '\\$&') 15956 : string; 15957 } 15958 15959 /** 15960 * Converts `string` to 15961 * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). 15962 * 15963 * @static 15964 * @memberOf _ 15965 * @since 3.0.0 15966 * @category String 15967 * @param {string} [string=''] The string to convert. 15968 * @returns {string} Returns the kebab cased string. 15969 * @example 15970 * 15971 * _.kebabCase('Foo Bar'); 15972 * // => 'foo-bar' 15973 * 15974 * _.kebabCase('fooBar'); 15975 * // => 'foo-bar' 15976 * 15977 * _.kebabCase('__FOO_BAR__'); 15978 * // => 'foo-bar' 15979 */ 15980 var kebabCase = createCompounder(function(result, word, index) { 15981 return result + (index ? '-' : '') + word.toLowerCase(); 15982 }); 15983 15984 /** 15985 * Converts `string`, as space separated words, to lower case. 15986 * 15987 * @static 15988 * @memberOf _ 15989 * @since 4.0.0 15990 * @category String 15991 * @param {string} [string=''] The string to convert. 15992 * @returns {string} Returns the lower cased string. 15993 * @example 15994 * 15995 * _.lowerCase('--Foo-Bar--'); 15996 * // => 'foo bar' 15997 * 15998 * _.lowerCase('fooBar'); 15999 * // => 'foo bar' 16000 * 16001 * _.lowerCase('__FOO_BAR__'); 16002 * // => 'foo bar' 16003 */ 16004 var lowerCase = createCompounder(function(result, word, index) { 16005 return result + (index ? ' ' : '') + word.toLowerCase(); 16006 }); 16007 16008 /** 16009 * Converts the first character of `string` to lower case. 16010 * 16011 * @static 16012 * @memberOf _ 16013 * @since 4.0.0 16014 * @category String 16015 * @param {string} [string=''] The string to convert. 16016 * @returns {string} Returns the converted string. 16017 * @example 16018 * 16019 * _.lowerFirst('Fred'); 16020 * // => 'fred' 16021 * 16022 * _.lowerFirst('FRED'); 16023 * // => 'fRED' 16024 */ 16025 var lowerFirst = createCaseFirst('toLowerCase'); 16026 16027 /** 16028 * Pads `string` on the left and right sides if it's shorter than `length`. 16029 * Padding characters are truncated if they can't be evenly divided by `length`. 16030 * 16031 * @static 16032 * @memberOf _ 16033 * @since 3.0.0 16034 * @category String 16035 * @param {string} [string=''] The string to pad. 16036 * @param {number} [length=0] The padding length. 16037 * @param {string} [chars=' '] The string used as padding. 16038 * @returns {string} Returns the padded string. 16039 * @example 16040 * 16041 * _.pad('abc', 8); 16042 * // => ' abc ' 16043 * 16044 * _.pad('abc', 8, '_-'); 16045 * // => '_-abc_-_' 16046 * 16047 * _.pad('abc', 3); 16048 * // => 'abc' 16049 */ 16050 function pad(string, length, chars) { 16051 string = toString(string); 16052 length = toInteger(length); 16053 16054 var strLength = length ? stringSize(string) : 0; 16055 if (!length || strLength >= length) { 16056 return string; 16057 } 16058 var mid = (length - strLength) / 2; 16059 return ( 16060 createPadding(nativeFloor(mid), chars) + 16061 string + 16062 createPadding(nativeCeil(mid), chars) 16063 ); 16064 } 16065 16066 /** 16067 * Pads `string` on the right side if it's shorter than `length`. Padding 16068 * characters are truncated if they exceed `length`. 16069 * 16070 * @static 16071 * @memberOf _ 16072 * @since 4.0.0 16073 * @category String 16074 * @param {string} [string=''] The string to pad. 16075 * @param {number} [length=0] The padding length. 16076 * @param {string} [chars=' '] The string used as padding. 16077 * @returns {string} Returns the padded string. 16078 * @example 16079 * 16080 * _.padEnd('abc', 6); 16081 * // => 'abc ' 16082 * 16083 * _.padEnd('abc', 6, '_-'); 16084 * // => 'abc_-_' 16085 * 16086 * _.padEnd('abc', 3); 16087 * // => 'abc' 16088 */ 16089 function padEnd(string, length, chars) { 16090 string = toString(string); 16091 length = toInteger(length); 16092 16093 var strLength = length ? stringSize(string) : 0; 16094 return (length && strLength < length) 16095 ? (string + createPadding(length - strLength, chars)) 16096 : string; 16097 } 16098 16099 /** 16100 * Pads `string` on the left side if it's shorter than `length`. Padding 16101 * characters are truncated if they exceed `length`. 16102 * 16103 * @static 16104 * @memberOf _ 16105 * @since 4.0.0 16106 * @category String 16107 * @param {string} [string=''] The string to pad. 16108 * @param {number} [length=0] The padding length. 16109 * @param {string} [chars=' '] The string used as padding. 16110 * @returns {string} Returns the padded string. 16111 * @example 16112 * 16113 * _.padStart('abc', 6); 16114 * // => ' abc' 16115 * 16116 * _.padStart('abc', 6, '_-'); 16117 * // => '_-_abc' 16118 * 16119 * _.padStart('abc', 3); 16120 * // => 'abc' 16121 */ 16122 function padStart(string, length, chars) {
vendor: 29,827 bytes, lines 16123-17020
16123 string = toString(string); 16124 length = toInteger(length); 16125 16126 var strLength = length ? stringSize(string) : 0; 16127 return (length && strLength < length) 16128 ? (createPadding(length - strLength, chars) + string) 16129 : string; 16130 } 16131 16132 /** 16133 * Converts `string` to an integer of the specified radix. If `radix` is 16134 * `undefined` or `0`, a `radix` of `10` is used unless `value` is a 16135 * hexadecimal, in which case a `radix` of `16` is used. 16136 * 16137 * **Note:** This method aligns with the 16138 * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`. 16139 * 16140 * @static 16141 * @memberOf _ 16142 * @since 1.1.0 16143 * @category String 16144 * @param {string} string The string to convert. 16145 * @param {number} [radix=10] The radix to interpret `value` by. 16146 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 16147 * @returns {number} Returns the converted integer. 16148 * @example 16149 * 16150 * _.parseInt('08'); 16151 * // => 8 16152 * 16153 * _.map(['6', '08', '10'], _.parseInt); 16154 * // => [6, 8, 10] 16155 */ 16156 function parseInt(string, radix, guard) { 16157 if (guard || radix == null) { 16158 radix = 0; 16159 } else if (radix) { 16160 radix = +radix; 16161 } 16162 return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0); 16163 } 16164 16165 /** 16166 * Repeats the given string `n` times. 16167 * 16168 * @static 16169 * @memberOf _ 16170 * @since 3.0.0 16171 * @category String 16172 * @param {string} [string=''] The string to repeat. 16173 * @param {number} [n=1] The number of times to repeat the string. 16174 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 16175 * @returns {string} Returns the repeated string. 16176 * @example 16177 * 16178 * _.repeat('*', 3); 16179 * // => '***' 16180 * 16181 * _.repeat('abc', 2); 16182 * // => 'abcabc' 16183 * 16184 * _.repeat('abc', 0); 16185 * // => '' 16186 */ 16187 function repeat(string, n, guard) { 16188 if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) { 16189 n = 1; 16190 } else { 16191 n = toInteger(n); 16192 } 16193 return baseRepeat(toString(string), n); 16194 } 16195 16196 /** 16197 * Replaces matches for `pattern` in `string` with `replacement`. 16198 * 16199 * **Note:** This method is based on 16200 * [`String#replace`](https://mdn.io/String/replace). 16201 * 16202 * @static 16203 * @memberOf _ 16204 * @since 4.0.0 16205 * @category String 16206 * @param {string} [string=''] The string to modify. 16207 * @param {RegExp|string} pattern The pattern to replace. 16208 * @param {Function|string} replacement The match replacement. 16209 * @returns {string} Returns the modified string. 16210 * @example 16211 * 16212 * _.replace('Hi Fred', 'Fred', 'Barney'); 16213 * // => 'Hi Barney' 16214 */ 16215 function replace() { 16216 var args = arguments, 16217 string = toString(args[0]); 16218 16219 return args.length < 3 ? string : string.replace(args[1], args[2]); 16220 } 16221 16222 /** 16223 * Converts `string` to 16224 * [snake case](https://en.wikipedia.org/wiki/Snake_case). 16225 * 16226 * @static 16227 * @memberOf _ 16228 * @since 3.0.0 16229 * @category String 16230 * @param {string} [string=''] The string to convert. 16231 * @returns {string} Returns the snake cased string. 16232 * @example 16233 * 16234 * _.snakeCase('Foo Bar'); 16235 * // => 'foo_bar' 16236 * 16237 * _.snakeCase('fooBar'); 16238 * // => 'foo_bar' 16239 * 16240 * _.snakeCase('--FOO-BAR--'); 16241 * // => 'foo_bar' 16242 */ 16243 var snakeCase = createCompounder(function(result, word, index) { 16244 return result + (index ? '_' : '') + word.toLowerCase(); 16245 }); 16246 16247 /** 16248 * Splits `string` by `separator`. 16249 * 16250 * **Note:** This method is based on 16251 * [`String#split`](https://mdn.io/String/split). 16252 * 16253 * @static 16254 * @memberOf _ 16255 * @since 4.0.0 16256 * @category String 16257 * @param {string} [string=''] The string to split. 16258 * @param {RegExp|string} separator The separator pattern to split by. 16259 * @param {number} [limit] The length to truncate results to. 16260 * @returns {Array} Returns the string segments. 16261 * @example 16262 * 16263 * _.split('a-b-c', '-', 2); 16264 * // => ['a', 'b'] 16265 */ 16266 function split(string, separator, limit) { 16267 if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) { 16268 separator = limit = undefined; 16269 } 16270 limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0; 16271 if (!limit) { 16272 return []; 16273 } 16274 string = toString(string); 16275 if (string && ( 16276 typeof separator == 'string' || 16277 (separator != null && !isRegExp(separator)) 16278 )) { 16279 separator = baseToString(separator); 16280 if (!separator && hasUnicode(string)) { 16281 return castSlice(stringToArray(string), 0, limit); 16282 } 16283 } 16284 return string.split(separator, limit); 16285 } 16286 16287 /** 16288 * Converts `string` to 16289 * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage). 16290 * 16291 * @static 16292 * @memberOf _ 16293 * @since 3.1.0 16294 * @category String 16295 * @param {string} [string=''] The string to convert. 16296 * @returns {string} Returns the start cased string. 16297 * @example 16298 * 16299 * _.startCase('--foo-bar--'); 16300 * // => 'Foo Bar' 16301 * 16302 * _.startCase('fooBar'); 16303 * // => 'Foo Bar' 16304 * 16305 * _.startCase('__FOO_BAR__'); 16306 * // => 'FOO BAR' 16307 */ 16308 var startCase = createCompounder(function(result, word, index) { 16309 return result + (index ? ' ' : '') + upperFirst(word); 16310 }); 16311 16312 /** 16313 * Checks if `string` starts with the given target string. 16314 * 16315 * @static 16316 * @memberOf _ 16317 * @since 3.0.0 16318 * @category String 16319 * @param {string} [string=''] The string to inspect. 16320 * @param {string} [target] The string to search for. 16321 * @param {number} [position=0] The position to search from. 16322 * @returns {boolean} Returns `true` if `string` starts with `target`, 16323 * else `false`. 16324 * @example 16325 * 16326 * _.startsWith('abc', 'a'); 16327 * // => true 16328 * 16329 * _.startsWith('abc', 'b'); 16330 * // => false 16331 * 16332 * _.startsWith('abc', 'b', 1); 16333 * // => true 16334 */ 16335 function startsWith(string, target, position) { 16336 string = toString(string); 16337 position = position == null 16338 ? 0 16339 : baseClamp(toInteger(position), 0, string.length); 16340 16341 target = baseToString(target); 16342 return string.slice(position, position + target.length) == target; 16343 } 16344 16345 /** 16346 * Creates a compiled template function that can interpolate data properties 16347 * in "interpolate" delimiters, HTML-escape interpolated data properties in 16348 * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data 16349 * properties may be accessed as free variables in the template. If a setting 16350 * object is given, it takes precedence over `_.templateSettings` values. 16351 * 16352 * **Note:** In the development build `_.template` utilizes 16353 * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) 16354 * for easier debugging. 16355 * 16356 * For more information on precompiling templates see 16357 * [lodash's custom builds documentation](https://lodash.com/custom-builds). 16358 * 16359 * For more information on Chrome extension sandboxes see 16360 * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval). 16361 * 16362 * @static 16363 * @since 0.1.0 16364 * @memberOf _ 16365 * @category String 16366 * @param {string} [string=''] The template string. 16367 * @param {Object} [options={}] The options object. 16368 * @param {RegExp} [options.escape=_.templateSettings.escape] 16369 * The HTML "escape" delimiter. 16370 * @param {RegExp} [options.evaluate=_.templateSettings.evaluate] 16371 * The "evaluate" delimiter. 16372 * @param {Object} [options.imports=_.templateSettings.imports] 16373 * An object to import into the template as free variables. 16374 * @param {RegExp} [options.interpolate=_.templateSettings.interpolate] 16375 * The "interpolate" delimiter. 16376 * @param {string} [options.sourceURL='lodash.templateSources[n]'] 16377 * The sourceURL of the compiled template. 16378 * @param {string} [options.variable='obj'] 16379 * The data object variable name. 16380 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 16381 * @returns {Function} Returns the compiled template function. 16382 * @example 16383 * 16384 * // Use the "interpolate" delimiter to create a compiled template. 16385 * var compiled = _.template('hello <%= user %>!'); 16386 * compiled({ 'user': 'fred' }); 16387 * // => 'hello fred!' 16388 * 16389 * // Use the HTML "escape" delimiter to escape data property values. 16390 * var compiled = _.template('<b><%- value %></b>'); 16391 * compiled({ 'value': '<script>' }); 16392 * // => '<b><script></b>' 16393 * 16394 * // Use the "evaluate" delimiter to execute JavaScript and generate HTML. 16395 * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>'); 16396 * compiled({ 'users': ['fred', 'barney'] }); 16397 * // => '<li>fred</li><li>barney</li>' 16398 * 16399 * // Use the internal `print` function in "evaluate" delimiters. 16400 * var compiled = _.template('<% print("hello " + user); %>!'); 16401 * compiled({ 'user': 'barney' }); 16402 * // => 'hello barney!' 16403 * 16404 * // Use the ES template literal delimiter as an "interpolate" delimiter. 16405 * // Disable support by replacing the "interpolate" delimiter. 16406 * var compiled = _.template('hello ${ user }!'); 16407 * compiled({ 'user': 'pebbles' }); 16408 * // => 'hello pebbles!' 16409 * 16410 * // Use backslashes to treat delimiters as plain text. 16411 * var compiled = _.template('<%= "\\<%- value %\\>" %>'); 16412 * compiled({ 'value': 'ignored' }); 16413 * // => '<%- value %>' 16414 * 16415 * // Use the `imports` option to import `jQuery` as `jq`. 16416 * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>'; 16417 * var compiled = _.template(text, { 'imports': { 'jq': jQuery } }); 16418 * compiled({ 'users': ['fred', 'barney'] }); 16419 * // => '<li>fred</li><li>barney</li>' 16420 * 16421 * // Use the `sourceURL` option to specify a custom sourceURL for the template. 16422 * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' }); 16423 * compiled(data); 16424 * // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector. 16425 * 16426 * // Use the `variable` option to ensure a with-statement isn't used in the compiled template. 16427 * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' }); 16428 * compiled.source; 16429 * // => function(data) { 16430 * // var __t, __p = ''; 16431 * // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!'; 16432 * // return __p; 16433 * // } 16434 * 16435 * // Use custom template delimiters. 16436 * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g; 16437 * var compiled = _.template('hello {{ user }}!'); 16438 * compiled({ 'user': 'mustache' }); 16439 * // => 'hello mustache!' 16440 * 16441 * // Use the `source` property to inline compiled templates for meaningful 16442 * // line numbers in error messages and stack traces. 16443 * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\ 16444 * var JST = {\ 16445 * "main": ' + _.template(mainText).source + '\ 16446 * };\ 16447 * '); 16448 */ 16449 function template(string, options, guard) { 16450 // Based on John Resig's `tmpl` implementation 16451 // (http://ejohn.org/blog/javascript-micro-templating/) 16452 // and Laura Doktorova's doT.js (https://github.com/olado/doT). 16453 var settings = lodash.templateSettings; 16454 16455 if (guard && isIterateeCall(string, options, guard)) { 16456 options = undefined; 16457 } 16458 string = toString(string); 16459 options = assignInWith({}, options, settings, customDefaultsAssignIn); 16460 16461 var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn), 16462 importsKeys = keys(imports), 16463 importsValues = baseValues(imports, importsKeys); 16464 16465 var isEscaping, 16466 isEvaluating, 16467 index = 0, 16468 interpolate = options.interpolate || reNoMatch, 16469 source = "__p += '"; 16470 16471 // Compile the regexp to match each delimiter. 16472 var reDelimiters = RegExp( 16473 (options.escape || reNoMatch).source + '|' + 16474 interpolate.source + '|' + 16475 (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' + 16476 (options.evaluate || reNoMatch).source + '|$' 16477 , 'g'); 16478 16479 // Use a sourceURL for easier debugging. 16480 // The sourceURL gets injected into the source that's eval-ed, so be careful 16481 // to normalize all kinds of whitespace, so e.g. newlines (and unicode versions of it) can't sneak in 16482 // and escape the comment, thus injecting code that gets evaled. 16483 var sourceURL = '//# sourceURL=' + 16484 (hasOwnProperty.call(options, 'sourceURL') 16485 ? (options.sourceURL + '').replace(/\s/g, ' ') 16486 : ('lodash.templateSources[' + (++templateCounter) + ']') 16487 ) + '\n'; 16488 16489 string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { 16490 interpolateValue || (interpolateValue = esTemplateValue); 16491 16492 // Escape characters that can't be included in string literals. 16493 source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); 16494 16495 // Replace delimiters with snippets. 16496 if (escapeValue) { 16497 isEscaping = true; 16498 source += "' +\n__e(" + escapeValue + ") +\n'"; 16499 } 16500 if (evaluateValue) { 16501 isEvaluating = true; 16502 source += "';\n" + evaluateValue + ";\n__p += '"; 16503 } 16504 if (interpolateValue) { 16505 source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'"; 16506 } 16507 index = offset + match.length; 16508 16509 // The JS engine embedded in Adobe products needs `match` returned in 16510 // order to produce the correct `offset` value. 16511 return match; 16512 }); 16513 16514 source += "';\n"; 16515 16516 // If `variable` is not specified wrap a with-statement around the generated 16517 // code to add the data object to the top of the scope chain. 16518 var variable = hasOwnProperty.call(options, 'variable') && options.variable; 16519 if (!variable) { 16520 source = 'with (obj) {\n' + source + '\n}\n'; 16521 } 16522 // Throw an error if a forbidden character was found in `variable`, to prevent 16523 // potential command injection attacks. 16524 else if (reForbiddenIdentifierChars.test(variable)) { 16525 throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT); 16526 } 16527 16528 // Cleanup code by stripping empty strings. 16529 source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source) 16530 .replace(reEmptyStringMiddle, '$1') 16531 .replace(reEmptyStringTrailing, '$1;'); 16532 16533 // Frame code as the function body. 16534 source = 'function(' + (variable || 'obj') + ') {\n' + 16535 (variable 16536 ? '' 16537 : 'obj || (obj = {});\n' 16538 ) + 16539 "var __t, __p = ''" + 16540 (isEscaping 16541 ? ', __e = _.escape' 16542 : '' 16543 ) + 16544 (isEvaluating 16545 ? ', __j = Array.prototype.join;\n' + 16546 "function print() { __p += __j.call(arguments, '') }\n" 16547 : ';\n' 16548 ) + 16549 source + 16550 'return __p\n}'; 16551 16552 var result = attempt(function() { 16553 return Function(importsKeys, sourceURL + 'return ' + source) 16554 .apply(undefined, importsValues); 16555 }); 16556 16557 // Provide the compiled function's source by its `toString` method or 16558 // the `source` property as a convenience for inlining compiled templates. 16559 result.source = source; 16560 if (isError(result)) { 16561 throw result; 16562 } 16563 return result; 16564 } 16565 16566 /** 16567 * Converts `string`, as a whole, to lower case just like 16568 * [String#toLowerCase](https://mdn.io/toLowerCase). 16569 * 16570 * @static 16571 * @memberOf _ 16572 * @since 4.0.0 16573 * @category String 16574 * @param {string} [string=''] The string to convert. 16575 * @returns {string} Returns the lower cased string. 16576 * @example 16577 * 16578 * _.toLower('--Foo-Bar--'); 16579 * // => '--foo-bar--' 16580 * 16581 * _.toLower('fooBar'); 16582 * // => 'foobar' 16583 * 16584 * _.toLower('__FOO_BAR__'); 16585 * // => '__foo_bar__' 16586 */ 16587 function toLower(value) { 16588 return toString(value).toLowerCase(); 16589 } 16590 16591 /** 16592 * Converts `string`, as a whole, to upper case just like 16593 * [String#toUpperCase](https://mdn.io/toUpperCase). 16594 * 16595 * @static 16596 * @memberOf _ 16597 * @since 4.0.0 16598 * @category String 16599 * @param {string} [string=''] The string to convert. 16600 * @returns {string} Returns the upper cased string. 16601 * @example 16602 * 16603 * _.toUpper('--foo-bar--'); 16604 * // => '--FOO-BAR--' 16605 * 16606 * _.toUpper('fooBar'); 16607 * // => 'FOOBAR' 16608 * 16609 * _.toUpper('__foo_bar__'); 16610 * // => '__FOO_BAR__' 16611 */ 16612 function toUpper(value) { 16613 return toString(value).toUpperCase(); 16614 } 16615 16616 /** 16617 * Removes leading and trailing whitespace or specified characters from `string`. 16618 * 16619 * @static 16620 * @memberOf _ 16621 * @since 3.0.0 16622 * @category String 16623 * @param {string} [string=''] The string to trim. 16624 * @param {string} [chars=whitespace] The characters to trim. 16625 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 16626 * @returns {string} Returns the trimmed string. 16627 * @example 16628 * 16629 * _.trim(' abc '); 16630 * // => 'abc' 16631 * 16632 * _.trim('-_-abc-_-', '_-'); 16633 * // => 'abc' 16634 * 16635 * _.map([' foo ', ' bar '], _.trim); 16636 * // => ['foo', 'bar'] 16637 */ 16638 function trim(string, chars, guard) { 16639 string = toString(string); 16640 if (string && (guard || chars === undefined)) { 16641 return baseTrim(string); 16642 } 16643 if (!string || !(chars = baseToString(chars))) { 16644 return string; 16645 } 16646 var strSymbols = stringToArray(string), 16647 chrSymbols = stringToArray(chars), 16648 start = charsStartIndex(strSymbols, chrSymbols), 16649 end = charsEndIndex(strSymbols, chrSymbols) + 1; 16650 16651 return castSlice(strSymbols, start, end).join(''); 16652 } 16653 16654 /** 16655 * Removes trailing whitespace or specified characters from `string`. 16656 * 16657 * @static 16658 * @memberOf _ 16659 * @since 4.0.0 16660 * @category String 16661 * @param {string} [string=''] The string to trim. 16662 * @param {string} [chars=whitespace] The characters to trim. 16663 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 16664 * @returns {string} Returns the trimmed string. 16665 * @example 16666 * 16667 * _.trimEnd(' abc '); 16668 * // => ' abc' 16669 * 16670 * _.trimEnd('-_-abc-_-', '_-'); 16671 * // => '-_-abc' 16672 */ 16673 function trimEnd(string, chars, guard) { 16674 string = toString(string); 16675 if (string && (guard || chars === undefined)) { 16676 return string.slice(0, trimmedEndIndex(string) + 1); 16677 } 16678 if (!string || !(chars = baseToString(chars))) { 16679 return string; 16680 } 16681 var strSymbols = stringToArray(string), 16682 end = charsEndIndex(strSymbols, stringToArray(chars)) + 1; 16683 16684 return castSlice(strSymbols, 0, end).join(''); 16685 } 16686 16687 /** 16688 * Removes leading whitespace or specified characters from `string`. 16689 * 16690 * @static 16691 * @memberOf _ 16692 * @since 4.0.0 16693 * @category String 16694 * @param {string} [string=''] The string to trim. 16695 * @param {string} [chars=whitespace] The characters to trim. 16696 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 16697 * @returns {string} Returns the trimmed string. 16698 * @example 16699 * 16700 * _.trimStart(' abc '); 16701 * // => 'abc ' 16702 * 16703 * _.trimStart('-_-abc-_-', '_-'); 16704 * // => 'abc-_-' 16705 */ 16706 function trimStart(string, chars, guard) { 16707 string = toString(string); 16708 if (string && (guard || chars === undefined)) { 16709 return string.replace(reTrimStart, ''); 16710 } 16711 if (!string || !(chars = baseToString(chars))) { 16712 return string; 16713 } 16714 var strSymbols = stringToArray(string), 16715 start = charsStartIndex(strSymbols, stringToArray(chars)); 16716 16717 return castSlice(strSymbols, start).join(''); 16718 } 16719 16720 /** 16721 * Truncates `string` if it's longer than the given maximum string length. 16722 * The last characters of the truncated string are replaced with the omission 16723 * string which defaults to "...". 16724 * 16725 * @static 16726 * @memberOf _ 16727 * @since 4.0.0 16728 * @category String 16729 * @param {string} [string=''] The string to truncate. 16730 * @param {Object} [options={}] The options object. 16731 * @param {number} [options.length=30] The maximum string length. 16732 * @param {string} [options.omission='...'] The string to indicate text is omitted. 16733 * @param {RegExp|string} [options.separator] The separator pattern to truncate to. 16734 * @returns {string} Returns the truncated string. 16735 * @example 16736 * 16737 * _.truncate('hi-diddly-ho there, neighborino'); 16738 * // => 'hi-diddly-ho there, neighbo...' 16739 * 16740 * _.truncate('hi-diddly-ho there, neighborino', { 16741 * 'length': 24, 16742 * 'separator': ' ' 16743 * }); 16744 * // => 'hi-diddly-ho there,...' 16745 * 16746 * _.truncate('hi-diddly-ho there, neighborino', { 16747 * 'length': 24, 16748 * 'separator': /,? +/ 16749 * }); 16750 * // => 'hi-diddly-ho there...' 16751 * 16752 * _.truncate('hi-diddly-ho there, neighborino', { 16753 * 'omission': ' [...]' 16754 * }); 16755 * // => 'hi-diddly-ho there, neig [...]' 16756 */ 16757 function truncate(string, options) { 16758 var length = DEFAULT_TRUNC_LENGTH, 16759 omission = DEFAULT_TRUNC_OMISSION; 16760 16761 if (isObject(options)) { 16762 var separator = 'separator' in options ? options.separator : separator; 16763 length = 'length' in options ? toInteger(options.length) : length; 16764 omission = 'omission' in options ? baseToString(options.omission) : omission; 16765 } 16766 string = toString(string); 16767 16768 var strLength = string.length; 16769 if (hasUnicode(string)) { 16770 var strSymbols = stringToArray(string); 16771 strLength = strSymbols.length; 16772 } 16773 if (length >= strLength) { 16774 return string; 16775 } 16776 var end = length - stringSize(omission); 16777 if (end < 1) { 16778 return omission; 16779 } 16780 var result = strSymbols 16781 ? castSlice(strSymbols, 0, end).join('') 16782 : string.slice(0, end); 16783 16784 if (separator === undefined) { 16785 return result + omission; 16786 } 16787 if (strSymbols) { 16788 end += (result.length - end); 16789 } 16790 if (isRegExp(separator)) { 16791 if (string.slice(end).search(separator)) { 16792 var match, 16793 substring = result; 16794 16795 if (!separator.global) { 16796 separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g'); 16797 } 16798 separator.lastIndex = 0; 16799 while ((match = separator.exec(substring))) { 16800 var newEnd = match.index; 16801 } 16802 result = result.slice(0, newEnd === undefined ? end : newEnd); 16803 } 16804 } else if (string.indexOf(baseToString(separator), end) != end) { 16805 var index = result.lastIndexOf(separator); 16806 if (index > -1) { 16807 result = result.slice(0, index); 16808 } 16809 } 16810 return result + omission; 16811 } 16812 16813 /** 16814 * The inverse of `_.escape`; this method converts the HTML entities 16815 * `&`, `<`, `>`, `"`, and `'` in `string` to 16816 * their corresponding characters. 16817 * 16818 * **Note:** No other HTML entities are unescaped. To unescape additional 16819 * HTML entities use a third-party library like [_he_](https://mths.be/he). 16820 * 16821 * @static 16822 * @memberOf _ 16823 * @since 0.6.0 16824 * @category String 16825 * @param {string} [string=''] The string to unescape. 16826 * @returns {string} Returns the unescaped string. 16827 * @example 16828 * 16829 * _.unescape('fred, barney, & pebbles'); 16830 * // => 'fred, barney, & pebbles' 16831 */ 16832 function unescape(string) { 16833 string = toString(string); 16834 return (string && reHasEscapedHtml.test(string)) 16835 ? string.replace(reEscapedHtml, unescapeHtmlChar) 16836 : string; 16837 } 16838 16839 /** 16840 * Converts `string`, as space separated words, to upper case. 16841 * 16842 * @static 16843 * @memberOf _ 16844 * @since 4.0.0 16845 * @category String 16846 * @param {string} [string=''] The string to convert. 16847 * @returns {string} Returns the upper cased string. 16848 * @example 16849 * 16850 * _.upperCase('--foo-bar'); 16851 * // => 'FOO BAR' 16852 * 16853 * _.upperCase('fooBar'); 16854 * // => 'FOO BAR' 16855 * 16856 * _.upperCase('__foo_bar__'); 16857 * // => 'FOO BAR' 16858 */ 16859 var upperCase = createCompounder(function(result, word, index) { 16860 return result + (index ? ' ' : '') + word.toUpperCase(); 16861 }); 16862 16863 /** 16864 * Converts the first character of `string` to upper case. 16865 * 16866 * @static 16867 * @memberOf _ 16868 * @since 4.0.0 16869 * @category String 16870 * @param {string} [string=''] The string to convert. 16871 * @returns {string} Returns the converted string. 16872 * @example 16873 * 16874 * _.upperFirst('fred'); 16875 * // => 'Fred' 16876 * 16877 * _.upperFirst('FRED'); 16878 * // => 'FRED' 16879 */ 16880 var upperFirst = createCaseFirst('toUpperCase'); 16881 16882 /** 16883 * Splits `string` into an array of its words. 16884 * 16885 * @static 16886 * @memberOf _ 16887 * @since 3.0.0 16888 * @category String 16889 * @param {string} [string=''] The string to inspect. 16890 * @param {RegExp|string} [pattern] The pattern to match words. 16891 * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. 16892 * @returns {Array} Returns the words of `string`. 16893 * @example 16894 * 16895 * _.words('fred, barney, & pebbles'); 16896 * // => ['fred', 'barney', 'pebbles'] 16897 * 16898 * _.words('fred, barney, & pebbles', /[^, ]+/g); 16899 * // => ['fred', 'barney', '&', 'pebbles'] 16900 */ 16901 function words(string, pattern, guard) { 16902 string = toString(string); 16903 pattern = guard ? undefined : pattern; 16904 16905 if (pattern === undefined) { 16906 return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string); 16907 } 16908 return string.match(pattern) || []; 16909 } 16910 16911 /*------------------------------------------------------------------------*/ 16912 16913 /** 16914 * Attempts to invoke `func`, returning either the result or the caught error 16915 * object. Any additional arguments are provided to `func` when it's invoked. 16916 * 16917 * @static 16918 * @memberOf _ 16919 * @since 3.0.0 16920 * @category Util 16921 * @param {Function} func The function to attempt. 16922 * @param {...*} [args] The arguments to invoke `func` with. 16923 * @returns {*} Returns the `func` result or error object. 16924 * @example 16925 * 16926 * // Avoid throwing errors for invalid selectors. 16927 * var elements = _.attempt(function(selector) { 16928 * return document.querySelectorAll(selector); 16929 * }, '>_>'); 16930 * 16931 * if (_.isError(elements)) { 16932 * elements = []; 16933 * } 16934 */ 16935 var attempt = baseRest(function(func, args) { 16936 try { 16937 return apply(func, undefined, args); 16938 } catch (e) { 16939 return isError(e) ? e : new Error(e); 16940 } 16941 }); 16942 16943 /** 16944 * Binds methods of an object to the object itself, overwriting the existing 16945 * method. 16946 * 16947 * **Note:** This method doesn't set the "length" property of bound functions. 16948 * 16949 * @static 16950 * @since 0.1.0 16951 * @memberOf _ 16952 * @category Util 16953 * @param {Object} object The object to bind and assign the bound methods to. 16954 * @param {...(string|string[])} methodNames The object method names to bind. 16955 * @returns {Object} Returns `object`. 16956 * @example 16957 * 16958 * var view = { 16959 * 'label': 'docs', 16960 * 'click': function() { 16961 * console.log('clicked ' + this.label); 16962 * } 16963 * }; 16964 * 16965 * _.bindAll(view, ['click']); 16966 * jQuery(element).on('click', view.click); 16967 * // => Logs 'clicked docs' when clicked. 16968 */ 16969 var bindAll = flatRest(function(object, methodNames) { 16970 arrayEach(methodNames, function(key) { 16971 key = toKey(key); 16972 baseAssignValue(object, key, bind(object[key], object)); 16973 }); 16974 return object; 16975 }); 16976 16977 /** 16978 * Creates a function that iterates over `pairs` and invokes the corresponding 16979 * function of the first predicate to return truthy. The predicate-function 16980 * pairs are invoked with the `this` binding and arguments of the created 16981 * function. 16982 * 16983 * @static 16984 * @memberOf _ 16985 * @since 4.0.0 16986 * @category Util 16987 * @param {Array} pairs The predicate-function pairs. 16988 * @returns {Function} Returns the new composite function. 16989 * @example 16990 * 16991 * var func = _.cond([ 16992 * [_.matches({ 'a': 1 }), _.constant('matches A')], 16993 * [_.conforms({ 'b': _.isNumber }), _.constant('matches B')], 16994 * [_.stubTrue, _.constant('no match')] 16995 * ]); 16996 * 16997 * func({ 'a': 1, 'b': 2 }); 16998 * // => 'matches A' 16999 * 17000 * func({ 'a': 0, 'b': 1 }); 17001 * // => 'matches B' 17002 * 17003 * func({ 'a': '1', 'b': '2' }); 17004 * // => 'no match' 17005 */ 17006 function cond(pairs) { 17007 var length = pairs == null ? 0 : pairs.length, 17008 toIteratee = getIteratee(); 17009 17010 pairs = !length ? [] : arrayMap(pairs, function(pair) { 17011 if (typeof pair[1] != 'function') { 17012 throw new TypeError(FUNC_ERROR_TEXT); 17013 } 17014 return [toIteratee(pair[0]), pair[1]]; 17015 }); 17016 17017 return baseRest(function(args) { 17018 var index = -1; 17019 while (++index < length) { 17020 var pair = pairs[index];
vendor: 10,296 bytes, lines 17021-17353
17021 if (apply(pair[0], this, args)) { 17022 return apply(pair[1], this, args); 17023 } 17024 } 17025 }); 17026 } 17027 17028 /** 17029 * Creates a function that invokes the predicate properties of `source` with 17030 * the corresponding property values of a given object, returning `true` if 17031 * all predicates return truthy, else `false`. 17032 * 17033 * **Note:** The created function is equivalent to `_.conformsTo` with 17034 * `source` partially applied. 17035 * 17036 * @static 17037 * @memberOf _ 17038 * @since 4.0.0 17039 * @category Util 17040 * @param {Object} source The object of property predicates to conform to. 17041 * @returns {Function} Returns the new spec function. 17042 * @example 17043 * 17044 * var objects = [ 17045 * { 'a': 2, 'b': 1 }, 17046 * { 'a': 1, 'b': 2 } 17047 * ]; 17048 * 17049 * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } })); 17050 * // => [{ 'a': 1, 'b': 2 }] 17051 */ 17052 function conforms(source) { 17053 return baseConforms(baseClone(source, CLONE_DEEP_FLAG)); 17054 } 17055 17056 /** 17057 * Creates a function that returns `value`. 17058 * 17059 * @static 17060 * @memberOf _ 17061 * @since 2.4.0 17062 * @category Util 17063 * @param {*} value The value to return from the new function. 17064 * @returns {Function} Returns the new constant function. 17065 * @example 17066 * 17067 * var objects = _.times(2, _.constant({ 'a': 1 })); 17068 * 17069 * console.log(objects); 17070 * // => [{ 'a': 1 }, { 'a': 1 }] 17071 * 17072 * console.log(objects[0] === objects[1]); 17073 * // => true 17074 */ 17075 function constant(value) { 17076 return function() { 17077 return value; 17078 }; 17079 } 17080 17081 /** 17082 * Checks `value` to determine whether a default value should be returned in 17083 * its place. The `defaultValue` is returned if `value` is `NaN`, `null`, 17084 * or `undefined`. 17085 * 17086 * @static 17087 * @memberOf _ 17088 * @since 4.14.0 17089 * @category Util 17090 * @param {*} value The value to check. 17091 * @param {*} defaultValue The default value. 17092 * @returns {*} Returns the resolved value. 17093 * @example 17094 * 17095 * _.defaultTo(1, 10); 17096 * // => 1 17097 * 17098 * _.defaultTo(undefined, 10); 17099 * // => 10 17100 */ 17101 function defaultTo(value, defaultValue) { 17102 return (value == null || value !== value) ? defaultValue : value; 17103 } 17104 17105 /** 17106 * Creates a function that returns the result of invoking the given functions 17107 * with the `this` binding of the created function, where each successive 17108 * invocation is supplied the return value of the previous. 17109 * 17110 * @static 17111 * @memberOf _ 17112 * @since 3.0.0 17113 * @category Util 17114 * @param {...(Function|Function[])} [funcs] The functions to invoke. 17115 * @returns {Function} Returns the new composite function. 17116 * @see _.flowRight 17117 * @example 17118 * 17119 * function square(n) { 17120 * return n * n; 17121 * } 17122 * 17123 * var addSquare = _.flow([_.add, square]); 17124 * addSquare(1, 2); 17125 * // => 9 17126 */ 17127 var flow = createFlow(); 17128 17129 /** 17130 * This method is like `_.flow` except that it creates a function that 17131 * invokes the given functions from right to left. 17132 * 17133 * @static 17134 * @since 3.0.0 17135 * @memberOf _ 17136 * @category Util 17137 * @param {...(Function|Function[])} [funcs] The functions to invoke. 17138 * @returns {Function} Returns the new composite function. 17139 * @see _.flow 17140 * @example 17141 * 17142 * function square(n) { 17143 * return n * n; 17144 * } 17145 * 17146 * var addSquare = _.flowRight([square, _.add]); 17147 * addSquare(1, 2); 17148 * // => 9 17149 */ 17150 var flowRight = createFlow(true); 17151 17152 /** 17153 * This method returns the first argument it receives. 17154 * 17155 * @static 17156 * @since 0.1.0 17157 * @memberOf _ 17158 * @category Util 17159 * @param {*} value Any value. 17160 * @returns {*} Returns `value`. 17161 * @example 17162 * 17163 * var object = { 'a': 1 }; 17164 * 17165 * console.log(_.identity(object) === object); 17166 * // => true 17167 */ 17168 function identity(value) { 17169 return value; 17170 } 17171 17172 /** 17173 * Creates a function that invokes `func` with the arguments of the created 17174 * function. If `func` is a property name, the created function returns the 17175 * property value for a given element. If `func` is an array or object, the 17176 * created function returns `true` for elements that contain the equivalent 17177 * source properties, otherwise it returns `false`. 17178 * 17179 * @static 17180 * @since 4.0.0 17181 * @memberOf _ 17182 * @category Util 17183 * @param {*} [func=_.identity] The value to convert to a callback. 17184 * @returns {Function} Returns the callback. 17185 * @example 17186 * 17187 * var users = [ 17188 * { 'user': 'barney', 'age': 36, 'active': true }, 17189 * { 'user': 'fred', 'age': 40, 'active': false } 17190 * ]; 17191 * 17192 * // The `_.matches` iteratee shorthand. 17193 * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true })); 17194 * // => [{ 'user': 'barney', 'age': 36, 'active': true }] 17195 * 17196 * // The `_.matchesProperty` iteratee shorthand. 17197 * _.filter(users, _.iteratee(['user', 'fred'])); 17198 * // => [{ 'user': 'fred', 'age': 40 }] 17199 * 17200 * // The `_.property` iteratee shorthand. 17201 * _.map(users, _.iteratee('user')); 17202 * // => ['barney', 'fred'] 17203 * 17204 * // Create custom iteratee shorthands. 17205 * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) { 17206 * return !_.isRegExp(func) ? iteratee(func) : function(string) { 17207 * return func.test(string); 17208 * }; 17209 * }); 17210 * 17211 * _.filter(['abc', 'def'], /ef/); 17212 * // => ['def'] 17213 */ 17214 function iteratee(func) { 17215 return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG)); 17216 } 17217 17218 /** 17219 * Creates a function that performs a partial deep comparison between a given 17220 * object and `source`, returning `true` if the given object has equivalent 17221 * property values, else `false`. 17222 * 17223 * **Note:** The created function is equivalent to `_.isMatch` with `source` 17224 * partially applied. 17225 * 17226 * Partial comparisons will match empty array and empty object `source` 17227 * values against any array or object value, respectively. See `_.isEqual` 17228 * for a list of supported value comparisons. 17229 * 17230 * **Note:** Multiple values can be checked by combining several matchers 17231 * using `_.overSome` 17232 * 17233 * @static 17234 * @memberOf _ 17235 * @since 3.0.0 17236 * @category Util 17237 * @param {Object} source The object of property values to match. 17238 * @returns {Function} Returns the new spec function. 17239 * @example 17240 * 17241 * var objects = [ 17242 * { 'a': 1, 'b': 2, 'c': 3 }, 17243 * { 'a': 4, 'b': 5, 'c': 6 } 17244 * ]; 17245 * 17246 * _.filter(objects, _.matches({ 'a': 4, 'c': 6 })); 17247 * // => [{ 'a': 4, 'b': 5, 'c': 6 }] 17248 * 17249 * // Checking for several possible values 17250 * _.filter(objects, _.overSome([_.matches({ 'a': 1 }), _.matches({ 'a': 4 })])); 17251 * // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }] 17252 */ 17253 function matches(source) { 17254 return baseMatches(baseClone(source, CLONE_DEEP_FLAG)); 17255 } 17256 17257 /** 17258 * Creates a function that performs a partial deep comparison between the 17259 * value at `path` of a given object to `srcValue`, returning `true` if the 17260 * object value is equivalent, else `false`. 17261 * 17262 * **Note:** Partial comparisons will match empty array and empty object 17263 * `srcValue` values against any array or object value, respectively. See 17264 * `_.isEqual` for a list of supported value comparisons. 17265 * 17266 * **Note:** Multiple values can be checked by combining several matchers 17267 * using `_.overSome` 17268 * 17269 * @static 17270 * @memberOf _ 17271 * @since 3.2.0 17272 * @category Util 17273 * @param {Array|string} path The path of the property to get. 17274 * @param {*} srcValue The value to match. 17275 * @returns {Function} Returns the new spec function. 17276 * @example 17277 * 17278 * var objects = [ 17279 * { 'a': 1, 'b': 2, 'c': 3 }, 17280 * { 'a': 4, 'b': 5, 'c': 6 } 17281 * ]; 17282 * 17283 * _.find(objects, _.matchesProperty('a', 4)); 17284 * // => { 'a': 4, 'b': 5, 'c': 6 } 17285 * 17286 * // Checking for several possible values 17287 * _.filter(objects, _.overSome([_.matchesProperty('a', 1), _.matchesProperty('a', 4)])); 17288 * // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }] 17289 */ 17290 function matchesProperty(path, srcValue) { 17291 return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG)); 17292 } 17293 17294 /** 17295 * Creates a function that invokes the method at `path` of a given object. 17296 * Any additional arguments are provided to the invoked method. 17297 * 17298 * @static 17299 * @memberOf _ 17300 * @since 3.7.0 17301 * @category Util 17302 * @param {Array|string} path The path of the method to invoke. 17303 * @param {...*} [args] The arguments to invoke the method with. 17304 * @returns {Function} Returns the new invoker function. 17305 * @example 17306 * 17307 * var objects = [ 17308 * { 'a': { 'b': _.constant(2) } }, 17309 * { 'a': { 'b': _.constant(1) } } 17310 * ]; 17311 * 17312 * _.map(objects, _.method('a.b')); 17313 * // => [2, 1] 17314 * 17315 * _.map(objects, _.method(['a', 'b'])); 17316 * // => [2, 1] 17317 */ 17318 var method = baseRest(function(path, args) { 17319 return function(object) { 17320 return baseInvoke(object, path, args); 17321 }; 17322 }); 17323 17324 /** 17325 * The opposite of `_.method`; this method creates a function that invokes 17326 * the method at a given path of `object`. Any additional arguments are 17327 * provided to the invoked method. 17328 * 17329 * @static 17330 * @memberOf _ 17331 * @since 3.7.0 17332 * @category Util 17333 * @param {Object} object The object to query. 17334 * @param {...*} [args] The arguments to invoke the method with. 17335 * @returns {Function} Returns the new invoker function. 17336 * @example 17337 * 17338 * var array = _.times(3, _.constant), 17339 * object = { 'a': array, 'b': array, 'c': array }; 17340 * 17341 * _.map(['a[2]', 'c[0]'], _.methodOf(object)); 17342 * // => [2, 0] 17343 * 17344 * _.map([['a', '2'], ['c', '0']], _.methodOf(object)); 17345 * // => [2, 0] 17346 */ 17347 var methodOf = baseRest(function(object, args) { 17348 return function(path) { 17349 return baseInvoke(object, path, args); 17350 }; 17351 }); 17352 17353 /**
vendor: 10,734 bytes, lines 17354-17741
17354 * Adds all own enumerable string keyed function properties of a source 17355 * object to the destination object. If `object` is a function, then methods 17356 * are added to its prototype as well. 17357 * 17358 * **Note:** Use `_.runInContext` to create a pristine `lodash` function to 17359 * avoid conflicts caused by modifying the original. 17360 * 17361 * @static 17362 * @since 0.1.0 17363 * @memberOf _ 17364 * @category Util 17365 * @param {Function|Object} [object=lodash] The destination object. 17366 * @param {Object} source The object of functions to add. 17367 * @param {Object} [options={}] The options object. 17368 * @param {boolean} [options.chain=true] Specify whether mixins are chainable. 17369 * @returns {Function|Object} Returns `object`. 17370 * @example 17371 * 17372 * function vowels(string) { 17373 * return _.filter(string, function(v) { 17374 * return /[aeiou]/i.test(v); 17375 * }); 17376 * } 17377 * 17378 * _.mixin({ 'vowels': vowels }); 17379 * _.vowels('fred'); 17380 * // => ['e'] 17381 * 17382 * _('fred').vowels().value(); 17383 * // => ['e'] 17384 * 17385 * _.mixin({ 'vowels': vowels }, { 'chain': false }); 17386 * _('fred').vowels(); 17387 * // => ['e'] 17388 */ 17389 function mixin(object, source, options) { 17390 var props = keys(source), 17391 methodNames = baseFunctions(source, props); 17392 17393 if (options == null && 17394 !(isObject(source) && (methodNames.length || !props.length))) { 17395 options = source; 17396 source = object; 17397 object = this; 17398 methodNames = baseFunctions(source, keys(source)); 17399 } 17400 var chain = !(isObject(options) && 'chain' in options) || !!options.chain, 17401 isFunc = isFunction(object); 17402 17403 arrayEach(methodNames, function(methodName) { 17404 var func = source[methodName]; 17405 object[methodName] = func; 17406 if (isFunc) { 17407 object.prototype[methodName] = function() { 17408 var chainAll = this.__chain__; 17409 if (chain || chainAll) { 17410 var result = object(this.__wrapped__), 17411 actions = result.__actions__ = copyArray(this.__actions__); 17412 17413 actions.push({ 'func': func, 'args': arguments, 'thisArg': object }); 17414 result.__chain__ = chainAll; 17415 return result; 17416 } 17417 return func.apply(object, arrayPush([this.value()], arguments)); 17418 }; 17419 } 17420 }); 17421 17422 return object; 17423 } 17424 17425 /** 17426 * Reverts the `_` variable to its previous value and returns a reference to 17427 * the `lodash` function. 17428 * 17429 * @static 17430 * @since 0.1.0 17431 * @memberOf _ 17432 * @category Util 17433 * @returns {Function} Returns the `lodash` function. 17434 * @example 17435 * 17436 * var lodash = _.noConflict(); 17437 */ 17438 function noConflict() { 17439 if (root._ === this) { 17440 root._ = oldDash; 17441 } 17442 return this; 17443 } 17444 17445 /** 17446 * This method returns `undefined`. 17447 * 17448 * @static 17449 * @memberOf _ 17450 * @since 2.3.0 17451 * @category Util 17452 * @example 17453 * 17454 * _.times(2, _.noop); 17455 * // => [undefined, undefined] 17456 */ 17457 function noop() { 17458 // No operation performed. 17459 } 17460 17461 /** 17462 * Creates a function that gets the argument at index `n`. If `n` is negative, 17463 * the nth argument from the end is returned. 17464 * 17465 * @static 17466 * @memberOf _ 17467 * @since 4.0.0 17468 * @category Util 17469 * @param {number} [n=0] The index of the argument to return. 17470 * @returns {Function} Returns the new pass-thru function. 17471 * @example 17472 * 17473 * var func = _.nthArg(1); 17474 * func('a', 'b', 'c', 'd'); 17475 * // => 'b' 17476 * 17477 * var func = _.nthArg(-2); 17478 * func('a', 'b', 'c', 'd'); 17479 * // => 'c' 17480 */ 17481 function nthArg(n) { 17482 n = toInteger(n); 17483 return baseRest(function(args) { 17484 return baseNth(args, n); 17485 }); 17486 } 17487 17488 /** 17489 * Creates a function that invokes `iteratees` with the arguments it receives 17490 * and returns their results. 17491 * 17492 * @static 17493 * @memberOf _ 17494 * @since 4.0.0 17495 * @category Util 17496 * @param {...(Function|Function[])} [iteratees=[_.identity]] 17497 * The iteratees to invoke. 17498 * @returns {Function} Returns the new function. 17499 * @example 17500 * 17501 * var func = _.over([Math.max, Math.min]); 17502 * 17503 * func(1, 2, 3, 4); 17504 * // => [4, 1] 17505 */ 17506 var over = createOver(arrayMap); 17507 17508 /** 17509 * Creates a function that checks if **all** of the `predicates` return 17510 * truthy when invoked with the arguments it receives. 17511 * 17512 * Following shorthands are possible for providing predicates. 17513 * Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate. 17514 * Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them. 17515 * 17516 * @static 17517 * @memberOf _ 17518 * @since 4.0.0 17519 * @category Util 17520 * @param {...(Function|Function[])} [predicates=[_.identity]] 17521 * The predicates to check. 17522 * @returns {Function} Returns the new function. 17523 * @example 17524 * 17525 * var func = _.overEvery([Boolean, isFinite]); 17526 * 17527 * func('1'); 17528 * // => true 17529 * 17530 * func(null); 17531 * // => false 17532 * 17533 * func(NaN); 17534 * // => false 17535 */ 17536 var overEvery = createOver(arrayEvery); 17537 17538 /** 17539 * Creates a function that checks if **any** of the `predicates` return 17540 * truthy when invoked with the arguments it receives. 17541 * 17542 * Following shorthands are possible for providing predicates. 17543 * Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate. 17544 * Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them. 17545 * 17546 * @static 17547 * @memberOf _ 17548 * @since 4.0.0 17549 * @category Util 17550 * @param {...(Function|Function[])} [predicates=[_.identity]] 17551 * The predicates to check. 17552 * @returns {Function} Returns the new function. 17553 * @example 17554 * 17555 * var func = _.overSome([Boolean, isFinite]); 17556 * 17557 * func('1'); 17558 * // => true 17559 * 17560 * func(null); 17561 * // => true 17562 * 17563 * func(NaN); 17564 * // => false 17565 * 17566 * var matchesFunc = _.overSome([{ 'a': 1 }, { 'a': 2 }]) 17567 * var matchesPropertyFunc = _.overSome([['a', 1], ['a', 2]]) 17568 */ 17569 var overSome = createOver(arraySome); 17570 17571 /** 17572 * Creates a function that returns the value at `path` of a given object. 17573 * 17574 * @static 17575 * @memberOf _ 17576 * @since 2.4.0 17577 * @category Util 17578 * @param {Array|string} path The path of the property to get. 17579 * @returns {Function} Returns the new accessor function. 17580 * @example 17581 * 17582 * var objects = [ 17583 * { 'a': { 'b': 2 } }, 17584 * { 'a': { 'b': 1 } } 17585 * ]; 17586 * 17587 * _.map(objects, _.property('a.b')); 17588 * // => [2, 1] 17589 * 17590 * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b'); 17591 * // => [1, 2] 17592 */ 17593 function property(path) { 17594 return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path); 17595 } 17596 17597 /** 17598 * The opposite of `_.property`; this method creates a function that returns 17599 * the value at a given path of `object`. 17600 * 17601 * @static 17602 * @memberOf _ 17603 * @since 3.0.0 17604 * @category Util 17605 * @param {Object} object The object to query. 17606 * @returns {Function} Returns the new accessor function. 17607 * @example 17608 * 17609 * var array = [0, 1, 2], 17610 * object = { 'a': array, 'b': array, 'c': array }; 17611 * 17612 * _.map(['a[2]', 'c[0]'], _.propertyOf(object)); 17613 * // => [2, 0] 17614 * 17615 * _.map([['a', '2'], ['c', '0']], _.propertyOf(object)); 17616 * // => [2, 0] 17617 */ 17618 function propertyOf(object) { 17619 return function(path) { 17620 return object == null ? undefined : baseGet(object, path); 17621 }; 17622 } 17623 17624 /** 17625 * Creates an array of numbers (positive and/or negative) progressing from 17626 * `start` up to, but not including, `end`. A step of `-1` is used if a negative 17627 * `start` is specified without an `end` or `step`. If `end` is not specified, 17628 * it's set to `start` with `start` then set to `0`. 17629 * 17630 * **Note:** JavaScript follows the IEEE-754 standard for resolving 17631 * floating-point values which can produce unexpected results. 17632 * 17633 * @static 17634 * @since 0.1.0 17635 * @memberOf _ 17636 * @category Util 17637 * @param {number} [start=0] The start of the range. 17638 * @param {number} end The end of the range. 17639 * @param {number} [step=1] The value to increment or decrement by. 17640 * @returns {Array} Returns the range of numbers. 17641 * @see _.inRange, _.rangeRight 17642 * @example 17643 * 17644 * _.range(4); 17645 * // => [0, 1, 2, 3] 17646 * 17647 * _.range(-4); 17648 * // => [0, -1, -2, -3] 17649 * 17650 * _.range(1, 5); 17651 * // => [1, 2, 3, 4] 17652 * 17653 * _.range(0, 20, 5); 17654 * // => [0, 5, 10, 15] 17655 * 17656 * _.range(0, -4, -1); 17657 * // => [0, -1, -2, -3] 17658 * 17659 * _.range(1, 4, 0); 17660 * // => [1, 1, 1] 17661 * 17662 * _.range(0); 17663 * // => [] 17664 */ 17665 var range = createRange(); 17666 17667 /** 17668 * This method is like `_.range` except that it populates values in 17669 * descending order. 17670 * 17671 * @static 17672 * @memberOf _ 17673 * @since 4.0.0 17674 * @category Util 17675 * @param {number} [start=0] The start of the range. 17676 * @param {number} end The end of the range. 17677 * @param {number} [step=1] The value to increment or decrement by. 17678 * @returns {Array} Returns the range of numbers. 17679 * @see _.inRange, _.range 17680 * @example 17681 * 17682 * _.rangeRight(4); 17683 * // => [3, 2, 1, 0] 17684 * 17685 * _.rangeRight(-4); 17686 * // => [-3, -2, -1, 0] 17687 * 17688 * _.rangeRight(1, 5); 17689 * // => [4, 3, 2, 1] 17690 * 17691 * _.rangeRight(0, 20, 5); 17692 * // => [15, 10, 5, 0] 17693 * 17694 * _.rangeRight(0, -4, -1); 17695 * // => [-3, -2, -1, 0] 17696 * 17697 * _.rangeRight(1, 4, 0); 17698 * // => [1, 1, 1] 17699 * 17700 * _.rangeRight(0); 17701 * // => [] 17702 */ 17703 var rangeRight = createRange(true); 17704 17705 /** 17706 * This method returns a new empty array. 17707 * 17708 * @static 17709 * @memberOf _ 17710 * @since 4.13.0 17711 * @category Util 17712 * @returns {Array} Returns the new empty array. 17713 * @example 17714 * 17715 * var arrays = _.times(2, _.stubArray); 17716 * 17717 * console.log(arrays); 17718 * // => [[], []] 17719 * 17720 * console.log(arrays[0] === arrays[1]); 17721 * // => false 17722 */ 17723 function stubArray() { 17724 return []; 17725 } 17726 17727 /** 17728 * This method returns `false`. 17729 * 17730 * @static 17731 * @memberOf _ 17732 * @since 4.13.0 17733 * @category Util 17734 * @returns {boolean} Returns `false`. 17735 * @example 17736 * 17737 * _.times(2, _.stubFalse); 17738 * // => [false, false] 17739 */ 17740 function stubFalse() { 17741 return false;
vendor: 1,044 bytes, lines 17742-17795
17742 } 17743 17744 /** 17745 * This method returns a new empty object. 17746 * 17747 * @static 17748 * @memberOf _ 17749 * @since 4.13.0 17750 * @category Util 17751 * @returns {Object} Returns the new empty object. 17752 * @example 17753 * 17754 * var objects = _.times(2, _.stubObject); 17755 * 17756 * console.log(objects); 17757 * // => [{}, {}] 17758 * 17759 * console.log(objects[0] === objects[1]); 17760 * // => false 17761 */ 17762 function stubObject() { 17763 return {}; 17764 } 17765 17766 /** 17767 * This method returns an empty string. 17768 * 17769 * @static 17770 * @memberOf _ 17771 * @since 4.13.0 17772 * @category Util 17773 * @returns {string} Returns the empty string. 17774 * @example 17775 * 17776 * _.times(2, _.stubString); 17777 * // => ['', ''] 17778 */ 17779 function stubString() { 17780 return ''; 17781 } 17782 17783 /** 17784 * This method returns `true`. 17785 * 17786 * @static 17787 * @memberOf _ 17788 * @since 4.13.0 17789 * @category Util 17790 * @returns {boolean} Returns `true`. 17791 * @example 17792 * 17793 * _.times(2, _.stubTrue); 17794 * // => [true, true] 17795 */
vendor: 9,081 bytes, lines 17796-18139
17796 function stubTrue() { 17797 return true; 17798 } 17799 17800 /** 17801 * Invokes the iteratee `n` times, returning an array of the results of 17802 * each invocation. The iteratee is invoked with one argument; (index). 17803 * 17804 * @static 17805 * @since 0.1.0 17806 * @memberOf _ 17807 * @category Util 17808 * @param {number} n The number of times to invoke `iteratee`. 17809 * @param {Function} [iteratee=_.identity] The function invoked per iteration. 17810 * @returns {Array} Returns the array of results. 17811 * @example 17812 * 17813 * _.times(3, String); 17814 * // => ['0', '1', '2'] 17815 * 17816 * _.times(4, _.constant(0)); 17817 * // => [0, 0, 0, 0] 17818 */ 17819 function times(n, iteratee) { 17820 n = toInteger(n); 17821 if (n < 1 || n > MAX_SAFE_INTEGER) { 17822 return []; 17823 } 17824 var index = MAX_ARRAY_LENGTH, 17825 length = nativeMin(n, MAX_ARRAY_LENGTH); 17826 17827 iteratee = getIteratee(iteratee); 17828 n -= MAX_ARRAY_LENGTH; 17829 17830 var result = baseTimes(length, iteratee); 17831 while (++index < n) { 17832 iteratee(index); 17833 } 17834 return result; 17835 } 17836 17837 /** 17838 * Converts `value` to a property path array. 17839 * 17840 * @static 17841 * @memberOf _ 17842 * @since 4.0.0 17843 * @category Util 17844 * @param {*} value The value to convert. 17845 * @returns {Array} Returns the new property path array. 17846 * @example 17847 * 17848 * _.toPath('a.b.c'); 17849 * // => ['a', 'b', 'c'] 17850 * 17851 * _.toPath('a[0].b.c'); 17852 * // => ['a', '0', 'b', 'c'] 17853 */ 17854 function toPath(value) { 17855 if (isArray(value)) { 17856 return arrayMap(value, toKey); 17857 } 17858 return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value))); 17859 } 17860 17861 /** 17862 * Generates a unique ID. If `prefix` is given, the ID is appended to it. 17863 * 17864 * @static 17865 * @since 0.1.0 17866 * @memberOf _ 17867 * @category Util 17868 * @param {string} [prefix=''] The value to prefix the ID with. 17869 * @returns {string} Returns the unique ID. 17870 * @example 17871 * 17872 * _.uniqueId('contact_'); 17873 * // => 'contact_104' 17874 * 17875 * _.uniqueId(); 17876 * // => '105' 17877 */ 17878 function uniqueId(prefix) { 17879 var id = ++idCounter; 17880 return toString(prefix) + id; 17881 } 17882 17883 /*------------------------------------------------------------------------*/ 17884 17885 /** 17886 * Adds two numbers. 17887 * 17888 * @static 17889 * @memberOf _ 17890 * @since 3.4.0 17891 * @category Math 17892 * @param {number} augend The first number in an addition. 17893 * @param {number} addend The second number in an addition. 17894 * @returns {number} Returns the total. 17895 * @example 17896 * 17897 * _.add(6, 4); 17898 * // => 10 17899 */ 17900 var add = createMathOperation(function(augend, addend) { 17901 return augend + addend; 17902 }, 0); 17903 17904 /** 17905 * Computes `number` rounded up to `precision`. 17906 * 17907 * @static 17908 * @memberOf _ 17909 * @since 3.10.0 17910 * @category Math 17911 * @param {number} number The number to round up. 17912 * @param {number} [precision=0] The precision to round up to. 17913 * @returns {number} Returns the rounded up number. 17914 * @example 17915 * 17916 * _.ceil(4.006); 17917 * // => 5 17918 * 17919 * _.ceil(6.004, 2); 17920 * // => 6.01 17921 * 17922 * _.ceil(6040, -2); 17923 * // => 6100 17924 */ 17925 var ceil = createRound('ceil'); 17926 17927 /** 17928 * Divide two numbers. 17929 * 17930 * @static 17931 * @memberOf _ 17932 * @since 4.7.0 17933 * @category Math 17934 * @param {number} dividend The first number in a division. 17935 * @param {number} divisor The second number in a division. 17936 * @returns {number} Returns the quotient. 17937 * @example 17938 * 17939 * _.divide(6, 4); 17940 * // => 1.5 17941 */ 17942 var divide = createMathOperation(function(dividend, divisor) { 17943 return dividend / divisor; 17944 }, 1); 17945 17946 /** 17947 * Computes `number` rounded down to `precision`. 17948 * 17949 * @static 17950 * @memberOf _ 17951 * @since 3.10.0 17952 * @category Math 17953 * @param {number} number The number to round down. 17954 * @param {number} [precision=0] The precision to round down to. 17955 * @returns {number} Returns the rounded down number. 17956 * @example 17957 * 17958 * _.floor(4.006); 17959 * // => 4 17960 * 17961 * _.floor(0.046, 2); 17962 * // => 0.04 17963 * 17964 * _.floor(4060, -2); 17965 * // => 4000 17966 */ 17967 var floor = createRound('floor'); 17968 17969 /** 17970 * Computes the maximum value of `array`. If `array` is empty or falsey, 17971 * `undefined` is returned. 17972 * 17973 * @static 17974 * @since 0.1.0 17975 * @memberOf _ 17976 * @category Math 17977 * @param {Array} array The array to iterate over. 17978 * @returns {*} Returns the maximum value. 17979 * @example 17980 * 17981 * _.max([4, 2, 8, 6]); 17982 * // => 8 17983 * 17984 * _.max([]); 17985 * // => undefined 17986 */ 17987 function max(array) { 17988 return (array && array.length) 17989 ? baseExtremum(array, identity, baseGt) 17990 : undefined; 17991 } 17992 17993 /** 17994 * This method is like `_.max` except that it accepts `iteratee` which is 17995 * invoked for each element in `array` to generate the criterion by which 17996 * the value is ranked. The iteratee is invoked with one argument: (value). 17997 * 17998 * @static 17999 * @memberOf _ 18000 * @since 4.0.0 18001 * @category Math 18002 * @param {Array} array The array to iterate over. 18003 * @param {Function} [iteratee=_.identity] The iteratee invoked per element. 18004 * @returns {*} Returns the maximum value. 18005 * @example 18006 * 18007 * var objects = [{ 'n': 1 }, { 'n': 2 }]; 18008 * 18009 * _.maxBy(objects, function(o) { return o.n; }); 18010 * // => { 'n': 2 } 18011 * 18012 * // The `_.property` iteratee shorthand. 18013 * _.maxBy(objects, 'n'); 18014 * // => { 'n': 2 } 18015 */ 18016 function maxBy(array, iteratee) { 18017 return (array && array.length) 18018 ? baseExtremum(array, getIteratee(iteratee, 2), baseGt) 18019 : undefined; 18020 } 18021 18022 /** 18023 * Computes the mean of the values in `array`. 18024 * 18025 * @static 18026 * @memberOf _ 18027 * @since 4.0.0 18028 * @category Math 18029 * @param {Array} array The array to iterate over. 18030 * @returns {number} Returns the mean. 18031 * @example 18032 * 18033 * _.mean([4, 2, 8, 6]); 18034 * // => 5 18035 */ 18036 function mean(array) { 18037 return baseMean(array, identity); 18038 } 18039 18040 /** 18041 * This method is like `_.mean` except that it accepts `iteratee` which is 18042 * invoked for each element in `array` to generate the value to be averaged. 18043 * The iteratee is invoked with one argument: (value). 18044 * 18045 * @static 18046 * @memberOf _ 18047 * @since 4.7.0 18048 * @category Math 18049 * @param {Array} array The array to iterate over. 18050 * @param {Function} [iteratee=_.identity] The iteratee invoked per element. 18051 * @returns {number} Returns the mean. 18052 * @example 18053 * 18054 * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }]; 18055 * 18056 * _.meanBy(objects, function(o) { return o.n; }); 18057 * // => 5 18058 * 18059 * // The `_.property` iteratee shorthand. 18060 * _.meanBy(objects, 'n'); 18061 * // => 5 18062 */ 18063 function meanBy(array, iteratee) { 18064 return baseMean(array, getIteratee(iteratee, 2)); 18065 } 18066 18067 /** 18068 * Computes the minimum value of `array`. If `array` is empty or falsey, 18069 * `undefined` is returned. 18070 * 18071 * @static 18072 * @since 0.1.0 18073 * @memberOf _ 18074 * @category Math 18075 * @param {Array} array The array to iterate over. 18076 * @returns {*} Returns the minimum value. 18077 * @example 18078 * 18079 * _.min([4, 2, 8, 6]); 18080 * // => 2 18081 * 18082 * _.min([]); 18083 * // => undefined 18084 */ 18085 function min(array) { 18086 return (array && array.length) 18087 ? baseExtremum(array, identity, baseLt) 18088 : undefined; 18089 } 18090 18091 /** 18092 * This method is like `_.min` except that it accepts `iteratee` which is 18093 * invoked for each element in `array` to generate the criterion by which 18094 * the value is ranked. The iteratee is invoked with one argument: (value). 18095 * 18096 * @static 18097 * @memberOf _ 18098 * @since 4.0.0 18099 * @category Math 18100 * @param {Array} array The array to iterate over. 18101 * @param {Function} [iteratee=_.identity] The iteratee invoked per element. 18102 * @returns {*} Returns the minimum value. 18103 * @example 18104 * 18105 * var objects = [{ 'n': 1 }, { 'n': 2 }]; 18106 * 18107 * _.minBy(objects, function(o) { return o.n; }); 18108 * // => { 'n': 1 } 18109 * 18110 * // The `_.property` iteratee shorthand. 18111 * _.minBy(objects, 'n'); 18112 * // => { 'n': 1 } 18113 */ 18114 function minBy(array, iteratee) { 18115 return (array && array.length) 18116 ? baseExtremum(array, getIteratee(iteratee, 2), baseLt) 18117 : undefined; 18118 } 18119 18120 /** 18121 * Multiply two numbers. 18122 * 18123 * @static 18124 * @memberOf _ 18125 * @since 4.7.0 18126 * @category Math 18127 * @param {number} multiplier The first number in a multiplication. 18128 * @param {number} multiplicand The second number in a multiplication. 18129 * @returns {number} Returns the product. 18130 * @example 18131 * 18132 * _.multiply(6, 4); 18133 * // => 24 18134 */ 18135 var multiply = createMathOperation(function(multiplier, multiplicand) { 18136 return multiplier * multiplicand; 18137 }, 1); 18138 18139 /**
vendor: 13,137 bytes, lines 18140-18578
18140 * Computes `number` rounded to `precision`. 18141 * 18142 * @static 18143 * @memberOf _ 18144 * @since 3.10.0 18145 * @category Math 18146 * @param {number} number The number to round. 18147 * @param {number} [precision=0] The precision to round to. 18148 * @returns {number} Returns the rounded number. 18149 * @example 18150 * 18151 * _.round(4.006); 18152 * // => 4 18153 * 18154 * _.round(4.006, 2); 18155 * // => 4.01 18156 * 18157 * _.round(4060, -2); 18158 * // => 4100 18159 */ 18160 var round = createRound('round'); 18161 18162 /** 18163 * Subtract two numbers. 18164 * 18165 * @static 18166 * @memberOf _ 18167 * @since 4.0.0 18168 * @category Math 18169 * @param {number} minuend The first number in a subtraction. 18170 * @param {number} subtrahend The second number in a subtraction. 18171 * @returns {number} Returns the difference. 18172 * @example 18173 * 18174 * _.subtract(6, 4); 18175 * // => 2 18176 */ 18177 var subtract = createMathOperation(function(minuend, subtrahend) { 18178 return minuend - subtrahend; 18179 }, 0); 18180 18181 /** 18182 * Computes the sum of the values in `array`. 18183 * 18184 * @static 18185 * @memberOf _ 18186 * @since 3.4.0 18187 * @category Math 18188 * @param {Array} array The array to iterate over. 18189 * @returns {number} Returns the sum. 18190 * @example 18191 * 18192 * _.sum([4, 2, 8, 6]); 18193 * // => 20 18194 */ 18195 function sum(array) { 18196 return (array && array.length) 18197 ? baseSum(array, identity) 18198 : 0; 18199 } 18200 18201 /** 18202 * This method is like `_.sum` except that it accepts `iteratee` which is 18203 * invoked for each element in `array` to generate the value to be summed. 18204 * The iteratee is invoked with one argument: (value). 18205 * 18206 * @static 18207 * @memberOf _ 18208 * @since 4.0.0 18209 * @category Math 18210 * @param {Array} array The array to iterate over. 18211 * @param {Function} [iteratee=_.identity] The iteratee invoked per element. 18212 * @returns {number} Returns the sum. 18213 * @example 18214 * 18215 * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }]; 18216 * 18217 * _.sumBy(objects, function(o) { return o.n; }); 18218 * // => 20 18219 * 18220 * // The `_.property` iteratee shorthand. 18221 * _.sumBy(objects, 'n'); 18222 * // => 20 18223 */ 18224 function sumBy(array, iteratee) { 18225 return (array && array.length) 18226 ? baseSum(array, getIteratee(iteratee, 2)) 18227 : 0; 18228 } 18229 18230 /*------------------------------------------------------------------------*/ 18231 18232 // Add methods that return wrapped values in chain sequences. 18233 lodash.after = after; 18234 lodash.ary = ary; 18235 lodash.assign = assign; 18236 lodash.assignIn = assignIn; 18237 lodash.assignInWith = assignInWith; 18238 lodash.assignWith = assignWith; 18239 lodash.at = at; 18240 lodash.before = before; 18241 lodash.bind = bind; 18242 lodash.bindAll = bindAll; 18243 lodash.bindKey = bindKey; 18244 lodash.castArray = castArray; 18245 lodash.chain = chain; 18246 lodash.chunk = chunk; 18247 lodash.compact = compact; 18248 lodash.concat = concat; 18249 lodash.cond = cond; 18250 lodash.conforms = conforms; 18251 lodash.constant = constant; 18252 lodash.countBy = countBy; 18253 lodash.create = create; 18254 lodash.curry = curry; 18255 lodash.curryRight = curryRight; 18256 lodash.debounce = debounce; 18257 lodash.defaults = defaults; 18258 lodash.defaultsDeep = defaultsDeep; 18259 lodash.defer = defer; 18260 lodash.delay = delay; 18261 lodash.difference = difference; 18262 lodash.differenceBy = differenceBy; 18263 lodash.differenceWith = differenceWith; 18264 lodash.drop = drop; 18265 lodash.dropRight = dropRight; 18266 lodash.dropRightWhile = dropRightWhile; 18267 lodash.dropWhile = dropWhile; 18268 lodash.fill = fill; 18269 lodash.filter = filter; 18270 lodash.flatMap = flatMap; 18271 lodash.flatMapDeep = flatMapDeep; 18272 lodash.flatMapDepth = flatMapDepth; 18273 lodash.flatten = flatten; 18274 lodash.flattenDeep = flattenDeep; 18275 lodash.flattenDepth = flattenDepth; 18276 lodash.flip = flip; 18277 lodash.flow = flow; 18278 lodash.flowRight = flowRight; 18279 lodash.fromPairs = fromPairs; 18280 lodash.functions = functions; 18281 lodash.functionsIn = functionsIn; 18282 lodash.groupBy = groupBy; 18283 lodash.initial = initial; 18284 lodash.intersection = intersection; 18285 lodash.intersectionBy = intersectionBy; 18286 lodash.intersectionWith = intersectionWith; 18287 lodash.invert = invert; 18288 lodash.invertBy = invertBy; 18289 lodash.invokeMap = invokeMap; 18290 lodash.iteratee = iteratee; 18291 lodash.keyBy = keyBy; 18292 lodash.keys = keys; 18293 lodash.keysIn = keysIn; 18294 lodash.map = map; 18295 lodash.mapKeys = mapKeys; 18296 lodash.mapValues = mapValues; 18297 lodash.matches = matches; 18298 lodash.matchesProperty = matchesProperty; 18299 lodash.memoize = memoize; 18300 lodash.merge = merge; 18301 lodash.mergeWith = mergeWith; 18302 lodash.method = method; 18303 lodash.methodOf = methodOf; 18304 lodash.mixin = mixin; 18305 lodash.negate = negate; 18306 lodash.nthArg = nthArg; 18307 lodash.omit = omit; 18308 lodash.omitBy = omitBy; 18309 lodash.once = once; 18310 lodash.orderBy = orderBy; 18311 lodash.over = over; 18312 lodash.overArgs = overArgs; 18313 lodash.overEvery = overEvery; 18314 lodash.overSome = overSome; 18315 lodash.partial = partial; 18316 lodash.partialRight = partialRight; 18317 lodash.partition = partition; 18318 lodash.pick = pick; 18319 lodash.pickBy = pickBy; 18320 lodash.property = property; 18321 lodash.propertyOf = propertyOf; 18322 lodash.pull = pull; 18323 lodash.pullAll = pullAll; 18324 lodash.pullAllBy = pullAllBy; 18325 lodash.pullAllWith = pullAllWith; 18326 lodash.pullAt = pullAt; 18327 lodash.range = range; 18328 lodash.rangeRight = rangeRight; 18329 lodash.rearg = rearg; 18330 lodash.reject = reject; 18331 lodash.remove = remove; 18332 lodash.rest = rest; 18333 lodash.reverse = reverse; 18334 lodash.sampleSize = sampleSize; 18335 lodash.set = set; 18336 lodash.setWith = setWith; 18337 lodash.shuffle = shuffle; 18338 lodash.slice = slice; 18339 lodash.sortBy = sortBy; 18340 lodash.sortedUniq = sortedUniq; 18341 lodash.sortedUniqBy = sortedUniqBy; 18342 lodash.split = split; 18343 lodash.spread = spread; 18344 lodash.tail = tail; 18345 lodash.take = take; 18346 lodash.takeRight = takeRight; 18347 lodash.takeRightWhile = takeRightWhile; 18348 lodash.takeWhile = takeWhile; 18349 lodash.tap = tap; 18350 lodash.throttle = throttle; 18351 lodash.thru = thru; 18352 lodash.toArray = toArray; 18353 lodash.toPairs = toPairs; 18354 lodash.toPairsIn = toPairsIn; 18355 lodash.toPath = toPath; 18356 lodash.toPlainObject = toPlainObject; 18357 lodash.transform = transform; 18358 lodash.unary = unary; 18359 lodash.union = union; 18360 lodash.unionBy = unionBy; 18361 lodash.unionWith = unionWith; 18362 lodash.uniq = uniq; 18363 lodash.uniqBy = uniqBy; 18364 lodash.uniqWith = uniqWith; 18365 lodash.unset = unset; 18366 lodash.unzip = unzip; 18367 lodash.unzipWith = unzipWith; 18368 lodash.update = update; 18369 lodash.updateWith = updateWith; 18370 lodash.values = values; 18371 lodash.valuesIn = valuesIn; 18372 lodash.without = without; 18373 lodash.words = words; 18374 lodash.wrap = wrap; 18375 lodash.xor = xor; 18376 lodash.xorBy = xorBy; 18377 lodash.xorWith = xorWith; 18378 lodash.zip = zip; 18379 lodash.zipObject = zipObject; 18380 lodash.zipObjectDeep = zipObjectDeep; 18381 lodash.zipWith = zipWith; 18382 18383 // Add aliases. 18384 lodash.entries = toPairs; 18385 lodash.entriesIn = toPairsIn; 18386 lodash.extend = assignIn; 18387 lodash.extendWith = assignInWith; 18388 18389 // Add methods to `lodash.prototype`. 18390 mixin(lodash, lodash); 18391 18392 /*------------------------------------------------------------------------*/ 18393 18394 // Add methods that return unwrapped values in chain sequences. 18395 lodash.add = add; 18396 lodash.attempt = attempt; 18397 lodash.camelCase = camelCase; 18398 lodash.capitalize = capitalize; 18399 lodash.ceil = ceil; 18400 lodash.clamp = clamp; 18401 lodash.clone = clone; 18402 lodash.cloneDeep = cloneDeep; 18403 lodash.cloneDeepWith = cloneDeepWith; 18404 lodash.cloneWith = cloneWith; 18405 lodash.conformsTo = conformsTo; 18406 lodash.deburr = deburr; 18407 lodash.defaultTo = defaultTo; 18408 lodash.divide = divide; 18409 lodash.endsWith = endsWith; 18410 lodash.eq = eq; 18411 lodash.escape = escape; 18412 lodash.escapeRegExp = escapeRegExp; 18413 lodash.every = every; 18414 lodash.find = find; 18415 lodash.findIndex = findIndex; 18416 lodash.findKey = findKey; 18417 lodash.findLast = findLast; 18418 lodash.findLastIndex = findLastIndex; 18419 lodash.findLastKey = findLastKey; 18420 lodash.floor = floor; 18421 lodash.forEach = forEach; 18422 lodash.forEachRight = forEachRight; 18423 lodash.forIn = forIn; 18424 lodash.forInRight = forInRight; 18425 lodash.forOwn = forOwn; 18426 lodash.forOwnRight = forOwnRight; 18427 lodash.get = get; 18428 lodash.gt = gt; 18429 lodash.gte = gte; 18430 lodash.has = has; 18431 lodash.hasIn = hasIn; 18432 lodash.head = head; 18433 lodash.identity = identity; 18434 lodash.includes = includes; 18435 lodash.indexOf = indexOf; 18436 lodash.inRange = inRange; 18437 lodash.invoke = invoke; 18438 lodash.isArguments = isArguments; 18439 lodash.isArray = isArray; 18440 lodash.isArrayBuffer = isArrayBuffer; 18441 lodash.isArrayLike = isArrayLike; 18442 lodash.isArrayLikeObject = isArrayLikeObject; 18443 lodash.isBoolean = isBoolean; 18444 lodash.isBuffer = isBuffer; 18445 lodash.isDate = isDate; 18446 lodash.isElement = isElement; 18447 lodash.isEmpty = isEmpty; 18448 lodash.isEqual = isEqual; 18449 lodash.isEqualWith = isEqualWith; 18450 lodash.isError = isError; 18451 lodash.isFinite = isFinite; 18452 lodash.isFunction = isFunction; 18453 lodash.isInteger = isInteger; 18454 lodash.isLength = isLength; 18455 lodash.isMap = isMap; 18456 lodash.isMatch = isMatch; 18457 lodash.isMatchWith = isMatchWith; 18458 lodash.isNaN = isNaN; 18459 lodash.isNative = isNative; 18460 lodash.isNil = isNil; 18461 lodash.isNull = isNull; 18462 lodash.isNumber = isNumber; 18463 lodash.isObject = isObject; 18464 lodash.isObjectLike = isObjectLike; 18465 lodash.isPlainObject = isPlainObject; 18466 lodash.isRegExp = isRegExp; 18467 lodash.isSafeInteger = isSafeInteger; 18468 lodash.isSet = isSet; 18469 lodash.isString = isString; 18470 lodash.isSymbol = isSymbol; 18471 lodash.isTypedArray = isTypedArray; 18472 lodash.isUndefined = isUndefined; 18473 lodash.isWeakMap = isWeakMap; 18474 lodash.isWeakSet = isWeakSet; 18475 lodash.join = join; 18476 lodash.kebabCase = kebabCase; 18477 lodash.last = last; 18478 lodash.lastIndexOf = lastIndexOf; 18479 lodash.lowerCase = lowerCase; 18480 lodash.lowerFirst = lowerFirst; 18481 lodash.lt = lt; 18482 lodash.lte = lte; 18483 lodash.max = max; 18484 lodash.maxBy = maxBy; 18485 lodash.mean = mean; 18486 lodash.meanBy = meanBy; 18487 lodash.min = min; 18488 lodash.minBy = minBy; 18489 lodash.stubArray = stubArray; 18490 lodash.stubFalse = stubFalse; 18491 lodash.stubObject = stubObject; 18492 lodash.stubString = stubString; 18493 lodash.stubTrue = stubTrue; 18494 lodash.multiply = multiply; 18495 lodash.nth = nth; 18496 lodash.noConflict = noConflict; 18497 lodash.noop = noop; 18498 lodash.now = now; 18499 lodash.pad = pad; 18500 lodash.padEnd = padEnd; 18501 lodash.padStart = padStart; 18502 lodash.parseInt = parseInt; 18503 lodash.random = random; 18504 lodash.reduce = reduce; 18505 lodash.reduceRight = reduceRight; 18506 lodash.repeat = repeat; 18507 lodash.replace = replace; 18508 lodash.result = result; 18509 lodash.round = round; 18510 lodash.runInContext = runInContext; 18511 lodash.sample = sample; 18512 lodash.size = size; 18513 lodash.snakeCase = snakeCase; 18514 lodash.some = some; 18515 lodash.sortedIndex = sortedIndex; 18516 lodash.sortedIndexBy = sortedIndexBy; 18517 lodash.sortedIndexOf = sortedIndexOf; 18518 lodash.sortedLastIndex = sortedLastIndex; 18519 lodash.sortedLastIndexBy = sortedLastIndexBy; 18520 lodash.sortedLastIndexOf = sortedLastIndexOf; 18521 lodash.startCase = startCase; 18522 lodash.startsWith = startsWith; 18523 lodash.subtract = subtract; 18524 lodash.sum = sum; 18525 lodash.sumBy = sumBy; 18526 lodash.template = template; 18527 lodash.times = times; 18528 lodash.toFinite = toFinite; 18529 lodash.toInteger = toInteger; 18530 lodash.toLength = toLength; 18531 lodash.toLower = toLower; 18532 lodash.toNumber = toNumber; 18533 lodash.toSafeInteger = toSafeInteger; 18534 lodash.toString = toString; 18535 lodash.toUpper = toUpper; 18536 lodash.trim = trim; 18537 lodash.trimEnd = trimEnd; 18538 lodash.trimStart = trimStart; 18539 lodash.truncate = truncate; 18540 lodash.unescape = unescape; 18541 lodash.uniqueId = uniqueId; 18542 lodash.upperCase = upperCase; 18543 lodash.upperFirst = upperFirst; 18544 18545 // Add aliases. 18546 lodash.each = forEach; 18547 lodash.eachRight = forEachRight; 18548 lodash.first = head; 18549 18550 mixin(lodash, (function() { 18551 var source = {}; 18552 baseForOwn(lodash, function(func, methodName) { 18553 if (!hasOwnProperty.call(lodash.prototype, methodName)) { 18554 source[methodName] = func; 18555 } 18556 }); 18557 return source; 18558 }()), { 'chain': false }); 18559 18560 /*------------------------------------------------------------------------*/ 18561 18562 /** 18563 * The semantic version number. 18564 * 18565 * @static 18566 * @memberOf _ 18567 * @type {string} 18568 */ 18569 lodash.VERSION = VERSION; 18570 18571 // Assign default placeholders. 18572 arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) { 18573 lodash[methodName].placeholder = lodash; 18574 }); 18575 18576 // Add `LazyWrapper` methods for `_.drop` and `_.take` variants. 18577 arrayEach(['drop', 'take'], function(methodName, index) { 18578 LazyWrapper.prototype[methodName] = function(n) {
vendor: 7,434 bytes, lines 18579-18796
18579 n = n === undefined ? 1 : nativeMax(toInteger(n), 0); 18580 18581 var result = (this.__filtered__ && !index) 18582 ? new LazyWrapper(this) 18583 : this.clone(); 18584 18585 if (result.__filtered__) { 18586 result.__takeCount__ = nativeMin(n, result.__takeCount__); 18587 } else { 18588 result.__views__.push({ 18589 'size': nativeMin(n, MAX_ARRAY_LENGTH), 18590 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') 18591 }); 18592 } 18593 return result; 18594 }; 18595 18596 LazyWrapper.prototype[methodName + 'Right'] = function(n) { 18597 return this.reverse()[methodName](n).reverse(); 18598 }; 18599 }); 18600 18601 // Add `LazyWrapper` methods that accept an `iteratee` value. 18602 arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) { 18603 var type = index + 1, 18604 isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG; 18605 18606 LazyWrapper.prototype[methodName] = function(iteratee) { 18607 var result = this.clone(); 18608 result.__iteratees__.push({ 18609 'iteratee': getIteratee(iteratee, 3), 18610 'type': type 18611 }); 18612 result.__filtered__ = result.__filtered__ || isFilter; 18613 return result; 18614 }; 18615 }); 18616 18617 // Add `LazyWrapper` methods for `_.head` and `_.last`. 18618 arrayEach(['head', 'last'], function(methodName, index) { 18619 var takeName = 'take' + (index ? 'Right' : ''); 18620 18621 LazyWrapper.prototype[methodName] = function() { 18622 return this[takeName](1).value()[0]; 18623 }; 18624 }); 18625 18626 // Add `LazyWrapper` methods for `_.initial` and `_.tail`. 18627 arrayEach(['initial', 'tail'], function(methodName, index) { 18628 var dropName = 'drop' + (index ? '' : 'Right'); 18629 18630 LazyWrapper.prototype[methodName] = function() { 18631 return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1); 18632 }; 18633 }); 18634 18635 LazyWrapper.prototype.compact = function() { 18636 return this.filter(identity); 18637 }; 18638 18639 LazyWrapper.prototype.find = function(predicate) { 18640 return this.filter(predicate).head(); 18641 }; 18642 18643 LazyWrapper.prototype.findLast = function(predicate) { 18644 return this.reverse().find(predicate); 18645 }; 18646 18647 LazyWrapper.prototype.invokeMap = baseRest(function(path, args) { 18648 if (typeof path == 'function') { 18649 return new LazyWrapper(this); 18650 } 18651 return this.map(function(value) { 18652 return baseInvoke(value, path, args); 18653 }); 18654 }); 18655 18656 LazyWrapper.prototype.reject = function(predicate) { 18657 return this.filter(negate(getIteratee(predicate))); 18658 }; 18659 18660 LazyWrapper.prototype.slice = function(start, end) { 18661 start = toInteger(start); 18662 18663 var result = this; 18664 if (result.__filtered__ && (start > 0 || end < 0)) { 18665 return new LazyWrapper(result); 18666 } 18667 if (start < 0) { 18668 result = result.takeRight(-start); 18669 } else if (start) { 18670 result = result.drop(start); 18671 } 18672 if (end !== undefined) { 18673 end = toInteger(end); 18674 result = end < 0 ? result.dropRight(-end) : result.take(end - start); 18675 } 18676 return result; 18677 }; 18678 18679 LazyWrapper.prototype.takeRightWhile = function(predicate) { 18680 return this.reverse().takeWhile(predicate).reverse(); 18681 }; 18682 18683 LazyWrapper.prototype.toArray = function() { 18684 return this.take(MAX_ARRAY_LENGTH); 18685 }; 18686 18687 // Add `LazyWrapper` methods to `lodash.prototype`. 18688 baseForOwn(LazyWrapper.prototype, function(func, methodName) { 18689 var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName), 18690 isTaker = /^(?:head|last)$/.test(methodName), 18691 lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName], 18692 retUnwrapped = isTaker || /^find/.test(methodName); 18693 18694 if (!lodashFunc) { 18695 return; 18696 } 18697 lodash.prototype[methodName] = function() { 18698 var value = this.__wrapped__, 18699 args = isTaker ? [1] : arguments, 18700 isLazy = value instanceof LazyWrapper, 18701 iteratee = args[0], 18702 useLazy = isLazy || isArray(value); 18703 18704 var interceptor = function(value) { 18705 var result = lodashFunc.apply(lodash, arrayPush([value], args)); 18706 return (isTaker && chainAll) ? result[0] : result; 18707 }; 18708 18709 if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) { 18710 // Avoid lazy use if the iteratee has a "length" value other than `1`. 18711 isLazy = useLazy = false; 18712 } 18713 var chainAll = this.__chain__, 18714 isHybrid = !!this.__actions__.length, 18715 isUnwrapped = retUnwrapped && !chainAll, 18716 onlyLazy = isLazy && !isHybrid; 18717 18718 if (!retUnwrapped && useLazy) { 18719 value = onlyLazy ? value : new LazyWrapper(this); 18720 var result = func.apply(value, args); 18721 result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined }); 18722 return new LodashWrapper(result, chainAll); 18723 } 18724 if (isUnwrapped && onlyLazy) { 18725 return func.apply(this, args); 18726 } 18727 result = this.thru(interceptor); 18728 return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result; 18729 }; 18730 }); 18731 18732 // Add `Array` methods to `lodash.prototype`. 18733 arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) { 18734 var func = arrayProto[methodName], 18735 chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru', 18736 retUnwrapped = /^(?:pop|shift)$/.test(methodName); 18737 18738 lodash.prototype[methodName] = function() { 18739 var args = arguments; 18740 if (retUnwrapped && !this.__chain__) { 18741 var value = this.value(); 18742 return func.apply(isArray(value) ? value : [], args); 18743 } 18744 return this[chainName](function(value) { 18745 return func.apply(isArray(value) ? value : [], args); 18746 }); 18747 }; 18748 }); 18749 18750 // Map minified method names to their real names. 18751 baseForOwn(LazyWrapper.prototype, function(func, methodName) { 18752 var lodashFunc = lodash[methodName]; 18753 if (lodashFunc) { 18754 var key = lodashFunc.name + ''; 18755 if (!hasOwnProperty.call(realNames, key)) { 18756 realNames[key] = []; 18757 } 18758 realNames[key].push({ 'name': methodName, 'func': lodashFunc }); 18759 } 18760 }); 18761 18762 realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [{ 18763 'name': 'wrapper', 18764 'func': undefined 18765 }]; 18766 18767 // Add methods to `LazyWrapper`. 18768 LazyWrapper.prototype.clone = lazyClone; 18769 LazyWrapper.prototype.reverse = lazyReverse; 18770 LazyWrapper.prototype.value = lazyValue; 18771 18772 // Add chain sequence methods to the `lodash` wrapper. 18773 lodash.prototype.at = wrapperAt; 18774 lodash.prototype.chain = wrapperChain; 18775 lodash.prototype.commit = wrapperCommit; 18776 lodash.prototype.next = wrapperNext; 18777 lodash.prototype.plant = wrapperPlant; 18778 lodash.prototype.reverse = wrapperReverse; 18779 lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; 18780 18781 // Add lazy aliases. 18782 lodash.prototype.first = lodash.prototype.head; 18783 18784 if (symIterator) { 18785 lodash.prototype[symIterator] = wrapperToIterator; 18786 } 18787 return lodash; 18788 }); 18789 18790 /*--------------------------------------------------------------------------*/ 18791 18792 // Export lodash. 18793 var _ = runInContext(); 18794 18795 // Some AMD build optimizers, like r.js, check for condition patterns like: 18796 if (t
18796ypeof define == 'function' && typeof define.amd == 'object' && define.amd) { 18797 // Expose Lodash on the global object to prevent errors when Lodash is 18798 // loaded by a script tag in the presence of an AMD loader. 18799 // See http://requirejs.org/docs/errors.html#mismatch for more details. 18800 // Use `_.noConflict` to remove Lodash from the global object. 18801 root._ = _; 18802 18803 // Define as an anonymous module so, through path mapping, it can be 18804 // referenced as the "underscore" module. 18805 define(function() { 18806 return _; 18807 }); 18808 } 18809 // Check for `exports` after `define` in case a build optimizer adds it. 18810 else if (freeModule) { 18811 // Export for Node.js. 18812 (freeModule.exports = _)._ = _; 18813 // Export for CommonJS support. 18814 freeExports._ = _; 18815 } 18816 else { 18817 // Export to the global object. 18818 root._ = _; 18819 } 18820}.call(this)); 18821/*globals define,module */ 18822 18823/*! 18824 * simple-namespace 18825 * https://github.com/drzax/simple-namespace 18826 * 18827 * @version 0.2.0 18828 * @copyright Simon Elvery 18829 * @license MIT 18830 * 18831 */ 18832(function(){ 18833 18834 // most likely `window` 18835 var _this = this; 18836 18837 // the main function 18838 function main(ns, root) { 18839 var parts, part, space; 18840 18841 root = root || _this; 18842 parts = ns.split('.'); 18843 part = parts.shift(); 18844 while (part) { 18845 space = root[part] || {}; 18846 root = root[part] = space; 18847 part = parts.shift(); 18848 } 18849 return space; 18850 } 18851 18852 // export 18853 if (typeof define === "function" && define.amd) { 18854 define(main); 18855 } else if (typeof module === "object" && module.exports) { 18856 module.exports = main; 18857 } else { 18858 _this.ns = main; 18859 } 18860 18861}()); 18862 18863/** 18864 * isMobile.js v0.4.1 18865 * 18866 * A simple library to detect Apple phones and tablets, 18867 * Android phones and tablets, other mobile devices (like blackberry, mini-opera and windows phone), 18868 * and any kind of seven inch device, via user agent sniffing. 18869 * 18870 * @author: Kai Mallea ([email protected]) 18871 * 18872 * @license: http://creativecommons.org/publicdomain/zero/1.0/ 18873 */ 18874(function (global) { 18875 18876 var apple_phone = /iPhone/i, 18877 apple_ipod = /iPod/i, 18878 apple_tablet = /iPad/i, 18879 android_phone = /(?=.*\bAndroid\b)(?=.*\bMobile\b)/i, // Match 'Android' AND 'Mobile' 18880 android_tablet = /Android/i, 18881 amazon_phone = /(?=.*\bAndroid\b)(?=.*\bSD4930UR\b)/i, 18882 amazon_tablet = /(?=.*\bAndroid\b)(?=.*\b(?:KFOT|KFTT|KFJWI|KFJWA|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|KFARWI|KFASWI|KFSAWI|KFSAWA)\b)/i, 18883 windows_phone = /Windows Phone/i, 18884 windows_tablet = /(?=.*\bWindows\b)(?=.*\bARM\b)/i, // Match 'Windows' AND 'ARM' 18885 other_blackberry = /BlackBerry/i, 18886 other_blackberry_10 = /BB10/i, 18887 other_opera = /Opera Mini/i, 18888 other_chrome = /(CriOS|Chrome)(?=.*\bMobile\b)/i, 18889 other_firefox = /(?=.*\bFirefox\b)(?=.*\bMobile\b)/i, // Match 'Firefox' AND 'Mobile' 18890 seven_inch = new RegExp( 18891 '(?:' + // Non-capturing group 18892 18893 'Nexus 7' + // Nexus 7 18894 18895 '|' + // OR 18896 18897 'BNTV250' + // B&N Nook Tablet 7 inch 18898 18899 '|' + // OR 18900 18901 'Kindle Fire' + // Kindle Fire 18902 18903 '|' + // OR 18904 18905 'Silk' + // Kindle Fire, Silk Accelerated 18906 18907 '|' + // OR 18908 18909 'GT-P1000' + // Galaxy Tab 7 inch 18910 18911 ')', // End non-capturing group 18912 18913 'i'); // Case-insensitive matching 18914 18915 var match = function(regex, userAgent) { 18916 return regex.test(userAgent); 18917 }; 18918 18919 var IsMobileClass = function(userAgent) { 18920 var ua = userAgent || navigator.userAgent; 18921 18922 // Facebook mobile app's integrated browser adds a bunch of strings that 18923 // match everything. Strip it out if it exists. 18924 var tmp = ua.split('[FBAN'); 18925 if (typeof tmp[1] !== 'undefined') { 18926 ua = tmp[0]; 18927 } 18928 18929 // Twitter mobile app's integrated browser on iPad adds a "Twitter for 18930 // iPhone" string. Same probable happens on other tablet platforms. 18931 // This will confuse detection so strip it out if it exists. 18932 tmp = ua.split('Twitter'); 18933 if (typeof tmp[1] !== 'undefined') { 18934 ua = tmp[0]; 18935 } 18936 18937 this.apple = { 18938 phone: match(apple_phone, ua), 18939 ipod: match(apple_ipod, ua), 18940 tablet: !match(apple_phone, ua) && match(apple_tablet, ua), 18941 device: match(apple_phone, ua) || match(apple_ipod, ua) || match(apple_tablet, ua) 18942 }; 18943 this.amazon = { 18944 phone: match(amazon_phone, ua), 18945 tablet: !match(amazon_phone, ua) && match(amazon_tablet, ua), 18946 device: match(amazon_phone, ua) || match(amazon_tablet, ua) 18947 }; 18948 this.android = { 18949 phone: match(amazon_phone, ua) || match(android_phone, ua), 18950 tablet: !match(amazon_phone, ua) && !match(android_phone, ua) && (match(amazon_tablet, ua) || match(android_tablet, ua)), 18951 device: match(amazon_phone, ua) || match(amazon_tablet, ua) || match(android_phone, ua) || match(android_tablet, ua) 18952 }; 18953 this.windows = { 18954 phone: match(windows_phone, ua), 18955 tablet: match(windows_tablet, ua), 18956 device: match(windows_phone, ua) || match(windows_tablet, ua) 18957 }; 18958 this.other = { 18959 blackberry: match(other_blackberry, ua), 18960 blackberry10: match(other_blackberry_10, ua), 18961 opera: match(other_opera, ua), 18962 firefox: match(other_firefox, ua), 18963 chrome: match(other_chrome, ua), 18964 device: match(other_blackberry, ua) || match(other_blackberry_10, ua) || match(other_opera, ua) || match(other_firefox, ua) || match(other_chrome, ua) 18965 }; 18966 this.seven_inch = match(seven_inch, ua); 18967 this.any = this.apple.device || this.android.device || this.windows.device || this.other.device || this.seven_inch; 18968 18969 // excludes 'other' devices and ipods, targeting touchscreen phones 18970 this.phone = this.apple.phone || this.android.phone || this.windows.phone; 18971 18972 // excludes 7 inch devices, classifying as phone or tablet is left to the user 18973 this.tablet = this.apple.tablet || this.android.tablet || this.windows.tablet; 18974 18975 if (typeof window === 'undefined') { 18976 return this; 18977 } 18978 }; 18979 18980 var instantiate = function() { 18981 var IM = new IsMobileClass(); 18982 IM.Class = IsMobileClass; 18983 return IM; 18984 }; 18985 18986 if (typeof module !== 'undefined' && module.exports && typeof window === 'undefined') { 18987 //node 18988 module.exports = IsMobileClass; 18989 } else if (typeof module !== 'undefined' && module.exports && typeof window !== 'undefined') { 18990 //browserify 18991 module.exports = instantiate(); 18992 } else if (typeof define === 'function' && define.amd) { 18993 //AMD 18994 define('isMobile', [], global.isMobile = instantiate()); 18995 } else { 18996 global.isMobile = instantiate(); 18997 } 18998 18999})(this); 19000 19001// HumanizeDuration.js - http://git.io/j0HgmQ 19002// This has been modified for the purposes of SpectrumLocalNews.com 19003// the original can be found at the URL above 19004;(function () { 19005 var languages = { 19006 en: { 19007 y: function (c) { 19008 return 'year' + (c !== 1 ? 's' : '') 19009 }, 19010 mo: function (c) { 19011 return 'month' + (c !== 1 ? 's' : '') 19012 }, 19013 w: function (c) { 19014 return 'week' + (c !== 1 ? 's' : '') 19015 }, 19016 d: function (c) { 19017 return 'day' + (c !== 1 ? 's' : '') 19018 }, 19019 h: function (c) { 19020 return 'hour' + (c !== 1 ? 's' : '') 19021 }, 19022 m: function (c) { 19023 return 'minute' + (c !== 1 ? 's' : '') 19024 }, 19025 s: function (c) { 19026 return 'second' + (c !== 1 ? 's' : '') 19027 }, 19028 ms: function (c) { 19029 return 'millisecond' + (c !== 1 ? 's' : '') 19030 },
19031 decimal: '.' 19032 }, 19033 es: { 19034 y: function (c) { 19035 return (c === 1 ? 'un ' : '') + 'año' + (c !== 1 ? 's' : '') 19036 }, 19037 mo: function (c) { 19038 return (c === 1 ? 'un ' : '') + 'mes' + (c !== 1 ? 'es' : '') 19039 }, 19040 w: function (c) { 19041 return (c === 1 ? 'una ' : '') + 'semana' + (c !== 1 ? 's' : '') 19042 }, 19043 d: function (c) { 19044 return (c === 1 ? 'un ' : '') + 'dÃa' + (c !== 1 ? 's' : '') 19045 }, 19046 h: function (c) { 19047 return (c === 1 ? 'una ' : '') + 'hora' + (c !== 1 ? 's' : '') 19048 }, 19049 m: function (c) { 19050 return (c === 1 ? 'un ' : '') + 'minuto' + (c !== 1 ? 's' : '') 19051 }, 19052 s: function (c) { 19053 return (c === 1 ? 'un ' : '') + 'segundo' + (c !== 1 ? 's' : '') 19054 }, 19055 ms: function (c) { 19056 return (c === 1 ? 'un ' : '') + 'milisegundo' + (c !== 1 ? 's' : '') 19057 }, 19058 decimal: ',' 19059 } 19060 } 19061 19062 // You can create a humanizer, which returns a function with default 19063 // parameters. 19064 function humanizer(passedOptions) { 19065 var result = function humanizer(ms, humanizerOptions) { 19066 var options = extend({}, result, humanizerOptions || {}) 19067 return doHumanization(ms, options) 19068 } 19069 19070 return extend(result, { 19071 language: 'en', 19072 delimiter: ', ', 19073 spacer: ' ', 19074 conjunction: '', 19075 serialComma: true, 19076 units: ['y', 'mo', 'w', 'd', 'h', 'm', 's'], 19077 languages: {}, 19078 round: false, 19079 unitMeasures: { 19080 y: 31557600000, 19081 mo: 2629800000, 19082 w: 604800000, 19083 d: 86400000, 19084 h: 3600000, 19085 m: 60000, 19086 s: 1000, 19087 ms: 1 19088 } 19089 }, passedOptions) 19090 } 19091 19092 // The main function is just a wrapper around a default humanizer. 19093 var humanizeDuration = humanizer({}) 19094 19095 // doHumanization does the bulk of the work. 19096 function doHumanization(ms, options) { 19097 var i, len, piece 19098 19099 // Make sure we have a positive number. 19100 // Has the nice sideffect of turning Number objects into primitives. 19101 ms = Math.abs(ms) 19102 19103 var dictionary = options.languages[options.language] || languages[options.language] 19104 if (!dictionary) { 19105 throw new Error('No language ' + dictionary + '.') 19106 } 19107 19108 var pieces = [] 19109 19110 // Start at the top and keep removing units, bit by bit. 19111 var unitName, unitMS, unitCount 19112 for (i = 0, len = options.units.length; i < len; i++) { 19113 unitName = options.units[i] 19114 unitMS = options.unitMeasures[unitName] 19115 19116 // What's the number of full units we can fit? 19117 if (i + 1 === len) { 19118 unitCount = ms / unitMS 19119 } else { 19120 unitCount = Math.floor(ms / unitMS) 19121 } 19122 19123 // Add the string. 19124 pieces.push({ 19125 unitCount: unitCount, 19126 unitName: unitName 19127 }) 19128 19129 // Remove what we just figured out. 19130 ms -= unitCount * unitMS 19131 } 19132 19133 var firstOccupiedUnitIndex = 0 19134 for (i = 0; i < pieces.length; i++) { 19135 if (pieces[i].unitCount) { 19136 firstOccupiedUnitIndex = i 19137 break 19138 } 19139 } 19140 19141 if (options.round) { 19142 var ratioToLargerUnit, previousPiece 19143 for (i = pieces.length - 1; i >= 0; i--) { 19144 piece = pieces[i] 19145 piece.unitCount = Math.round(piece.unitCount) 19146 19147 if (i === 0) { 19148 break 19149 } 19150 19151 previousPiece = pieces[i - 1] 19152 19153 ratioToLargerUnit = options.unitMeasures[previousPiece.unitName] / options.unitMeasures[piece.unitName] 19154 if ((piece.unitCount % ratioToLargerUnit) === 0 || (options.largest && ((options.largest - 1) < (i - firstOccupiedUnitIndex)))) { 19155 previousPiece.unitCount += piece.unitCount / ratioToLargerUnit 19156 piece.unitCount = 0 19157 } 19158 } 19159 } 19160 19161 var result = [] 19162 for (i = 0, pieces.length; i < len; i++) { 19163 piece = pieces[i] 19164 if (piece.unitCount) { 19165 result.push(render(piece.unitCount, piece.unitName, dictionary, options)) 19166 } 19167 19168 if (result.length === options.largest) { 19169 break 19170 } 19171 } 19172 19173 if (result.length) { 19174 if (!options.conjunction || result.length === 1) { 19175 return result.join(options.delimiter) 19176 } else if (result.length === 2) { 19177 return result.join(options.conjunction) 19178 } else if (result.length > 2) { 19179 return result.slice(0, -1).join(options.delimiter) + (options.serialComma ? ',' : '') + options.conjunction + result.slice(-1) 19180 } 19181 } else { 19182 return render(0, options.units[options.units.length - 1], dictionary, options) 19183 } 19184 } 19185 19186 function render(count, type, dictionary, options) { 19187 var decimal 19188 if (options.decimal === void 0) { 19189 decimal = dictionary.decimal 19190 } else { 19191 decimal = options.decimal 19192 } 19193 19194 var countStr = count.toString().replace('.', decimal) 19195 19196 var dictionaryValue = dictionary[type] 19197 var word 19198 if (typeof dictionaryValue === 'function') { 19199 word = dictionaryValue(count) 19200 } else { 19201 word = dictionaryValue 19202 } 19203 if (options.language === 'en' && options.ago) { 19204 word = word + ' ago'; 19205 } else if (options.language === 'es' && options.ago) { 19206 // TWCNEWS-3370: NY1Noticias Added handling 19207 countStr = countStr === '1' ? 'hace ' : 'hace ' + countStr; 19208 } 19209 return countStr + options.spacer + word 19210 } 19211 19212 function extend(destination) { 19213 var source 19214 for (var i = 1; i < arguments.length; i++) { 19215 source = arguments[i] 19216 for (var prop in source) { 19217 if (source.hasOwnProperty(prop)) { 19218 destination[prop] = source[prop] 19219 } 19220 } 19221 } 19222 return destination 19223 } 19224
19225 humanizeDuration.getSupportedLanguages = function getSupportedLanguages() { 19226 var result = [] 19227 for (var language in languages) { 19228 if (languages.hasOwnProperty(language)) { 19229 result.push(language) 19230 } 19231 } 19232 return result 19233 } 19234 19235 humanizeDuration.humanizer = humanizer 19236 19237 if (typeof define === 'function' && define.amd) { 19238 define(function () { 19239 return humanizeDuration 19240 }) 19241 } else if (typeof module !== 'undefined' && module.exports) { 19242 module.exports = humanizeDuration 19243 } else { 19244 this.humanizeDuration = humanizeDuration 19245 } 19246})(); // eslint-disable-line semi 19247 19248/*! ======================================================= 19249 VERSION 9.8.0 19250========================================================= */ 19251"use strict"; 19252 19253var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 19254 19255/*! ========================================================= 19256 * bootstrap-slider.js 19257 * 19258 * Maintainers: 19259 * Kyle Kemp 19260 * - Twitter: @seiyria 19261 * - Github: seiyria 19262 * Rohit Kalkur 19263 * - Twitter: @Rovolutionary 19264 * - Github: rovolution 19265 * 19266 * ========================================================= 19267 * 19268 * bootstrap-slider is released under the MIT License 19269 * Copyright (c) 2017 Kyle Kemp, Rohit Kalkur, and contributors 19270 * 19271 * Permission is hereby granted, free of charge, to any person 19272 * obtaining a copy of this software and associated documentation 19273 * files (the "Software"), to deal in the Software without 19274 * restriction, including without limitation the rights to use, 19275 * copy, modify, merge, publish, distribute, sublicense, and/or sell 19276 * copies of the Software, and to permit persons to whom the 19277 * Software is furnished to do so, subject to the following 19278 * conditions: 19279 * 19280 * The above copyright notice and this permission notice shall be 19281 * included in all copies or substantial portions of the Software. 19282 * 19283 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19284 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19285 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19286 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19287 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19288 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19289 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 19290 * OTHER DEALINGS IN THE SOFTWARE. 19291 * 19292 * ========================================================= */ 19293 19294/** 19295 * Bridget makes jQuery widgets 19296 * v1.0.1 19297 * MIT license 19298 */ 19299var windowIsDefined = (typeof window === "undefined" ? "undefined" : _typeof(window)) === "object"; 19300 19301(function (factory) { 19302 if (typeof define === "function" && define.amd) { 19303 define(["jquery"], factory); 19304 } else if ((typeof module === "undefined" ? "undefined" : _typeof(module)) === "object" && module.exports) { 19305 var jQuery; 19306 try { 19307 jQuery = require("jquery"); 19308 } catch (err) { 19309 jQuery = null; 19310 } 19311 module.exports = factory(jQuery); 19312 } else if (window) { 19313 window.Slider = factory(window.jQuery); 19314 } 19315})(function ($) { 19316 // Constants 19317 var NAMESPACE_MAIN = 'slider'; 19318 var NAMESPACE_ALTERNATE = 'bootstrapSlider'; 19319 19320 // Polyfill console methods 19321 if (windowIsDefined && !window.console) { 19322 window.console = {}; 19323 } 19324 if (windowIsDefined && !window.console.log) { 19325 window.console.log = function () {}; 19326 } 19327 if (windowIsDefined && !window.console.warn) { 19328 window.console.warn = function () {}; 19329 } 19330 19331 // Reference to Slider constructor 19332 var Slider; 19333 19334 (function ($) { 19335 19336 'use strict'; 19337 19338 // -------------------------- utils -------------------------- // 19339 19340 var slice = Array.prototype.slice; 19341 19342 function noop() {} 19343 19344 // -------------------------- definition -------------------------- // 19345 19346 function defineBridget($) { 19347 19348 // bail if no jQuery 19349 if (!$) { 19350 return; 19351 } 19352 19353 // -------------------------- addOptionMethod -------------------------- // 19354 19355 /** 19356 * adds option method -> $().plugin('option', {...}) 19357 * @param {Function} PluginClass - constructor class 19358 */ 19359 function addOptionMethod(PluginClass) { 19360 // don't overwrite original option method 19361 if (PluginClass.prototype.option) { 19362 return; 19363 } 19364 19365 // option setter 19366 PluginClass.prototype.option = function (opts) { 19367 // bail out if not an object 19368 if (!$.isPlainObject(opts)) { 19369 return; 19370 } 19371 this.options = $.extend(true, this.options, opts); 19372 }; 19373 } 19374 19375 // -------------------------- plugin bridge -------------------------- // 19376 19377 // helper function for logging errors 19378 // $.error breaks jQuery chaining 19379 var logError = typeof console === 'undefined' ? noop : function (message) { 19380 console.error(message); 19381 }; 19382 19383 /** 19384 * jQuery plugin bridge, access methods like $elem.plugin('method') 19385 * @param {String} namespace - plugin name 19386 * @param {Function} PluginClass - constructor class 19387 */ 19388 function bridge(namespace, PluginClass) { 19389 // add to jQuery fn namespace 19390 $.fn[namespace] = function (options) { 19391 if (typeof options === 'string') { 19392 // call plugin method when first argument is a string 19393 // get arguments for method 19394 var args = slice.call(arguments, 1); 19395 19396 for (var i = 0, len = this.length; i < len; i++) { 19397 var elem = this[i]; 19398 var instance = $.data(elem, namespace); 19399 if (!instance) { 19400 logError("cannot call methods on " + namespace + " prior to initialization; " + "attempted to call '" + options + "'"); 19401 continue; 19402 } 19403 if (!$.isFunction(instance[options]) || options.charAt(0) === '_') { 19404 logError("no such method '" + options + "' for " + namespace + " instance"); 19405 continue; 19406 } 19407 19408 // trigger method with arguments 19409 var returnValue = instance[options].apply(instance, args); 19410 19411 // break look and return first value if provided 19412 if (returnValue !== undefined && returnValue !== instance) { 19413 return returnValue; 19414 } 19415 } 19416 // return this if no return value 19417 return this; 19418 } else { 19419 var objects = this.map(function () { 19420 var instance = $.data(this, namespace); 19421 if (instance) { 19422 // apply options & init 19423 instance.option(options); 19424 instance._init(); 19425 } else { 19426 // initialize new instance 19427 instance = new PluginClass(this, options); 19428 $.data(this, namespace, instance); 19429 } 19430 return $(this); 19431 }); 19432 19433 if (!objects || objects.length > 1) { 19434 return objects; 19435 } else { 19436 return objects[0]; 19437 } 19438 } 19439 }; 19440 } 19441 19442 // -------------------------- bridget -------------------------- // 19443 19444 /** 19445 * converts a Prototypical class into a proper jQuery plugin 19446 * the class must have a ._init method 19447 * @param {String} namespace - plugin name, used in $().pluginName 19448 * @param {Function} PluginClass - constructor class 19449 */ 19450 $.bridget = function (namespace, PluginClass) { 19451 addOptionMethod(PluginClass); 19452 bridge(namespace, PluginClass); 19453 }; 19454 19455 return $.bridget; 19456 } 19457 19458 // get jquery from browser global 19459 defineBridget($); 19460 })($); 19461 19462 /************************************************* 19463 BOOTSTRAP-SLIDER SOURCE CODE 19464 **************************************************/ 19465 19466 (function ($) { 19467 19468 var ErrorMsgs = { 19469 formatInvalidInputErrorMsg: function formatInvalidInputErrorMsg(input) { 19470 return "Invalid input value '" + input + "' passed in"; 19471 }, 19472 callingContextNotSliderInstance: "Calling context element does not have instance of Slider bound to it. Check your code to make sure the JQuery object returned from the call to the slider() initializer is calling the method" 19473 }; 19474 19475 var SliderScale = { 19476 linear: { 19477 toValue: function toValue(percentage) { 19478 var rawValue = percentage / 100 * (this.options.max - this.options.min); 19479 var shouldAdjustWithBase = true; 19480 if (this.options.ticks_positions.length > 0) { 19481 var minv, 19482 maxv, 19483 minp, 19484 maxp = 0; 19485 for (var i = 1; i < this.options.ticks_positions.length; i++) { 19486 if (percentage <= this.options.ticks_positions[i]) { 19487 minv = this.options.ticks[i - 1]; 19488 minp = this.options.ticks_positions[i - 1]; 19489 maxv = this.options.ticks[i]; 19490 maxp = this.options.ticks_positions[i]; 19491 19492 break; 19493 } 19494 } 19495 var partialPercentage = (percentage - minp) / (maxp - minp); 19496 rawValue = minv + partialPercentage * (maxv - minv); 19497 shouldAdjustWithBase = false;
19498 } 19499 19500 var adjustment = shouldAdjustWithBase ? this.options.min : 0; 19501 var value = adjustment + Math.round(rawValue / this.options.step) * this.options.step; 19502 if (value < this.options.min) { 19503 return this.options.min; 19504 } else if (value > this.options.max) { 19505 return this.options.max; 19506 } else { 19507 return value; 19508 } 19509 }, 19510 toPercentage: function toPercentage(value) { 19511 if (this.options.max === this.options.min) { 19512 return 0; 19513 } 19514 19515 if (this.options.ticks_positions.length > 0) { 19516 var minv, 19517 maxv, 19518 minp, 19519 maxp = 0; 19520 for (var i = 0; i < this.options.ticks.length; i++) { 19521 if (value <= this.options.ticks[i]) { 19522 minv = i > 0 ? this.options.ticks[i - 1] : 0; 19523 minp = i > 0 ? this.options.ticks_positions[i - 1] : 0; 19524 maxv = this.options.ticks[i]; 19525 maxp = this.options.ticks_positions[i]; 19526 19527 break; 19528 } 19529 } 19530 if (i > 0) { 19531 var partialPercentage = (value - minv) / (maxv - minv); 19532 return minp + partialPercentage * (maxp - minp); 19533 } 19534 } 19535 19536 return 100 * (value - this.options.min) / (this.options.max - this.options.min); 19537 } 19538 }, 19539 19540 logarithmic: { 19541 /* Based on http://stackoverflow.com/questions/846221/logarithmic-slider */ 19542 toValue: function toValue(percentage) { 19543 var min = this.options.min === 0 ? 0 : Math.log(this.options.min); 19544 var max = Math.log(this.options.max); 19545 var value = Math.exp(min + (max - min) * percentage / 100); 19546 value = this.options.min + Math.round((value - this.options.min) / this.options.step) * this.options.step; 19547 /* Rounding to the nearest step could exceed the min or 19548 * max, so clip to those values. */ 19549 if (value < this.options.min) { 19550 return this.options.min; 19551 } else if (value > this.options.max) { 19552 return this.options.max; 19553 } else { 19554 return value; 19555 } 19556 }, 19557 toPercentage: function toPercentage(value) { 19558 if (this.options.max === this.options.min) { 19559 return 0; 19560 } else { 19561 var max = Math.log(this.options.max); 19562 var min = this.options.min === 0 ? 0 : Math.log(this.options.min); 19563 var v = value === 0 ? 0 : Math.log(value); 19564 return 100 * (v - min) / (max - min); 19565 } 19566 } 19567 } 19568 }; 19569 19570 /************************************************* 19571 CONSTRUCTOR 19572 **************************************************/ 19573 Slider = function (element, options) { 19574 createNewSlider.call(this, element, options); 19575 return this; 19576 }; 19577 19578 function createNewSlider(element, options) { 19579 19580 /* 19581 The internal state object is used to store data about the current 'state' of slider. 19582 This includes values such as the `value`, `enabled`, etc... 19583 */ 19584 this._state = { 19585 value: null, 19586 enabled: null, 19587 offset: null, 19588 size: null, 19589 percentage: null, 19590 inDrag: false, 19591 over: false 19592 }; 19593 19594 // The objects used to store the reference to the tick methods if ticks_tooltip is on 19595 this.ticksCallbackMap = {}; 19596 this.handleCallbackMap = {}; 19597 19598 if (typeof element === "string") { 19599 this.element = document.querySelector(element); 19600 } else if (element instanceof HTMLElement) { 19601 this.element = element; 19602 } 19603 19604 /************************************************* 19605 Process Options 19606 **************************************************/ 19607 options = options ? options : {}; 19608 var optionTypes = Object.keys(this.defaultOptions); 19609 19610 for (var i = 0; i < optionTypes.length; i++) { 19611 var optName = optionTypes[i]; 19612 19613 // First check if an option was passed in via the constructor 19614 var val = options[optName]; 19615 // If no data attrib, then check data atrributes 19616 val = typeof val !== 'undefined' ? val : getDataAttrib(this.element, optName); 19617 // Finally, if nothing was specified, use the defaults 19618 val = val !== null ? val : this.defaultOptions[optName]; 19619 19620 // Set all options on the instance of the Slider 19621 if (!this.options) { 19622 this.options = {}; 19623 } 19624 this.options[optName] = val; 19625 } 19626 19627 // Check options.rtl 19628 if (this.options.rtl === 'auto') { 19629 this.options.rtl = window.getComputedStyle(this.element).direction === 'rtl'; 19630 } 19631 19632 /* 19633 Validate `tooltip_position` against 'orientation` 19634 - if `tooltip_position` is incompatible with orientation, swith it to a default compatible with specified `orientation` 19635 -- default for "vertical" -> "right", "left" if rtl 19636 -- default for "horizontal" -> "top" 19637 */ 19638 if (this.options.orientation === "vertical" && (this.options.tooltip_position === "top" || this.options.tooltip_position === "bottom")) { 19639 if (this.options.rtl) { 19640 this.options.tooltip_position = "left"; 19641 } else { 19642 this.options.tooltip_position = "right"; 19643 } 19644 } else if (this.options.orientation === "horizontal" && (this.options.tooltip_position === "left" || this.options.tooltip_position === "right")) { 19645 19646 this.options.tooltip_position = "top"; 19647 } 19648 19649 function getDataAttrib(element, optName) {
19650 var dataName = "data-slider-" + optName.replace(/_/g, '-'); 19651 var dataValString = element.getAttribute(dataName); 19652 19653 try { 19654 return JSON.parse(dataValString); 19655 } catch (err) { 19656 return dataValString; 19657 } 19658 } 19659 19660 /************************************************* 19661 Create Markup 19662 **************************************************/ 19663 19664 var origWidth = this.element.style.width; 19665 var updateSlider = false; 19666 var parent = this.element.parentNode; 19667 var sliderTrackSelection; 19668 var sliderTrackLow, sliderTrackHigh; 19669 var sliderMinHandle; 19670 var sliderMaxHandle; 19671 19672 if (this.sliderElem) { 19673 updateSlider = true; 19674 } else { 19675 /* Create elements needed for slider */ 19676 this.sliderElem = document.createElement("div"); 19677 this.sliderElem.className = "slider"; 19678 19679 /* Create slider track elements */ 19680 var sliderTrack = document.createElement("div"); 19681 sliderTrack.className = "slider-track"; 19682 19683 sliderTrackLow = document.createElement("div"); 19684 sliderTrackLow.className = "slider-track-low"; 19685 19686 sliderTrackSelection = document.createElement("div"); 19687 sliderTrackSelection.className = "slider-selection"; 19688 19689 sliderTrackHigh = document.createElement("div"); 19690 sliderTrackHigh.className = "slider-track-high"; 19691 19692 sliderMinHandle = document.createElement("div"); 19693 sliderMinHandle.className = "slider-handle min-slider-handle"; 19694 sliderMinHandle.setAttribute('role', 'slider'); 19695 sliderMinHandle.setAttribute('aria-valuemin', this.options.min); 19696 sliderMinHandle.setAttribute('aria-valuemax', this.options.max); 19697 19698 sliderMaxHandle = document.createElement("div"); 19699 sliderMaxHandle.className = "slider-handle max-slider-handle"; 19700 sliderMaxHandle.setAttribute('role', 'slider'); 19701 sliderMaxHandle.setAttribute('aria-valuemin', this.options.min); 19702 sliderMaxHandle.setAttribute('aria-valuemax', this.options.max); 19703 19704 sliderTrack.appendChild(sliderTrackLow); 19705 sliderTrack.appendChild(sliderTrackSelection); 19706 sliderTrack.appendChild(sliderTrackHigh); 19707 19708 /* Create highlight range elements */ 19709 this.rangeHighlightElements = []; 19710 var rangeHighlightsOpts = this.options.rangeHighlights; 19711 if (Array.isArray(rangeHighlightsOpts) && rangeHighlightsOpts.length > 0) { 19712 for (var j = 0; j < rangeHighlightsOpts.length; j++) { 19713 var rangeHighlightElement = document.createElement("div"); 19714 var customClassString = rangeHighlightsOpts[j]['class'] || ""; 19715 rangeHighlightElement.className = "slider-rangeHighlight slider-selection " + customClassString; 19716 this.rangeHighlightElements.push(rangeHighlightElement); 19717 sliderTrack.appendChild(rangeHighlightElement); 19718 } 19719 } 19720 19721 /* Add aria-labelledby to handle's */ 19722 var isLabelledbyArray = Array.isArray(this.options.labelledby); 19723 if (isLabelledbyArray && this.options.labelledby[0]) { 19724 sliderMinHandle.setAttribute('aria-labelledby', this.options.labelledby[0]); 19725 } 19726 if (isLabelledbyArray && this.options.labelledby[1]) { 19727 sliderMaxHandle.setAttribute('aria-labelledby', this.options.labelledby[1]); 19728 } 19729 if (!isLabelledbyArray && this.options.labelledby) { 19730 sliderMinHandle.setAttribute('aria-labelledby', this.options.labelledby); 19731 sliderMaxHandle.setAttribute('aria-labelledby', this.options.labelledby); 19732 } 19733 19734 /* Create ticks */ 19735 this.ticks = []; 19736 if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) { 19737 this.ticksContainer = document.createElement('div'); 19738 this.ticksContainer.className = 'slider-tick-container'; 19739 19740 for (i = 0; i < this.options.ticks.length; i++) { 19741 var tick = document.createElement('div'); 19742 tick.className = 'slider-tick'; 19743 if (this.options.ticks_tooltip) { 19744 var tickListenerReference = this._addTickListener(); 19745 var enterCallback = tickListenerReference.addMouseEnter(this, tick, i); 19746 var leaveCallback = tickListenerReference.addMouseLeave(this, tick); 19747 19748 this.ticksCallbackMap[i] = { 19749 mouseEnter: enterCallback, 19750 mouseLeave: leaveCallback 19751 }; 19752 } 19753 this.ticks.push(tick); 19754 this.ticksContainer.appendChild(tick); 19755 } 19756 19757 sliderTrackSelection.className += " tick-slider-selection"; 19758 } 19759 19760 this.tickLabels = []; 19761 if (Array.isArray(this.options.ticks_labels) && this.options.ticks_labels.length > 0) { 19762 this.tickLabelContainer = document.createElement('div'); 19763 this.tickLabelContainer.className = 'slider-tick-label-container'; 19764 19765 for (i = 0; i < this.options.ticks_labels.length; i++) { 19766 var label = document.createElement('div'); 19767 var noTickPositionsSpecified = this.options.ticks_positions.length === 0; 19768 var tickLabelsIndex = this.options.reversed && noTickPositionsSpecified ? this.options.ticks_labels.length - (i + 1) : i; 19769 label.className = 'slider-tick-label'; 19770 label.innerHTML = this.options.ticks_labels[tickLabelsIndex]; 19771 19772 this.tickLabels.push(label); 19773 this.tickLabelContainer.appendChild(label); 19774 } 19775 } 19776 19777 var createAndAppendTooltipSubElements = function createAndAppendTooltipSubElements(tooltipElem) { 19778 var arrow = document.createElement("div"); 19779 arrow.className = "tooltip-arrow"; 19780 19781 var inner = document.createElement("div"); 19782 inner.className = "tooltip-inner"; 19783 19784 tooltipElem.appendChild(arrow); 19785 tooltipElem.appendChild(inner); 19786 }; 19787 19788 /* Create tooltip elements */ 19789 var sliderTooltip = document.createElement("div"); 19790 sliderTooltip.className = "tooltip tooltip-main"; 19791 sliderTooltip.setAttribute('role', 'presentation'); 19792 createAndAppendTooltipSubElements(sliderTooltip); 19793 19794 var sliderTooltipMin = document.createElement("div"); 19795 sliderTooltipMin.className = "tooltip tooltip-min"; 19796 sliderTooltipMin.setAttribute('role', 'presentation'); 19797 createAndAppendTooltipSubElements(sliderTooltipMin); 19798 19799 var sliderTooltipMax = document.createElement("div"); 19800 sliderTooltipMax.className = "tooltip tooltip-max"; 19801 sliderTooltipMax.setAttribute('role', 'presentation'); 19802 createAndAppendTooltipSubElements(sliderTooltipMax); 19803 19804 /* Append components to sliderElem */ 19805 this.sliderElem.appendChild(sliderTrack); 19806 this.sliderElem.appendChild(sliderTooltip); 19807 this.sliderElem.appendChild(sliderTooltipMin); 19808 this.sliderElem.appendChild(sliderTooltipMax); 19809 19810 if (this.tickLabelContainer) { 19811 this.sliderElem.appendChild(this.tickLabelContainer); 19812 } 19813 if (this.ticksContainer) { 19814 this.sliderElem.appendChild(this.ticksContainer); 19815 } 19816 19817 this.sliderElem.appendChild(sliderMinHandle); 19818 this.sliderElem.appendChild(sliderMaxHandle); 19819 19820 /* Append slider element to parent container, right before the original <input> element */ 19821 parent.insertBefore(this.sliderElem, this.element); 19822 19823 /* Hide original <input> element */ 19824 this.element.style.display = "none"; 19825 }
19826 /* If JQuery exists, cache JQ references */ 19827 if ($) { 19828 this.$element = $(this.element); 19829 this.$sliderElem = $(this.sliderElem); 19830 } 19831 19832 /************************************************* 19833 Setup 19834 **************************************************/ 19835 this.eventToCallbackMap = {}; 19836 this.sliderElem.id = this.options.id; 19837 19838 this.touchCapable = 'ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch; 19839 19840 this.touchX = 0; 19841 this.touchY = 0; 19842 19843 this.tooltip = this.sliderElem.querySelector('.tooltip-main'); 19844 this.tooltipInner = this.tooltip.querySelector('.tooltip-inner'); 19845 19846 this.tooltip_min = this.sliderElem.querySelector('.tooltip-min'); 19847 this.tooltipInner_min = this.tooltip_min.querySelector('.tooltip-inner'); 19848 19849 this.tooltip_max = this.sliderElem.querySelector('.tooltip-max'); 19850 this.tooltipInner_max = this.tooltip_max.querySelector('.tooltip-inner'); 19851 19852 if (SliderScale[this.options.scale]) { 19853 this.options.scale = SliderScale[this.options.scale]; 19854 } 19855 19856 if (updateSlider === true) { 19857 // Reset classes 19858 this._removeClass(this.sliderElem, 'slider-horizontal'); 19859 this._removeClass(this.sliderElem, 'slider-vertical'); 19860 this._removeClass(this.sliderElem, 'slider-rtl'); 19861 this._removeClass(this.tooltip, 'hide'); 19862 this._removeClass(this.tooltip_min, 'hide'); 19863 this._removeClass(this.tooltip_max, 'hide'); 19864 19865 // Undo existing inline styles for track 19866 ["left", "right", "top", "width", "height"].forEach(function (prop) { 19867 this._removeProperty(this.trackLow, prop);
19868 this._removeProperty(this.trackSelection, prop); 19869 this._removeProperty(this.trackHigh, prop); 19870 }, this); 19871 19872 // Undo inline styles on handles 19873 [this.handle1, this.handle2].forEach(function (handle) { 19874 this._removeProperty(handle, 'left'); 19875 this._removeProperty(handle, 'right'); 19876 this._removeProperty(handle, 'top'); 19877 }, this); 19878 19879 // Undo inline styles and classes on tooltips 19880 [this.tooltip, this.tooltip_min, this.tooltip_max].forEach(function (tooltip) { 19881 this._removeProperty(tooltip, 'left'); 19882 this._removeProperty(tooltip, 'right'); 19883 this._removeProperty(tooltip, 'top'); 19884 this._removeProperty(tooltip, 'margin-left'); 19885 this._removeProperty(tooltip, 'margin-right'); 19886 this._removeProperty(tooltip, 'margin-top'); 19887 19888 this._removeClass(tooltip, 'right'); 19889 this._removeClass(tooltip, 'left'); 19890 this._removeClass(tooltip, 'top'); 19891 }, this); 19892 } 19893 19894 if (this.options.orientation === 'vertical') { 19895 this._addClass(this.sliderElem, 'slider-vertical'); 19896 this.stylePos = 'top'; 19897 this.mousePos = 'pageY'; 19898 this.sizePos = 'offsetHeight'; 19899 } else { 19900 this._addClass(this.sliderElem, 'slider-horizontal'); 19901 this.sliderElem.style.width = origWidth; 19902 this.options.orientation = 'horizontal'; 19903 if (this.options.rtl) { 19904 this.stylePos = 'right'; 19905 } else { 19906 this.stylePos = 'left'; 19907 } 19908 this.mousePos = 'pageX'; 19909 this.sizePos = 'offsetWidth'; 19910 } 19911 // specific rtl class 19912 if (this.options.rtl) { 19913 this._addClass(this.sliderElem, 'slider-rtl'); 19914 } 19915 this._setTooltipPosition(); 19916 /* In case ticks are specified, overwrite the min and max bounds */ 19917 if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) { 19918 this.options.max = Math.max.apply(Math, this.options.ticks); 19919 this.options.min = Math.min.apply(Math, this.options.ticks); 19920 } 19921 19922 if (Array.isArray(this.options.value)) { 19923 this.options.range = true; 19924 this._state.value = this.options.value; 19925 } else if (this.options.range) { 19926 // User wants a range, but value is not an array 19927 this._state.value = [this.options.value, this.options.max]; 19928 } else { 19929 this._state.value = this.options.value; 19930 } 19931 19932 this.trackLow = sliderTrackLow || this.trackLow; 19933 this.trackSelection = sliderTrackSelection || this.trackSelection; 19934 this.trackHigh = sliderTrackHigh || this.trackHigh; 19935 19936 if (this.options.selection === 'none') { 19937 this._addClass(this.trackLow, 'hide'); 19938 this._addClass(this.trackSelection, 'hide'); 19939 this._addClass(this.trackHigh, 'hide'); 19940 } else if (this.options.selection === 'after' || this.options.selection === 'before') { 19941 this._removeClass(this.trackLow, 'hide'); 19942 this._removeClass(this.trackSelection, 'hide'); 19943 this._removeClass(this.trackHigh, 'hide'); 19944 } 19945 19946 this.handle1 = sliderMinHandle || this.handle1; 19947 this.handle2 = sliderMaxHandle || this.handle2; 19948 19949 if (updateSlider === true) { 19950 // Reset classes 19951 this._removeClass(this.handle1, 'round triangle'); 19952 this._removeClass(this.handle2, 'round triangle hide'); 19953 19954 for (i = 0; i < this.ticks.length; i++) { 19955 this._removeClass(this.ticks[i], 'round triangle hide'); 19956 } 19957 } 19958 19959 var availableHandleModifiers = ['round', 'triangle', 'custom']; 19960 var isValidHandleType = availableHandleModifiers.indexOf(this.options.handle) !== -1; 19961 if (isValidHandleType) { 19962 this._addClass(this.handle1, this.options.handle); 19963 this._addClass(this.handle2, this.options.handle); 19964 19965 for (i = 0; i < this.ticks.length; i++) { 19966 this._addClass(this.ticks[i], this.options.handle); 19967 } 19968 } 19969 19970 this._state.offset = this._offset(this.sliderElem); 19971 this._state.size = this.sliderElem[this.sizePos]; 19972 this.setValue(this._state.value); 19973 19974 /****************************************** 19975 Bind Event Listeners 19976 ******************************************/ 19977 19978 // Bind keyboard handlers 19979 this.handle1Keydown = this._keydown.bind(this, 0); 19980 this.handle1.addEventListener("keydown", this.handle1Keydown, false); 19981 19982 this.handle2Keydown = this._keydown.bind(this, 1); 19983 this.handle2.addEventListener("keydown", this.handle2Keydown, false); 19984 19985 this.mousedown = this._mousedown.bind(this); 19986 this.touchstart = this._touchstart.bind(this); 19987 this.touchmove = this._touchmove.bind(this); 19988 19989 if (this.touchCapable) { 19990 // Test for passive event support 19991 var supportsPassive = false;
19992 try { 19993 var opts = Object.defineProperty({}, 'passive', { 19994 get: function get() { 19995 supportsPassive = true; 19996 } 19997 }); 19998 window.addEventListener("test", null, opts); 19999 } catch (e) {} 20000 // Use our detect's results. passive applied if supported, capture will be false either way. 20001 var eventOptions = supportsPassive ? { passive: true } : false; 20002 // Bind touch handlers 20003 this.sliderElem.addEventListener("touchstart", this.touchstart, eventOptions); 20004 this.sliderElem.addEventListener("touchmove", this.touchmove, eventOptions); 20005 } 20006 this.sliderElem.addEventListener("mousedown", this.mousedown, false); 20007 20008 // Bind window handlers 20009 this.resize = this._resize.bind(this); 20010 window.addEventListener("resize", this.resize, false); 20011 20012 // Bind tooltip-related handlers 20013 if (this.options.tooltip === 'hide') { 20014 this._addClass(this.tooltip, 'hide'); 20015 this._addClass(this.tooltip_min, 'hide'); 20016 this._addClass(this.tooltip_max, 'hide'); 20017 } else if (this.options.tooltip === 'always') { 20018 this._showTooltip(); 20019 this._alwaysShowTooltip = true; 20020 } else { 20021 this.showTooltip = this._showTooltip.bind(this); 20022 this.hideTooltip = this._hideTooltip.bind(this); 20023 20024 if (this.options.ticks_tooltip) { 20025 var callbackHandle = this._addTickListener(); 20026 //create handle1 listeners and store references in map 20027 var mouseEnter = callbackHandle.addMouseEnter(this, this.handle1); 20028 var mouseLeave = callbackHandle.addMouseLeave(this, this.handle1); 20029 this.handleCallbackMap.handle1 = { 20030 mouseEnter: mouseEnter, 20031 mouseLeave: mouseLeave 20032 }; 20033 //create handle2 listeners and store references in map 20034 mouseEnter = callbackHandle.addMouseEnter(this, this.handle2); 20035 mouseLeave = callbackHandle.addMouseLeave(this, this.handle2); 20036 this.handleCallbackMap.handle2 = { 20037 mouseEnter: mouseEnter, 20038 mouseLeave: mouseLeave 20039 }; 20040 } else { 20041 this.sliderElem.addEventListener("mouseenter", this.showTooltip, false); 20042 this.sliderElem.addEventListener("mouseleave", this.hideTooltip, false); 20043 } 20044 20045 this.handle1.addEventListener("focus", this.showTooltip, false); 20046 this.handle1.addEventListener("blur", this.hideTooltip, false); 20047 20048 this.handle2.addEventListener("focus", this.showTooltip, false); 20049 this.handle2.addEventListener("blur", this.hideTooltip, false); 20050 } 20051 20052 if (this.options.enabled) { 20053 this.enable(); 20054 } else { 20055 this.disable(); 20056 } 20057 } 20058 20059 /************************************************* 20060 INSTANCE PROPERTIES/METHODS 20061 - Any methods bound to the prototype are considered 20062 part of the plugin's `public` interface 20063 **************************************************/ 20064 Slider.prototype = { 20065 _init: function _init() {}, // NOTE: Must exist to support bridget 20066 20067 constructor: Slider, 20068 20069 defaultOptions: { 20070 id: "", 20071 min: 0, 20072 max: 10, 20073 step: 1, 20074 precision: 0, 20075 orientation: 'horizontal', 20076 value: 5, 20077 range: false, 20078 selection: 'before', 20079 tooltip: 'show', 20080 tooltip_split: false, 20081 handle: 'round', 20082 reversed: false, 20083 rtl: 'auto', 20084 enabled: true, 20085 formatter: function formatter(val) { 20086 if (Array.isArray(val)) { 20087 return val[0] + " : " + val[1]; 20088 } else { 20089 return val; 20090 } 20091 }, 20092 natural_arrow_keys: false, 20093 ticks: [], 20094 ticks_positions: [], 20095 ticks_labels: [], 20096 ticks_snap_bounds: 0, 20097 ticks_tooltip: false, 20098 scale: 'linear', 20099 focus: false, 20100 tooltip_position: null, 20101 labelledby: null, 20102 rangeHighlights: [] 20103 }, 20104 20105 getElement: function getElement() { 20106 return this.sliderElem; 20107 }, 20108 20109 getValue: function getValue() { 20110 if (this.options.range) { 20111 return this._state.value; 20112 } else { 20113 return this._state.value[0]; 20114 } 20115 }, 20116 20117 setValue: function setValue(val, triggerSlideEvent, triggerChangeEvent) { 20118 if (!val) { 20119 val = 0; 20120 } 20121 var oldValue = this.getValue(); 20122 this._state.value = this._validateInputValue(val); 20123 var applyPrecision = this._applyPrecision.bind(this); 20124 20125 if (this.options.range) { 20126 this._state.value[0] = applyPrecision(this._state.value[0]); 20127 this._state.value[1] = applyPrecision(this._state.value[1]); 20128 20129 this._state.value[0] = Math.max(this.options.min, Math.min(this.options.max, this._state.value[0])); 20130 this._state.value[1] = Math.max(this.options.min, Math.min(this.options.max, this._state.value[1])); 20131 } else { 20132 this._state.value = applyPrecision(this._state.value); 20133 this._state.value = [Math.max(this.options.min, Math.min(this.options.max, this._state.value))]; 20134 this._addClass(this.handle2, 'hide'); 20135 if (this.options.selection === 'after') { 20136 this._state.value[1] = this.options.max; 20137 } else { 20138 this._state.value[1] = this.options.min; 20139 } 20140 } 20141 20142 if (this.options.max > this.options.min) { 20143 this._state.percentage = [this._toPercentage(this._state.value[0]), this._toPercentage(this._state.value[1]), this.options.step * 100 / (this.options.max - this.options.min)]; 20144 } else { 20145 this._state.percentage = [0, 0, 100]; 20146 } 20147 20148 this._layout(); 20149 var newValue = this.options.range ? this._state.value : this._state.value[0]; 20150 20151 this._setDataVal(newValue); 20152 if (triggerSlideEvent === true) { 20153 this._trigger('slide', newValue); 20154 } 20155 if (oldValue !== newValue && triggerChangeEvent === true) { 20156 this._trigger('change', { 20157 oldValue: oldValue, 20158 newValue: newValue 20159 }); 20160 } 20161 20162 return this; 20163 }, 20164 20165 destroy: function destroy() { 20166 // Remove event handlers on slider elements 20167 this._removeSliderEventHandlers(); 20168 20169 // Remove the slider from the DOM 20170 this.sliderElem.parentNode.removeChild(this.sliderElem); 20171 /* Show original <input> element */ 20172 this.element.style.display = ""; 20173 20174 // Clear out custom event bindings 20175 this._cleanUpEventCallbacksMap(); 20176 20177 // Remove data values 20178 this.element.removeAttribute("data"); 20179 20180 // Remove JQuery handlers/data 20181 if ($) { 20182 this._unbindJQueryEventHandlers(); 20183 this.$element.removeData('slider'); 20184 } 20185 }, 20186 20187 disable: function disable() { 20188 this._state.enabled = false;
20189 this.handle1.removeAttribute("tabindex"); 20190 this.handle2.removeAttribute("tabindex"); 20191 this._addClass(this.sliderElem, 'slider-disabled'); 20192 this._trigger('slideDisabled'); 20193 20194 return this; 20195 }, 20196 20197 enable: function enable() { 20198 this._state.enabled = true; 20199 this.handle1.setAttribute("tabindex", 0); 20200 this.handle2.setAttribute("tabindex", 0); 20201 this._removeClass(this.sliderElem, 'slider-disabled'); 20202 this._trigger('slideEnabled'); 20203 20204 return this; 20205 }, 20206 20207 toggle: function toggle() { 20208 if (this._state.enabled) { 20209 this.disable(); 20210 } else { 20211 this.enable(); 20212 } 20213 return this; 20214 }, 20215 20216 isEnabled: function isEnabled() { 20217 return this._state.enabled; 20218 }, 20219 20220 on: function on(evt, callback) { 20221 this._bindNonQueryEventHandler(evt, callback); 20222 return this; 20223 }, 20224 20225 off: function off(evt, callback) { 20226 if ($) { 20227 this.$element.off(evt, callback); 20228 this.$sliderElem.off(evt, callback); 20229 } else { 20230 this._unbindNonQueryEventHandler(evt, callback); 20231 } 20232 }, 20233 20234 getAttribute: function getAttribute(attribute) { 20235 if (attribute) { 20236 return this.options[attribute]; 20237 } else { 20238 return this.options; 20239 } 20240 }, 20241 20242 setAttribute: function setAttribute(attribute, value) { 20243 this.options[attribute] = value; 20244 return this; 20245 }, 20246 20247 refresh: function refresh() { 20248 this._removeSliderEventHandlers(); 20249 createNewSlider.call(this, this.element, this.options); 20250 if ($) { 20251 // Bind new instance of slider to the element 20252 $.data(this.element, 'slider', this); 20253 } 20254 return this; 20255 }, 20256 20257 relayout: function relayout() { 20258 this._resize(); 20259 this._layout(); 20260 return this; 20261 }, 20262 20263 /******************************+ 20264 HELPERS 20265 - Any method that is not part of the public interface. 20266 - Place it underneath this comment block and write its signature like so: 20267 _fnName : function() {...} 20268 ********************************/ 20269 _removeSliderEventHandlers: function _removeSliderEventHandlers() { 20270 // Remove keydown event listeners 20271 this.handle1.removeEventListener("keydown", this.handle1Keydown, false); 20272 this.handle2.removeEventListener("keydown", this.handle2Keydown, false); 20273 20274 //remove the listeners from the ticks and handles if they had their own listeners 20275 if (this.options.ticks_tooltip) { 20276 var ticks = this.ticksContainer.getElementsByClassName('slider-tick'); 20277 for (var i = 0; i < ticks.length; i++) { 20278 ticks[i].removeEventListener('mouseenter', this.ticksCallbackMap[i].mouseEnter, false); 20279 ticks[i].removeEventListener('mouseleave', this.ticksCallbackMap[i].mouseLeave, false); 20280 } 20281 this.handle1.removeEventListener('mouseenter', this.handleCallbackMap.handle1.mouseEnter, false); 20282 this.handle2.removeEventListener('mouseenter', this.handleCallbackMap.handle2.mouseEnter, false); 20283 this.handle1.removeEventListener('mouseleave', this.handleCallbackMap.handle1.mouseLeave, false); 20284 this.handle2.removeEventListener('mouseleave', this.handleCallbackMap.handle2.mouseLeave, false); 20285 } 20286 20287 this.handleCallbackMap = null; 20288 this.ticksCallbackMap = null; 20289 20290 if (this.showTooltip) { 20291 this.handle1.removeEventListener("focus", this.showTooltip, false); 20292 this.handle2.removeEventListener("focus", this.showTooltip, false); 20293 } 20294 if (this.hideTooltip) { 20295 this.handle1.removeEventListener("blur", this.hideTooltip, false); 20296 this.handle2.removeEventListener("blur", this.hideTooltip, false); 20297 } 20298 20299 // Remove event listeners from sliderElem 20300 if (this.showTooltip) { 20301 this.sliderElem.removeEventListener("mouseenter", this.showTooltip, false); 20302 } 20303 if (this.hideTooltip) { 20304 this.sliderElem.removeEventListener("mouseleave", this.hideTooltip, false); 20305 } 20306 this.sliderElem.removeEventListener("touchstart", this.touchstart, false); 20307 this.sliderElem.removeEventListener("touchmove", this.touchmove, false); 20308 this.sliderElem.removeEventListener("mousedown", this.mousedown, false); 20309 20310 // Remove window event listener 20311 window.removeEventListener("resize", this.resize, false); 20312 }, 20313 _bindNonQueryEventHandler: function _bindNonQueryEventHandler(evt, callback) { 20314 if (this.eventToCallbackMap[evt] === undefined) { 20315 this.eventToCallbackMap[evt] = []; 20316 } 20317 this.eventToCallbackMap[evt].push(callback); 20318 }, 20319 _unbindNonQueryEventHandler: function _unbindNonQueryEventHandler(evt, callback) { 20320 var callbacks = this.eventToCallbackMap[evt]; 20321 if (callbacks !== undefined) { 20322 for (var i = 0; i < callbacks.length; i++) { 20323 if (callbacks[i] === callback) { 20324 callbacks.splice(i, 1); 20325 break; 20326 } 20327 } 20328 } 20329 }, 20330 _cleanUpEventCallbacksMap: function _cleanUpEventCallbacksMap() { 20331 var eventNames = Object.keys(this.eventToCallbackMap); 20332 for (var i = 0; i < eventNames.length; i++) { 20333 var eventName = eventNames[i]; 20334 delete this.eventToCallbackMap[eventName]; 20335 } 20336 }, 20337 _showTooltip: function _showTooltip() { 20338 if (this.options.tooltip_split === false) { 20339 this._addClass(this.tooltip, 'in'); 20340 this.tooltip_min.style.display = 'none'; 20341 this.tooltip_max.style.display = 'none'; 20342 } else { 20343 this._addClass(this.tooltip_min, 'in'); 20344 this._addClass(this.tooltip_max, 'in'); 20345 this.tooltip.style.display = 'none'; 20346 } 20347 this._state.over = true; 20348 }, 20349 _hideTooltip: function _hideTooltip() { 20350 if (this._state.inDrag === false && this.alwaysShowTooltip !== true) { 20351 this._removeClass(this.tooltip, 'in'); 20352 this._removeClass(this.tooltip_min, 'in'); 20353 this._removeClass(this.tooltip_max, 'in'); 20354 } 20355 this._state.over = false;
20356 }, 20357 _setToolTipOnMouseOver: function _setToolTipOnMouseOver(tempState) { 20358 var formattedTooltipVal = this.options.formatter(!tempState ? this._state.value[0] : tempState.value[0]); 20359 var positionPercentages = !tempState ? getPositionPercentages(this._state, this.options.reversed) : getPositionPercentages(tempState, this.options.reversed); 20360 this._setText(this.tooltipInner, formattedTooltipVal); 20361 20362 this.tooltip.style[this.stylePos] = positionPercentages[0] + "%"; 20363 if (this.options.orientation === 'vertical') { 20364 this._css(this.tooltip, "margin-" + this.stylePos, -this.tooltip.offsetHeight / 2 + "px"); 20365 } else { 20366 this._css(this.tooltip, "margin-" + this.stylePos, -this.tooltip.offsetWidth / 2 + "px"); 20367 } 20368 20369 function getPositionPercentages(state, reversed) { 20370 if (reversed) { 20371 return [100 - state.percentage[0], this.options.range ? 100 - state.percentage[1] : state.percentage[1]]; 20372 } 20373 return [state.percentage[0], state.percentage[1]]; 20374 } 20375 }, 20376 _addTickListener: function _addTickListener() { 20377 return { 20378 addMouseEnter: function addMouseEnter(reference, tick, index) { 20379 var enter = function enter() { 20380 var tempState = reference._state; 20381 var idString = index >= 0 ? index : this.attributes['aria-valuenow'].value; 20382 var hoverIndex = parseInt(idString, 10); 20383 tempState.value[0] = hoverIndex; 20384 tempState.percentage[0] = reference.options.ticks_positions[hoverIndex]; 20385 reference._setToolTipOnMouseOver(tempState); 20386 reference._showTooltip(); 20387 }; 20388 tick.addEventListener("mouseenter", enter, false); 20389 return enter; 20390 }, 20391 addMouseLeave: function addMouseLeave(reference, tick) { 20392 var leave = function leave() { 20393 reference._hideTooltip(); 20394 }; 20395 tick.addEventListener("mouseleave", leave, false); 20396 return leave; 20397 } 20398 }; 20399 }, 20400 _layout: function _layout() { 20401 var positionPercentages; 20402 20403 if (this.options.reversed) { 20404 positionPercentages = [100 - this._state.percentage[0], this.options.range ? 100 - this._state.percentage[1] : this._state.percentage[1]]; 20405 } else { 20406 positionPercentages = [this._state.percentage[0], this._state.percentage[1]]; 20407 } 20408 20409 this.handle1.style[this.stylePos] = positionPercentages[0] + "%"; 20410 this.handle1.setAttribute('aria-valuenow', this._state.value[0]); 20411 if (isNaN(this.options.formatter(this._state.value[0]))) { 20412 this.handle1.setAttribute('aria-valuetext', this.options.formatter(this._state.value[0])); 20413 } 20414 20415 this.handle2.style[this.stylePos] = positionPercentages[1] + "%"; 20416 this.handle2.setAttribute('aria-valuenow', this._state.value[1]); 20417 if (isNaN(this.options.formatter(this._state.value[1]))) { 20418 this.handle2.setAttribute('aria-valuetext', this.options.formatter(this._state.value[1])); 20419 } 20420 20421 /* Position highlight range elements */ 20422 if (this.rangeHighlightElements.length > 0 && Array.isArray(this.options.rangeHighlights) && this.options.rangeHighlights.length > 0) { 20423 for (var _i = 0; _i < this.options.rangeHighlights.length; _i++) { 20424 var startPercent = this._toPercentage(this.options.rangeHighlights[_i].start); 20425 var endPercent = this._toPercentage(this.options.rangeHighlights[_i].end); 20426 20427 if (this.options.reversed) { 20428 var sp = 100 - endPercent; 20429 endPercent = 100 - startPercent; 20430 startPercent = sp; 20431 } 20432 20433 var currentRange = this._createHighlightRange(startPercent, endPercent); 20434 20435 if (currentRange) { 20436 if (this.options.orientation === 'vertical') { 20437 this.rangeHighlightElements[_i].style.top = currentRange.start + "%"; 20438 this.rangeHighlightElements[_i].style.height = currentRange.size + "%"; 20439 } else { 20440 if (this.options.rtl) { 20441 this.rangeHighlightElements[_i].style.right = currentRange.start + "%"; 20442 } else { 20443 this.rangeHighlightElements[_i].style.left = currentRange.start + "%"; 20444 } 20445 this.rangeHighlightElements[_i].style.width = currentRange.size + "%"; 20446 } 20447 } else { 20448 this.rangeHighlightElements[_i].style.display = "none"; 20449 } 20450 } 20451 } 20452 20453 /* Position ticks and labels */ 20454 if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) { 20455 20456 var styleSize = this.options.orientation === 'vertical' ? 'height' : 'width'; 20457 var styleMargin; 20458 if (this.options.orientation === 'vertical') { 20459 styleMargin = 'marginTop'; 20460 } else { 20461 if (this.options.rtl) { 20462 styleMargin = 'marginRight'; 20463 } else { 20464 styleMargin = 'marginLeft'; 20465 } 20466 } 20467 var labelSize = this._state.size / (this.options.ticks.length - 1); 20468 20469 if (this.tickLabelContainer) { 20470 var extraMargin = 0; 20471 if (this.options.ticks_positions.length === 0) { 20472 if (this.options.orientation !== 'vertical') { 20473 this.tickLabelContainer.style[styleMargin] = -labelSize / 2 + "px"; 20474 } 20475 20476 extraMargin = this.tickLabelContainer.offsetHeight; 20477 } else { 20478 /* Chidren are position absolute, calculate height by finding the max offsetHeight of a child */ 20479 for (i = 0; i < this.tickLabelContainer.childNodes.length; i++) { 20480 if (this.tickLabelContainer.childNodes[i].offsetHeight > extraMargin) { 20481 extraMargin = this.tickLabelContainer.childNodes[i].offsetHeight; 20482 } 20483 } 20484 } 20485 if (this.options.orientation === 'horizontal') { 20486 this.sliderElem.style.marginBottom = extraMargin + "px"; 20487 } 20488 } 20489 for (var i = 0; i < this.options.ticks.length; i++) { 20490 20491 var percentage = this.options.ticks_positions[i] || this._toPercentage(this.options.ticks[i]); 20492 20493 if (this.options.reversed) { 20494 percentage = 100 - percentage; 20495 } 20496 20497 this.ticks[i].style[this.stylePos] = percentage + "%"; 20498 20499 /* Set class labels to denote whether ticks are in the selection */ 20500 this._removeClass(this.ticks[i], 'in-selection'); 20501 if (!this.options.range) { 20502 if (this.options.selection === 'after' && percentage >= positionPercentages[0]) { 20503 this._addClass(this.ticks[i], 'in-selection'); 20504 } else if (this.options.selection === 'before' && percentage <= positionPercentages[0]) { 20505 this._addClass(this.ticks[i], 'in-selection'); 20506 } 20507 } else if (percentage >= positionPercentages[0] && percentage <= positionPercentages[1]) { 20508 this._addClass(this.ticks[i], 'in-selection'); 20509 } 20510 20511 if (this.tickLabels[i]) { 20512 this.tickLabels[i].style[styleSize] = labelSize + "px"; 20513 20514 if (this.options.orientation !== 'vertical' && this.options.ticks_positions[i] !== undefined) { 20515 this.tickLabels[i].style.position = 'absolute'; 20516 this.tickLabels[i].style[this.stylePos] = percentage + "%"; 20517 this.tickLabels[i].style[styleMargin] = -labelSize / 2 + 'px'; 20518 } else if (this.options.orientation === 'vertical') { 20519 if (this.options.rtl) { 20520 this.tickLabels[i].style['marginRight'] = this.sliderElem.offsetWidth + "px"; 20521 } else { 20522 this.tickLabels[i].style['marginLeft'] = this.sliderElem.offsetWidth + "px"; 20523 } 20524 this.tickLabelContainer.style[styleMargin] = this.sliderElem.offsetWidth / 2 * -1 + 'px'; 20525 } 20526 } 20527 } 20528 } 20529 20530 var formattedTooltipVal; 20531 20532 if (this.options.range) { 20533 formattedTooltipVal = this.options.formatter(this._state.value); 20534 this._setText(this.tooltipInner, formattedTooltipVal); 20535 this.tooltip.style[this.stylePos] = (positionPercentages[1] + positionPercentages[0]) / 2 + "%"; 20536 20537 if (this.options.orientation === 'vertical') { 20538 this._css(this.tooltip, "margin-" + this.stylePos, -this.tooltip.offsetHeight / 2 + "px"); 20539 } else { 20540 this._css(this.tooltip, "margin-" + this.stylePos, -this.tooltip.offsetWidth / 2 + "px"); 20541 } 20542 20543 var innerTooltipMinText = this.options.formatter(this._state.value[0]); 20544 this._setText(this.tooltipInner_min, innerTooltipMinText); 20545 20546 var innerTooltipMaxText = this.options.formatter(this._state.value[1]); 20547 this._setText(this.tooltipInner_max, innerTooltipMaxText); 20548 20549 this.tooltip_min.style[this.stylePos] = positionPercentages[0] + "%"; 20550 20551 if (this.options.orientation === 'vertical') { 20552 this._css(this.tooltip_min, "margin-" + this.stylePos, -this.tooltip_min.offsetHeight / 2 + "px"); 20553 } else { 20554 this._css(this.tooltip_min, "margin-" + this.stylePos, -this.tooltip_min.offsetWidth / 2 + "px"); 20555 } 20556 20557 this.tooltip_max.style[this.stylePos] = positionPercentages[1] + "%"; 20558 20559 if (this.options.orientation === 'vertical') { 20560 this._css(this.tooltip_max, "margin-" + this.stylePos, -this.tooltip_max.offsetHeight / 2 + "px"); 20561 } else { 20562 this._css(this.tooltip_max, "margin-" + this.stylePos, -this.tooltip_max.offsetWidth / 2 + "px"); 20563 } 20564 } else { 20565 formattedTooltipVal = this.options.formatter(this._state.value[0]); 20566 this._setText(this.tooltipInner, formattedTooltipVal); 20567 20568 this.tooltip.style[this.stylePos] = positionPercentages[0] + "%"; 20569 if (this.options.orientation === 'vertical') { 20570 this._css(this.tooltip, "margin-" + this.stylePos, -this.tooltip.offsetHeight / 2 + "px"); 20571 } else { 20572 this._css(this.tooltip, "margin-" + this.stylePos, -this.tooltip.offsetWidth / 2 + "px"); 20573 } 20574 } 20575 20576 if (this.options.orientation === 'vertical') { 20577 this.trackLow.style.top = '0'; 20578 this.trackLow.style.height = Math.min(positionPercentages[0], positionPercentages[1]) + '%'; 20579 20580 this.trackSelection.style.top = Math.min(positionPercentages[0], positionPercentages[1]) + '%'; 20581 this.trackSelection.style.height = Math.abs(positionPercentages[0] - positionPercentages[1]) + '%'; 20582 20583 this.trackHigh.style.bottom = '0'; 20584 this.trackHigh.style.height = 100 - Math.min(positionPercentages[0], positionPercentages[1]) - Math.abs(positionPercentages[0] - positionPercentages[1]) + '%'; 20585 } else { 20586 if (this.stylePos === 'right') { 20587 this.trackLow.style.right = '0'; 20588 } else { 20589 this.trackLow.style.left = '0'; 20590 } 20591 this.trackLow.style.width = Math.min(positionPercentages[0], positionPercentages[1]) + '%'; 20592 20593 if (this.stylePos === 'right') { 20594 this.trackSelection.style.right = Math.min(positionPercentages[0], positionPercentages[1]) + '%'; 20595 } else { 20596 this.trackSelection.style.left = Math.min(positionPercentages[0], positionPercentages[1]) + '%'; 20597 } 20598 this.trackSelection.style.width = Math.abs(positionPercentages[0] - positionPercentages[1]) + '%'; 20599 20600 if (this.stylePos === 'right') { 20601 this.trackHigh.style.left = '0'; 20602 } else { 20603 this.trackHigh.style.right = '0'; 20604 } 20605 this.trackHigh.style.width = 100 - Math.min(positionPercentages[0], positionPercentages[1]) - Math.abs(positionPercentages[0] - positionPercentages[1]) + '%'; 20606 20607 var offset_min = this.tooltip_min.getBoundingClientRect(); 20608 var offset_max = this.tooltip_max.getBoundingClientRect(); 20609 20610 if (this.options.tooltip_position === 'bottom') { 20611 if (offset_min.right > offset_max.left) { 20612 this._removeClass(this.tooltip_max, 'bottom'); 20613 this._addClass(this.tooltip_max, 'top'); 20614 this.tooltip_max.style.top = ''; 20615 this.tooltip_max.style.bottom = 22 + 'px'; 20616 } else { 20617 this._removeClass(this.tooltip_max, 'top'); 20618 this._addClass(this.tooltip_max, 'bottom'); 20619 this.tooltip_max.style.top = this.tooltip_min.style.top; 20620 this.tooltip_max.style.bottom = ''; 20621 } 20622 } else { 20623 if (offset_min.right > offset_max.left) { 20624 this._removeClass(this.tooltip_max, 'top'); 20625 this._addClass(this.tooltip_max, 'bottom'); 20626 this.tooltip_max.style.top = 18 + 'px'; 20627 } else { 20628 this._removeClass(this.tooltip_max, 'bottom'); 20629 this._addClass(this.tooltip_max, 'top'); 20630 this.tooltip_max.style.top = this.tooltip_min.style.top; 20631 } 20632 } 20633 } 20634 }, 20635 _createHighlightRange: function _createHighlightRange(start, end) { 20636 if (this._isHighlightRange(start, end)) { 20637 if (start > end) { 20638 return { 'start': end, 'size': start - end }; 20639 } 20640 return { 'start': start, 'size': end - start }; 20641 } 20642 return null; 20643 }, 20644 _isHighlightRange: function _isHighlightRange(start, end) { 20645 if (0 <= start && start <= 100 && 0 <= end && end <= 100) { 20646 return true; 20647 } else { 20648 return false;
20649 } 20650 }, 20651 _resize: function _resize(ev) { 20652 /*jshint unused:false*/ 20653 this._state.offset = this._offset(this.sliderElem); 20654 this._state.size = this.sliderElem[this.sizePos]; 20655 this._layout(); 20656 }, 20657 _removeProperty: function _removeProperty(element, prop) { 20658 if (element.style.removeProperty) { 20659 element.style.removeProperty(prop); 20660 } else { 20661 element.style.removeAttribute(prop); 20662 } 20663 }, 20664 _mousedown: function _mousedown(ev) { 20665 if (!this._state.enabled) { 20666 return false; 20667 } 20668 20669 this._state.offset = this._offset(this.sliderElem); 20670 this._state.size = this.sliderElem[this.sizePos]; 20671 20672 var percentage = this._getPercentage(ev); 20673 20674 if (this.options.range) { 20675 var diff1 = Math.abs(this._state.percentage[0] - percentage); 20676 var diff2 = Math.abs(this._state.percentage[1] - percentage); 20677 this._state.dragged = diff1 < diff2 ? 0 : 1; 20678 this._adjustPercentageForRangeSliders(percentage); 20679 } else { 20680 this._state.dragged = 0; 20681 } 20682 20683 this._state.percentage[this._state.dragged] = percentage; 20684 this._layout(); 20685 20686 if (this.touchCapable) { 20687 document.removeEventListener("touchmove", this.mousemove, false); 20688 document.removeEventListener("touchend", this.mouseup, false); 20689 } 20690 20691 if (this.mousemove) { 20692 document.removeEventListener("mousemove", this.mousemove, false); 20693 } 20694 if (this.mouseup) { 20695 document.removeEventListener("mouseup", this.mouseup, false); 20696 } 20697 20698 this.mousemove = this._mousemove.bind(this); 20699 this.mouseup = this._mouseup.bind(this); 20700 20701 if (this.touchCapable) { 20702 // Touch: Bind touch events: 20703 document.addEventListener("touchmove", this.mousemove, false); 20704 document.addEventListener("touchend", this.mouseup, false); 20705 } 20706 // Bind mouse events: 20707 document.addEventListener("mousemove", this.mousemove, false); 20708 document.addEventListener("mouseup", this.mouseup, false); 20709 20710 this._state.inDrag = true; 20711 var newValue = this._calculateValue(); 20712 20713 this._trigger('slideStart', newValue); 20714 20715 this._setDataVal(newValue); 20716 this.setValue(newValue, false, true); 20717 20718 ev.returnValue = false; 20719 20720 if (this.options.focus) { 20721 this._triggerFocusOnHandle(this._state.dragged); 20722 } 20723 20724 return true; 20725 }, 20726 _touchstart: function _touchstart(ev) { 20727 if (ev.changedTouches === undefined) { 20728 this._mousedown(ev); 20729 return; 20730 } 20731 20732 var touch = ev.changedTouches[0]; 20733 this.touchX = touch.pageX; 20734 this.touchY = touch.pageY; 20735 }, 20736 _triggerFocusOnHandle: function _triggerFocusOnHandle(handleIdx) { 20737 if (handleIdx === 0) { 20738 this.handle1.focus(); 20739 } 20740 if (handleIdx === 1) { 20741 this.handle2.focus(); 20742 } 20743 }, 20744 _keydown: function _keydown(handleIdx, ev) { 20745 if (!this._state.enabled) { 20746 return false; 20747 } 20748 20749 var dir; 20750 switch (ev.keyCode) { 20751 case 37: // left 20752 case 40: 20753 // down 20754 dir = -1; 20755 break; 20756 case 39: // right 20757 case 38: 20758 // up 20759 dir = 1; 20760 break; 20761 } 20762 if (!dir) { 20763 return; 20764 } 20765 20766 // use natural arrow keys instead of from min to max 20767 if (this.options.natural_arrow_keys) { 20768 var ifVerticalAndNotReversed = this.options.orientation === 'vertical' && !this.options.reversed; 20769 var ifHorizontalAndReversed = this.options.orientation === 'horizontal' && this.options.reversed; // @todo control with rtl 20770 20771 if (ifVerticalAndNotReversed || ifHorizontalAndReversed) { 20772 dir = -dir; 20773 } 20774 } 20775 20776 var val = this._state.value[handleIdx] + dir * this.options.step; 20777 var percentage = val / this.options.max * 100; 20778 this._state.keyCtrl = handleIdx; 20779 if (this.options.range) { 20780 this._adjustPercentageForRangeSliders(percentage); 20781 var val1 = !this._state.keyCtrl ? val : this._state.value[0]; 20782 var val2 = this._state.keyCtrl ? val : this._state.value[1]; 20783 val = [val1, val2]; 20784 } 20785 20786 this._trigger('slideStart', val); 20787 this._setDataVal(val); 20788 this.setValue(val, true, true); 20789 20790 this._setDataVal(val); 20791 this._trigger('slideStop', val); 20792 this._layout(); 20793 20794 this._pauseEvent(ev); 20795 delete this._state.keyCtrl; 20796 20797 return false;
20798 }, 20799 _pauseEvent: function _pauseEvent(ev) { 20800 if (ev.stopPropagation) { 20801 ev.stopPropagation(); 20802 } 20803 if (ev.preventDefault) { 20804 ev.preventDefault(); 20805 } 20806 ev.cancelBubble = true; 20807 ev.returnValue = false; 20808 }, 20809 _mousemove: function _mousemove(ev) { 20810 if (!this._state.enabled) { 20811 return false; 20812 } 20813 20814 var percentage = this._getPercentage(ev); 20815 this._adjustPercentageForRangeSliders(percentage); 20816 this._state.percentage[this._state.dragged] = percentage; 20817 this._layout(); 20818 20819 var val = this._calculateValue(true); 20820 this.setValue(val, true, true); 20821 20822 return false; 20823 }, 20824 _touchmove: function _touchmove(ev) { 20825 if (ev.changedTouches === undefined) { 20826 return; 20827 } 20828 20829 var touch = ev.changedTouches[0]; 20830 20831 var xDiff = touch.pageX - this.touchX; 20832 var yDiff = touch.pageY - this.touchY; 20833 20834 if (!this._state.inDrag) { 20835 // Vertical Slider 20836 if (this.options.orientation === 'vertical' && xDiff <= 5 && xDiff >= -5 && (yDiff >= 15 || yDiff <= -15)) { 20837 this._mousedown(ev); 20838 } 20839 // Horizontal slider. 20840 else if (yDiff <= 5 && yDiff >= -5 && (xDiff >= 15 || xDiff <= -15)) { 20841 this._mousedown(ev); 20842 } 20843 } 20844 }, 20845 _adjustPercentageForRangeSliders: function _adjustPercentageForRangeSliders(percentage) { 20846 if (this.options.range) { 20847 var precision = this._getNumDigitsAfterDecimalPlace(percentage); 20848 precision = precision ? precision - 1 : 0; 20849 var percentageWithAdjustedPrecision = this._applyToFixedAndParseFloat(percentage, precision); 20850 if (this._state.dragged === 0 && this._applyToFixedAndParseFloat(this._state.percentage[1], precision) < percentageWithAdjustedPrecision) { 20851 this._state.percentage[0] = this._state.percentage[1]; 20852 this._state.dragged = 1; 20853 } else if (this._state.dragged === 1 && this._applyToFixedAndParseFloat(this._state.percentage[0], precision) > percentageWithAdjustedPrecision) { 20854 this._state.percentage[1] = this._state.percentage[0]; 20855 this._state.dragged = 0; 20856 } else if (this._state.keyCtrl === 0 && this._state.value[1] / this.options.max * 100 < percentage) { 20857 this._state.percentage[0] = this._state.percentage[1]; 20858 this._state.keyCtrl = 1; 20859 this.handle2.focus(); 20860 } else if (this._state.keyCtrl === 1 && this._state.value[0] / this.options.max * 100 > percentage) { 20861 this._state.percentage[1] = this._state.percentage[0]; 20862 this._state.keyCtrl = 0; 20863 this.handle1.focus(); 20864 } 20865 } 20866 }, 20867 _mouseup: function _mouseup() { 20868 if (!this._state.enabled) { 20869 return false; 20870 } 20871 if (this.touchCapable) { 20872 // Touch: Unbind touch event handlers: 20873 document.removeEventListener("touchmove", this.mousemove, false); 20874 document.removeEventListener("touchend", this.mouseup, false); 20875 } 20876 // Unbind mouse event handlers: 20877 document.removeEventListener("mousemove", this.mousemove, false); 20878 document.removeEventListener("mouseup", this.mouseup, false); 20879 20880 this._state.inDrag = false; 20881 if (this._state.over === false) { 20882 this._hideTooltip(); 20883 } 20884 var val = this._calculateValue(true); 20885 20886 this._layout(); 20887 this._setDataVal(val); 20888 this._trigger('slideStop', val); 20889 20890 return false; 20891 }, 20892 _calculateValue: function _calculateValue(snapToClosestTick) { 20893 var val; 20894 if (this.options.range) { 20895 val = [this.options.min, this.options.max]; 20896 if (this._state.percentage[0] !== 0) { 20897 val[0] = this._toValue(this._state.percentage[0]); 20898 val[0] = this._applyPrecision(val[0]); 20899 } 20900 if (this._state.percentage[1] !== 100) { 20901 val[1] = this._toValue(this._state.percentage[1]); 20902 val[1] = this._applyPrecision(val[1]); 20903 } 20904 } else { 20905 val = this._toValue(this._state.percentage[0]); 20906 val = parseFloat(val); 20907 val = this._applyPrecision(val); 20908 } 20909 20910 if (snapToClosestTick) { 20911 var min = [val, Infinity]; 20912 for (var i = 0; i < this.options.ticks.length; i++) { 20913 var diff = Math.abs(this.options.ticks[i] - val); 20914 if (diff <= min[1]) { 20915 min = [this.options.ticks[i], diff]; 20916 } 20917 } 20918 if (min[1] <= this.options.ticks_snap_bounds) { 20919 return min[0]; 20920 } 20921 } 20922 20923 return val; 20924 }, 20925 _applyPrecision: function _applyPrecision(val) { 20926 var precision = this.options.precision || this._getNumDigitsAfterDecimalPlace(this.options.step); 20927 return this._applyToFixedAndParseFloat(val, precision); 20928 }, 20929 _getNumDigitsAfterDecimalPlace: function _getNumDigitsAfterDecimalPlace(num) { 20930 var match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/); 20931 if (!match) { 20932 return 0; 20933 } 20934 return Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0)); 20935 }, 20936 _applyToFixedAndParseFloat: function _applyToFixedAndParseFloat(num, toFixedInput) { 20937 var truncatedNum = num.toFixed(toFixedInput); 20938 return parseFloat(truncatedNum); 20939 }, 20940 /* 20941 Credits to Mike Samuel for the following method! 20942 Source: http://stackoverflow.com/questions/10454518/javascript-how-to-retrieve-the-number-of-decimals-of-a-string-number 20943 */ 20944 _getPercentage: function _getPercentage(ev) { 20945 if (this.touchCapable && (ev.type === 'touchstart' || ev.type === 'touchmove')) { 20946 ev = ev.touches[0]; 20947 } 20948 20949 var eventPosition = ev[this.mousePos]; 20950 var sliderOffset = this._state.offset[this.stylePos]; 20951 var distanceToSlide = eventPosition - sliderOffset; 20952 if (this.stylePos === 'right') { 20953 distanceToSlide = -distanceToSlide; 20954 } 20955 // Calculate what percent of the length the slider handle has slid 20956 var percentage = distanceToSlide / this._state.size * 100; 20957 percentage = Math.round(percentage / this._state.percentage[2]) * this._state.percentage[2]; 20958 if (this.options.reversed) { 20959 percentage = 100 - percentage; 20960 } 20961 20962 // Make sure the percent is within the bounds of the slider. 20963 // 0% corresponds to the 'min' value of the slide 20964 // 100% corresponds to the 'max' value of the slide 20965 return Math.max(0, Math.min(100, percentage)); 20966 }, 20967 _validateInputValue: function _validateInputValue(val) { 20968 if (!isNaN(+val)) { 20969 return +val; 20970 } else if (Array.isArray(val)) {
20971 this._validateArray(val); 20972 return val; 20973 } else { 20974 throw new Error(ErrorMsgs.formatInvalidInputErrorMsg(val)); 20975 } 20976 }, 20977 _validateArray: function _validateArray(val) { 20978 for (var i = 0; i < val.length; i++) { 20979 var input = val[i]; 20980 if (typeof input !== 'number') { 20981 throw new Error(ErrorMsgs.formatInvalidInputErrorMsg(input)); 20982 } 20983 } 20984 }, 20985 _setDataVal: function _setDataVal(val) { 20986 this.element.setAttribute('data-value', val); 20987 this.element.setAttribute('value', val); 20988 this.element.value = val; 20989 }, 20990 _trigger: function _trigger(evt, val) { 20991 val = val || val === 0 ? val : undefined; 20992 20993 var callbackFnArray = this.eventToCallbackMap[evt]; 20994 if (callbackFnArray && callbackFnArray.length) { 20995 for (var i = 0; i < callbackFnArray.length; i++) { 20996 var callbackFn = callbackFnArray[i]; 20997 callbackFn(val); 20998 } 20999 } 21000 21001 /* If JQuery exists, trigger JQuery events */ 21002 if ($) { 21003 this._triggerJQueryEvent(evt, val); 21004 } 21005 }, 21006 _triggerJQueryEvent: function _triggerJQueryEvent(evt, val) { 21007 var eventData = { 21008 type: evt, 21009 value: val 21010 }; 21011 this.$element.trigger(eventData); 21012 this.$sliderElem.trigger(eventData); 21013 }, 21014 _unbindJQueryEventHandlers: function _unbindJQueryEventHandlers() { 21015 this.$element.off(); 21016 this.$sliderElem.off(); 21017 }, 21018 _setText: function _setText(element, text) { 21019 if (typeof element.textContent !== "undefined") { 21020 element.textContent = text; 21021 } else if (typeof element.innerText !== "undefined") { 21022 element.innerText = text; 21023 } 21024 }, 21025 _removeClass: function _removeClass(element, classString) { 21026 var classes = classString.split(" "); 21027 var newClasses = element.className; 21028 21029 for (var i = 0; i < classes.length; i++) { 21030 var classTag = classes[i]; 21031 var regex = new RegExp("(?:\\s|^)" + classTag + "(?:\\s|$)"); 21032 newClasses = newClasses.replace(regex, " "); 21033 } 21034 21035 element.className = newClasses.trim(); 21036 }, 21037 _addClass: function _addClass(element, classString) { 21038 var classes = classString.split(" "); 21039 var newClasses = element.className; 21040 21041 for (var i = 0; i < classes.length; i++) { 21042 var classTag = classes[i]; 21043 var regex = new RegExp("(?:\\s|^)" + classTag + "(?:\\s|$)"); 21044 var ifClassExists = regex.test(newClasses); 21045 21046 if (!ifClassExists) { 21047 newClasses += " " + classTag; 21048 } 21049 } 21050 21051 element.className = newClasses.trim(); 21052 }, 21053 _offsetLeft: function _offsetLeft(obj) { 21054 return obj.getBoundingClientRect().left; 21055 }, 21056 _offsetRight: function _offsetRight(obj) { 21057 return obj.getBoundingClientRect().right; 21058 }, 21059 _offsetTop: function _offsetTop(obj) { 21060 var offsetTop = obj.offsetTop; 21061 while ((obj = obj.offsetParent) && !isNaN(obj.offsetTop)) { 21062 offsetTop += obj.offsetTop; 21063 if (obj.tagName !== 'BODY') { 21064 offsetTop -= obj.scrollTop; 21065 } 21066 } 21067 return offsetTop; 21068 }, 21069 _offset: function _offset(obj) { 21070 return { 21071 left: this._offsetLeft(obj), 21072 right: this._offsetRight(obj), 21073 top: this._offsetTop(obj) 21074 }; 21075 }, 21076 _css: function _css(elementRef, styleName, value) { 21077 if ($) { 21078 $.style(elementRef, styleName, value); 21079 } else { 21080 var style = styleName.replace(/^-ms-/, "ms-").replace(/-([\da-z])/gi, function (all, letter) { 21081 return letter.toUpperCase(); 21082 }); 21083 elementRef.style[style] = value; 21084 } 21085 }, 21086 _toValue: function _toValue(percentage) { 21087 return this.options.scale.toValue.apply(this, [percentage]); 21088 }, 21089 _toPercentage: function _toPercentage(value) { 21090 return this.options.scale.toPercentage.apply(this, [value]); 21091 }, 21092 _setTooltipPosition: function _setTooltipPosition() { 21093 var tooltips = [this.tooltip, this.tooltip_min, this.tooltip_max]; 21094 if (this.options.orientation === 'vertical') { 21095 var tooltipPos; 21096 if (this.options.tooltip_position) { 21097 tooltipPos = this.options.tooltip_position; 21098 } else { 21099 if (this.options.rtl) { 21100 tooltipPos = 'left'; 21101 } else { 21102 tooltipPos = 'right'; 21103 } 21104 } 21105 var oppositeSide = tooltipPos === 'left' ? 'right' : 'left'; 21106 tooltips.forEach(function (tooltip) { 21107 this._addClass(tooltip, tooltipPos); 21108 tooltip.style[oppositeSide] = '100%'; 21109 }.bind(this)); 21110 } else if (this.options.tooltip_position === 'bottom') { 21111 tooltips.forEach(function (tooltip) { 21112 this._addClass(tooltip, 'bottom'); 21113 tooltip.style.top = 22 + 'px'; 21114 }.bind(this)); 21115 } else { 21116 tooltips.forEach(function (tooltip) { 21117 this._addClass(tooltip, 'top'); 21118 tooltip.style.top = -this.tooltip.outerHeight - 14 + 'px'; 21119 }.bind(this)); 21120 } 21121 } 21122 }; 21123 21124 /********************************* 21125 Attach to global namespace 21126 *********************************/ 21127 if ($ && $.fn) { 21128 var autoRegisterNamespace = void 0; 21129 21130 if (!$.fn.slider) { 21131 $.bridget(NAMESPACE_MAIN, Slider); 21132 autoRegisterNamespace = NAMESPACE_MAIN; 21133 } else { 21134 if (windowIsDefined) { 21135 window.console.warn("bootstrap-slider.js - WARNING: $.fn.slider namespace is already bound. Use the $.fn.bootstrapSl
21135ider namespace instead."); 21136 } 21137 autoRegisterNamespace = NAMESPACE_ALTERNATE; 21138 } 21139 $.bridget(NAMESPACE_ALTERNATE, Slider); 21140 21141 // Auto-Register data-provide="slider" Elements 21142 $(function () { 21143 $("input[data-provide=slider]")[autoRegisterNamespace](); 21144 }); 21145 } 21146 })($); 21147 21148 return Slider; 21149}); 21150 21151+function() { 21152 ns('News.Utils').guid = function guid() { 21153 function s4() { 21154 return Math.floor((1 + Math.random()) * 0x10000) 21155 .toString(16) 21156 .substring(1); 21157 } 21158 return s4() + s4() + '-' + s4() + '-' + s4() + '-' + 21159 s4() + '-' + s4() + s4() + s4(); 21160 }; 21161}(); 21162+function() { 21163 //If browser does not support str.startWith (i.e. IE), create it manually 21164 if (!String.prototype.startsWith) { 21165 String.prototype.startsWith = function(searchString, position) { 21166 position = position || 0; 21167 return this.indexOf(searchString, position) === position; 21168 }; 21169 } 21170}(); 21171+function() { 21172 ns('News.Utils').electionBopSeats = function(officeID) { 21173 21174 if (officeID === "H") { 21175 return 435; 21176 } else if (officeID === "S") { 21177 return 100; 21178 } else if (officeID === "G") { 21179 return 50; 21180 } 21181 return 0; 21182 }; 21183 21184 21185}(); 21186(function($){ 21187 21188 "use strict"; 21189 21190 ns('News.App').TabletOrientationCheck = { 21191 21192 mql: window.matchMedia("(orientation: portrait)"), 21193 viewport: jQuery("meta[name=viewport]"), 21194 metaContentAttr: "width=device-width,initial-scale=", 21195 21196 load: function() { 21197 21198 // Only applies to tablets 21199 if (isMobile.tablet) { 21200 this.updateMetaViewport(this.mql); 21201 this.bindings(this.mql); 21202 } 21203 21204 }, 21205 21206 // Orientation change event listener 21207 bindings: function(mql) { 21208 mql.addListener(function(m) { 21209 News.App.TabletOrientationCheck.updateMetaViewport(mql) 21210 }); 21211 }, 21212 21213 updateMetaViewport: function(mql) { 21214 21215 // Default scale is always 1 21216 var scale = 1; 21217 21218 // Orientation is "Portrait" change to .74; 21219 if(mql.matches) { 21220 scale = ".7499"; 21221 } 21222 21223 this.viewport.attr("content",this.metaContentAttr + scale); 21224 21225 } 21226 } 21227 21228 News.App.TabletOrientationCheck.load(); 21229 21230})(jQuery); 21231/** 21232 * Owl Carousel v2.2.1 21233 * Copyright 2013-2017 David Deutsch 21234 * Licensed under () 21235 */ 21236/** 21237 * Owl carousel
vendor: 36,851 bytes, lines 21238-22645
21238 * @version 2.1.6 21239 * @author Bartosz Wojciechowski 21240 * @author David Deutsch 21241 * @license The MIT License (MIT) 21242 * @todo Lazy Load Icon 21243 * @todo prevent animationend bubling 21244 * @todo itemsScaleUp 21245 * @todo Test Zepto 21246 * @todo stagePadding calculate wrong active classes 21247 */ 21248;(function($, window, document, undefined) { 21249 21250 /** 21251 * Creates a carousel. 21252 * @class The Owl Carousel. 21253 * @public 21254 * @param {HTMLElement|jQuery} element - The element to create the carousel for. 21255 * @param {Object} [options] - The options 21256 */ 21257 function Owl(element, options) { 21258 21259 /** 21260 * Current settings for the carousel. 21261 * @public 21262 */ 21263 this.settings = null; 21264 21265 /** 21266 * Current options set by the caller including defaults. 21267 * @public 21268 */ 21269 this.options = $.extend({}, Owl.Defaults, options); 21270 21271 /** 21272 * Plugin element. 21273 * @public 21274 */ 21275 this.$element = $(element); 21276 21277 /** 21278 * Proxied event handlers. 21279 * @protected 21280 */ 21281 this._handlers = {}; 21282 21283 /** 21284 * References to the running plugins of this carousel. 21285 * @protected 21286 */ 21287 this._plugins = {}; 21288 21289 /** 21290 * Currently suppressed events to prevent them from beeing retriggered. 21291 * @protected 21292 */ 21293 this._supress = {}; 21294 21295 /** 21296 * Absolute current position. 21297 * @protected 21298 */ 21299 this._current = null; 21300 21301 /** 21302 * Animation speed in milliseconds. 21303 * @protected 21304 */ 21305 this._speed = null; 21306 21307 /** 21308 * Coordinates of all items in pixel. 21309 * @todo The name of this member is missleading. 21310 * @protected 21311 */ 21312 this._coordinates = []; 21313 21314 /** 21315 * Current breakpoint. 21316 * @todo Real media queries would be nice. 21317 * @protected 21318 */ 21319 this._breakpoint = null; 21320 21321 /** 21322 * Current width of the plugin element. 21323 */ 21324 this._width = null; 21325 21326 /** 21327 * All real items. 21328 * @protected 21329 */ 21330 this._items = []; 21331 21332 /** 21333 * All cloned items. 21334 * @protected 21335 */ 21336 this._clones = []; 21337 21338 /** 21339 * Merge values of all items. 21340 * @todo Maybe this could be part of a plugin. 21341 * @protected 21342 */ 21343 this._mergers = []; 21344 21345 /** 21346 * Widths of all items. 21347 */ 21348 this._widths = []; 21349 21350 /** 21351 * Invalidated parts within the update process. 21352 * @protected 21353 */ 21354 this._invalidated = {}; 21355 21356 /** 21357 * Ordered list of workers for the update process. 21358 * @protected 21359 */ 21360 this._pipe = []; 21361 21362 /** 21363 * Current state information for the drag operation. 21364 * @todo #261 21365 * @protected 21366 */ 21367 this._drag = { 21368 time: null, 21369 target: null, 21370 pointer: null, 21371 stage: { 21372 start: null, 21373 current: null 21374 }, 21375 direction: null 21376 }; 21377 21378 /** 21379 * Current state information and their tags. 21380 * @type {Object} 21381 * @protected 21382 */ 21383 this._states = { 21384 current: {}, 21385 tags: { 21386 'initializing': [ 'busy' ], 21387 'animating': [ 'busy' ], 21388 'dragging': [ 'interacting' ] 21389 } 21390 }; 21391 21392 $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) { 21393 this._handlers[handler] = $.proxy(this[handler], this); 21394 }, this)); 21395 21396 $.each(Owl.Plugins, $.proxy(function(key, plugin) { 21397 this._plugins[key.charAt(0).toLowerCase() + key.slice(1)] 21398 = new plugin(this); 21399 }, this)); 21400 21401 $.each(Owl.Workers, $.proxy(function(priority, worker) { 21402 this._pipe.push({ 21403 'filter': worker.filter, 21404 'run': $.proxy(worker.run, this) 21405 }); 21406 }, this)); 21407 21408 this.setup(); 21409 this.initialize(); 21410 } 21411 21412 /** 21413 * Default options for the carousel. 21414 * @public 21415 */ 21416 Owl.Defaults = { 21417 items: 3, 21418 loop: false, 21419 center: false, 21420 rewind: false, 21421 21422 mouseDrag: true, 21423 touchDrag: true, 21424 pullDrag: true, 21425 freeDrag: false, 21426 21427 margin: 0, 21428 stagePadding: 0, 21429 21430 merge: false, 21431 mergeFit: true, 21432 autoWidth: false, 21433 21434 startPosition: 0, 21435 rtl: false, 21436 21437 smartSpeed: 250, 21438 fluidSpeed: false, 21439 dragEndSpeed: false, 21440 21441 responsive: {}, 21442 responsiveRefreshRate: 200, 21443 responsiveBaseElement: window, 21444 21445 fallbackEasing: 'swing', 21446 21447 info: false, 21448 21449 nestedItemSelector: false, 21450 itemElement: 'div', 21451 stageElement: 'div', 21452 21453 refreshClass: 'owl-refresh', 21454 loadedClass: 'owl-loaded', 21455 loadingClass: 'owl-loading', 21456 rtlClass: 'owl-rtl', 21457 responsiveClass: 'owl-responsive', 21458 dragClass: 'owl-drag', 21459 itemClass: 'owl-item', 21460 stageClass: 'owl-stage', 21461 stageOuterClass: 'owl-stage-outer', 21462 grabClass: 'owl-grab' 21463 }; 21464 21465 /** 21466 * Enumeration for width. 21467 * @public 21468 * @readonly 21469 * @enum {String} 21470 */ 21471 Owl.Width = { 21472 Default: 'default', 21473 Inner: 'inner', 21474 Outer: 'outer' 21475 }; 21476 21477 /** 21478 * Enumeration for types. 21479 * @public 21480 * @readonly 21481 * @enum {String} 21482 */ 21483 Owl.Type = { 21484 Event: 'event', 21485 State: 'state' 21486 }; 21487 21488 /** 21489 * Contains all registered plugins. 21490 * @public 21491 */ 21492 Owl.Plugins = {}; 21493 21494 /** 21495 * List of workers involved in the update process. 21496 */ 21497 Owl.Workers = [ { 21498 filter: [ 'width', 'settings' ], 21499 run: function() { 21500 this._width = this.$element.width(); 21501 } 21502 }, { 21503 filter: [ 'width', 'items', 'settings' ], 21504 run: function(cache) { 21505 cache.current = this._items && this._items[this.relative(this._current)]; 21506 } 21507 }, { 21508 filter: [ 'items', 'settings' ], 21509 run: function() { 21510 this.$stage.children('.cloned').remove(); 21511 } 21512 }, { 21513 filter: [ 'width', 'items', 'settings' ], 21514 run: function(cache) { 21515 var margin = this.settings.margin || '', 21516 grid = !this.settings.autoWidth, 21517 rtl = this.settings.rtl, 21518 css = { 21519 'width': 'auto', 21520 'margin-left': rtl ? margin : '', 21521 'margin-right': rtl ? '' : margin 21522 }; 21523 21524 !grid && this.$stage.children().css(css); 21525 21526 cache.css = css; 21527 } 21528 }, { 21529 filter: [ 'width', 'items', 'settings' ], 21530 run: function(cache) { 21531 var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin, 21532 merge = null, 21533 iterator = this._items.length, 21534 grid = !this.settings.autoWidth, 21535 widths = []; 21536 21537 cache.items = { 21538 merge: false, 21539 width: width 21540 }; 21541 21542 while (iterator--) { 21543 merge = this._mergers[iterator]; 21544 merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge; 21545 21546 cache.items.merge = merge > 1 || cache.items.merge; 21547 21548 widths[iterator] = !grid ? this._items[iterator].width() : width * merge; 21549 } 21550 21551 this._widths = widths; 21552 } 21553 }, { 21554 filter: [ 'items', 'settings' ], 21555 run: function() { 21556 var clones = [], 21557 items = this._items, 21558 settings = this.settings, 21559 // TODO: Should be computed from number of min width items in stage 21560 view = Math.max(settings.items * 2, 4), 21561 size = Math.ceil(items.length / 2) * 2, 21562 repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0, 21563 append = '', 21564 prepend = ''; 21565 21566 repeat /= 2; 21567 21568 while (repeat--) { 21569 // Switch to only using appended clones 21570 clones.push(this.normalize(clones.length / 2, true)); 21571 append = append + items[clones[clones.length - 1]][0].outerHTML; 21572 clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true)); 21573 prepend = items[clones[clones.length - 1]][0].outerHTML + prepend; 21574 } 21575 21576 this._clones = clones; 21577 21578 $(append).addClass('cloned').appendTo(this.$stage); 21579 $(prepend).addClass('cloned').prependTo(this.$stage); 21580 } 21581 }, { 21582 filter: [ 'width', 'items', 'settings' ], 21583 run: function() { 21584 var rtl = this.settings.rtl ? 1 : -1, 21585 size = this._clones.length + this._items.length, 21586 iterator = -1, 21587 previous = 0, 21588 current = 0, 21589 coordinates = []; 21590 21591 while (++iterator < size) { 21592 previous = coordinates[iterator - 1] || 0; 21593 current = this._widths[this.relative(iterator)] + this.settings.margin; 21594 coordinates.push(previous + current * rtl); 21595 } 21596 21597 this._coordinates = coordinates; 21598 } 21599 }, { 21600 filter: [ 'width', 'items', 'settings' ], 21601 run: function() { 21602 var padding = this.settings.stagePadding, 21603 coordinates = this._coordinates, 21604 css = { 21605 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2, 21606 'padding-left': padding || '', 21607 'padding-right': padding || '' 21608 }; 21609 21610 this.$stage.css(css); 21611 } 21612 }, { 21613 filter: [ 'width', 'items', 'settings' ], 21614 run: function(cache) { 21615 var iterator = this._coordinates.length, 21616 grid = !this.settings.autoWidth, 21617 items = this.$stage.children(); 21618 21619 if (grid && cache.items.merge) { 21620 while (iterator--) { 21621 cache.css.width = this._widths[this.relative(iterator)]; 21622 items.eq(iterator).css(cache.css); 21623 } 21624 } else if (grid) { 21625 cache.css.width = cache.items.width; 21626 items.css(cache.css); 21627 } 21628 } 21629 }, { 21630 filter: [ 'items' ], 21631 run: function() { 21632 this._coordinates.length < 1 && this.$stage.removeAttr('style'); 21633 } 21634 }, { 21635 filter: [ 'width', 'items', 'settings' ], 21636 run: function(cache) { 21637 cache.current = cache.current ? this.$stage.children().index(cache.current) : 0; 21638 cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current)); 21639 this.reset(cache.current); 21640 } 21641 }, { 21642 filter: [ 'position' ], 21643 run: function() { 21644 this.animate(this.coordinates(this._current)); 21645 } 21646 }, { 21647 filter: [ 'width', 'position', 'items', 'settings' ], 21648 run: function() { 21649 var rtl = this.settings.rtl ? 1 : -1, 21650 padding = this.settings.stagePadding * 2, 21651 begin = this.coordinates(this.current()) + padding, 21652 end = begin + this.width() * rtl, 21653 inner, outer, matches = [], i, n; 21654 21655 for (i = 0, n = this._coordinates.length; i < n; i++) { 21656 inner = this._coordinates[i - 1] || 0; 21657 outer = Math.abs(this._coordinates[i]) + padding * rtl; 21658 21659 if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end))) 21660 || (this.op(outer, '<', begin) && this.op(outer, '>', end))) { 21661 matches.push(i); 21662 } 21663 } 21664 21665 this.$stage.children('.active').removeClass('active'); 21666 this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active'); 21667 21668 if (this.settings.center) { 21669 this.$stage.children('.center').removeClass('center'); 21670 this.$stage.children().eq(this.current()).addClass('center'); 21671 } 21672 } 21673 } ]; 21674 21675 /** 21676 * Initializes the carousel. 21677 * @protected 21678 */ 21679 Owl.prototype.initialize = function() { 21680 this.enter('initializing'); 21681 this.trigger('initialize'); 21682 21683 this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl); 21684 21685 if (this.settings.autoWidth && !this.is('pre-loading')) { 21686 var imgs, nestedSelector, width; 21687 imgs = this.$element.find('img'); 21688 nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined; 21689 width = this.$element.children(nestedSelector).width(); 21690 21691 if (imgs.length && width <= 0) { 21692 this.preloadAutoWidthImages(imgs); 21693 } 21694 } 21695 21696 this.$element.addClass(this.options.loadingClass); 21697 21698 // create stage 21699 this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>') 21700 .wrap('<div class="' + this.settings.stageOuterClass + '"/>'); 21701 21702 // append stage 21703 this.$element.append(this.$stage.parent()); 21704 21705 // append content 21706 this.replace(this.$element.children().not(this.$stage.parent())); 21707 21708 // check visibility 21709 if (this.$element.is(':visible')) { 21710 // update view 21711 this.refresh(); 21712 } else { 21713 // invalidate width 21714 this.invalidate('width'); 21715 } 21716 21717 this.$element 21718 .removeClass(this.options.loadingClass) 21719 .addClass(this.options.loadedClass); 21720 21721 // register event handlers 21722 this.registerEventHandlers(); 21723 21724 this.leave('initializing'); 21725 this.trigger('initialized'); 21726 }; 21727 21728 /** 21729 * Setups the current settings. 21730 * @todo Remove responsive classes. Why should adaptive designs be brought into IE8? 21731 * @todo Support for media queries by using `matchMedia` would be nice. 21732 * @public 21733 */ 21734 Owl.prototype.setup = function() { 21735 var viewport = this.viewport(), 21736 overwrites = this.options.responsive, 21737 match = -1, 21738 settings = null; 21739 21740 if (!overwrites) { 21741 settings = $.extend({}, this.options); 21742 } else { 21743 $.each(overwrites, function(breakpoint) { 21744 if (breakpoint <= viewport && breakpoint > match) { 21745 match = Number(breakpoint); 21746 } 21747 }); 21748 21749 settings = $.extend({}, this.options, overwrites[match]); 21750 if (typeof settings.stagePadding === 'function') { 21751 settings.stagePadding = settings.stagePadding(); 21752 } 21753 delete settings.responsive; 21754 21755 // responsive class 21756 if (settings.responsiveClass) { 21757 this.$element.attr('class', 21758 this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match) 21759 ); 21760 } 21761 } 21762 21763 this.trigger('change', { property: { name: 'settings', value: settings } }); 21764 this._breakpoint = match; 21765 this.settings = settings; 21766 this.invalidate('settings'); 21767 this.trigger('changed', { property: { name: 'settings', value: this.settings } }); 21768 }; 21769 21770 /** 21771 * Updates option logic if necessery. 21772 * @protected 21773 */ 21774 Owl.prototype.optionsLogic = function() { 21775 if (this.settings.autoWidth) { 21776 this.settings.stagePadding = false; 21777 this.settings.merge = false; 21778 } 21779 }; 21780 21781 /** 21782 * Prepares an item before add. 21783 * @todo Rename event parameter `content` to `item`. 21784 * @protected 21785 * @returns {jQuery|HTMLElement} - The item container. 21786 */ 21787 Owl.prototype.prepare = function(item) { 21788 var event = this.trigger('prepare', { content: item }); 21789 21790 if (!event.data) { 21791 event.data = $('<' + this.settings.itemElement + '/>') 21792 .addClass(this.options.itemClass).append(item) 21793 } 21794 21795 this.trigger('prepared', { content: event.data }); 21796 21797 return event.data; 21798 }; 21799 21800 /** 21801 * Updates the view. 21802 * @public 21803 */ 21804 Owl.prototype.update = function() { 21805 var i = 0, 21806 n = this._pipe.length, 21807 filter = $.proxy(function(p) { return this[p] }, this._invalidated), 21808 cache = {}; 21809 21810 while (i < n) { 21811 if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) { 21812 this._pipe[i].run(cache); 21813 } 21814 i++; 21815 } 21816 21817 this._invalidated = {}; 21818 21819 !this.is('valid') && this.enter('valid'); 21820 }; 21821 21822 /** 21823 * Gets the width of the view. 21824 * @public 21825 * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return. 21826 * @returns {Number} - The width of the view in pixel. 21827 */ 21828 Owl.prototype.width = function(dimension) { 21829 dimension = dimension || Owl.Width.Default; 21830 switch (dimension) { 21831 case Owl.Width.Inner: 21832 case Owl.Width.Outer: 21833 return this._width; 21834 default: 21835 return this._width - this.settings.stagePadding * 2 + this.settings.margin; 21836 } 21837 }; 21838 21839 /** 21840 * Refreshes the carousel primarily for adaptive purposes. 21841 * @public 21842 */ 21843 Owl.prototype.refresh = function() { 21844 this.enter('refreshing'); 21845 this.trigger('refresh'); 21846 21847 this.setup(); 21848 21849 this.optionsLogic(); 21850 21851 this.$element.addClass(this.options.refreshClass); 21852 21853 this.update(); 21854 21855 this.$element.removeClass(this.options.refreshClass); 21856 21857 this.leave('refreshing'); 21858 this.trigger('refreshed'); 21859 }; 21860 21861 /** 21862 * Checks window `resize` event. 21863 * @protected 21864 */ 21865 Owl.prototype.onThrottledResize = function() { 21866 window.clearTimeout(this.resizeTimer); 21867 this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate); 21868 }; 21869 21870 /** 21871 * Checks window `resize` event. 21872 * @protected 21873 */ 21874 Owl.prototype.onResize = function() { 21875 if (!this._items.length) { 21876 return false; 21877 } 21878 21879 if (this._width === this.$element.width()) { 21880 return false; 21881 } 21882 21883 if (!this.$element.is(':visible')) { 21884 return false; 21885 } 21886 21887 this.enter('resizing'); 21888 21889 if (this.trigger('resize').isDefaultPrevented()) { 21890 this.leave('resizing'); 21891 return false; 21892 } 21893 21894 this.invalidate('width'); 21895 21896 this.refresh(); 21897 21898 this.leave('resizing'); 21899 this.trigger('resized'); 21900 }; 21901 21902 /** 21903 * Registers event handlers. 21904 * @todo Check `msPointerEnabled` 21905 * @todo #261 21906 * @protected 21907 */ 21908 Owl.prototype.registerEventHandlers = function() { 21909 if ($.support.transition) { 21910 this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this)); 21911 } 21912 21913 if (this.settings.responsive !== false) { 21914 this.on(window, 'resize', this._handlers.onThrottledResize); 21915 } 21916 21917 if (this.settings.mouseDrag) { 21918 this.$element.addClass(this.options.dragClass); 21919 this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this)); 21920 this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false }); 21921 } 21922 21923 if (this.settings.touchDrag){ 21924 this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this)); 21925 this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this)); 21926 } 21927 }; 21928 21929 /** 21930 * Handles `touchstart` and `mousedown` events. 21931 * @todo Horizontal swipe threshold as option 21932 * @todo #261 21933 * @protected 21934 * @param {Event} event - The event arguments. 21935 */ 21936 Owl.prototype.onDragStart = function(event) { 21937 var stage = null; 21938 21939 if (event.which === 3) { 21940 return; 21941 } 21942 21943 if ($.support.transform) { 21944 stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(','); 21945 stage = { 21946 x: stage[stage.length === 16 ? 12 : 4], 21947 y: stage[stage.length === 16 ? 13 : 5] 21948 }; 21949 } else { 21950 stage = this.$stage.position(); 21951 stage = { 21952 x: this.settings.rtl ? 21953 stage.left + this.$stage.width() - this.width() + this.settings.margin : 21954 stage.left, 21955 y: stage.top 21956 }; 21957 } 21958 21959 if (this.is('animating')) { 21960 $.support.transform ? this.animate(stage.x) : this.$stage.stop() 21961 this.invalidate('position'); 21962 } 21963 21964 this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown'); 21965 21966 this.speed(0); 21967 21968 this._drag.time = new Date().getTime(); 21969 this._drag.target = $(event.target); 21970 this._drag.stage.start = stage; 21971 this._drag.stage.current = stage; 21972 this._drag.pointer = this.pointer(event); 21973 21974 $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this)); 21975 21976 $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) { 21977 var delta = this.difference(this._drag.pointer, this.pointer(event)); 21978 21979 $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this)); 21980 21981 if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) { 21982 return; 21983 } 21984 21985 event.preventDefault(); 21986 21987 this.enter('dragging'); 21988 this.trigger('drag'); 21989 }, this)); 21990 }; 21991 21992 /** 21993 * Handles the `touchmove` and `mousemove` events. 21994 * @todo #261 21995 * @protected 21996 * @param {Event} event - The event arguments. 21997 */ 21998 Owl.prototype.onDragMove = function(event) { 21999 var minimum = null, 22000 maximum = null, 22001 pull = null, 22002 delta = this.difference(this._drag.pointer, this.pointer(event)), 22003 stage = this.difference(this._drag.stage.start, delta); 22004 22005 if (!this.is('dragging')) { 22006 return; 22007 } 22008 22009 event.preventDefault(); 22010 22011 if (this.settings.loop) { 22012 minimum = this.coordinates(this.minimum()); 22013 maximum = this.coordinates(this.maximum() + 1) - minimum; 22014 stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum; 22015 } else { 22016 minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum()); 22017 maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum()); 22018 pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0; 22019 stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull); 22020 } 22021 22022 this._drag.stage.current = stage; 22023 22024 this.animate(stage.x); 22025 }; 22026 22027 /** 22028 * Handles the `touchend` and `mouseup` events. 22029 * @todo #261 22030 * @todo Threshold for click event 22031 * @protected 22032 * @param {Event} event - The event arguments. 22033 */ 22034 Owl.prototype.onDragEnd = function(event) { 22035 var delta = this.difference(this._drag.pointer, this.pointer(event)), 22036 stage = this._drag.stage.current, 22037 direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right'; 22038 22039 $(document).off('.owl.core'); 22040 22041 this.$element.removeClass(this.options.grabClass); 22042 22043 if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) { 22044 this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed); 22045 this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction)); 22046 this.invalidate('position'); 22047 this.update(); 22048 22049 this._drag.direction = direction; 22050 22051 if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) { 22052 this._drag.target.one('click.owl.core', function() { return false; }); 22053 } 22054 } 22055 22056 if (!this.is('dragging')) { 22057 return; 22058 } 22059 22060 this.leave('dragging'); 22061 this.trigger('dragged'); 22062 }; 22063 22064 /** 22065 * Gets absolute position of the closest item for a coordinate. 22066 * @todo Setting `freeDrag` makes `closest` not reusable. See #165. 22067 * @protected 22068 * @param {Number} coordinate - The coordinate in pixel. 22069 * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`. 22070 * @return {Number} - The absolute position of the closest item. 22071 */ 22072 Owl.prototype.closest = function(coordinate, direction) { 22073 var position = -1, 22074 pull = 30, 22075 width = this.width(), 22076 coordinates = this.coordinates(); 22077 22078 if (!this.settings.freeDrag) { 22079 // check closest item 22080 $.each(coordinates, $.proxy(function(index, value) { 22081 // on a left pull, check on current index 22082 if (direction === 'left' && coordinate > value - pull && coordinate < value + pull) { 22083 position = index; 22084 // on a right pull, check on previous index 22085 // to do so, subtract width from value and set position = index + 1 22086 } else if (direction === 'right' && coordinate > value - width - pull && coordinate < value - width + pull) { 22087 position = index + 1; 22088 } else if (this.op(coordinate, '<', value) 22089 && this.op(coordinate, '>', coordinates[index + 1] || value - width)) { 22090 position = direction === 'left' ? index + 1 : index; 22091 } 22092 return position === -1; 22093 }, this)); 22094 } 22095 22096 if (!this.settings.loop) { 22097 // non loop boundries 22098 if (this.op(coordinate, '>', coordinates[this.minimum()])) { 22099 position = coordinate = this.minimum(); 22100 } else if (this.op(coordinate, '<', coordinates[this.maximum()])) { 22101 position = coordinate = this.maximum(); 22102 } 22103 } 22104 22105 return position; 22106 }; 22107 22108 /** 22109 * Animates the stage. 22110 * @todo #270 22111 * @public 22112 * @param {Number} coordinate - The coordinate in pixels. 22113 */ 22114 Owl.prototype.animate = function(coordinate) { 22115 var animate = this.speed() > 0; 22116 22117 this.is('animating') && this.onTransitionEnd(); 22118 22119 if (animate) { 22120 this.enter('animating'); 22121 this.trigger('translate'); 22122 } 22123 22124 if ($.support.transform3d && $.support.transition) { 22125 this.$stage.css({ 22126 transform: 'translate3d(' + coordinate + 'px,0px,0px)', 22127 transition: (this.speed() / 1000) + 's' 22128 }); 22129 } else if (animate) { 22130 this.$stage.animate({ 22131 left: coordinate + 'px' 22132 }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this)); 22133 } else { 22134 this.$stage.css({ 22135 left: coordinate + 'px' 22136 }); 22137 } 22138 }; 22139 22140 /** 22141 * Checks whether the carousel is in a specific state or not. 22142 * @param {String} state - The state to check. 22143 * @returns {Boolean} - The flag which indicates if the carousel is busy. 22144 */ 22145 Owl.prototype.is = function(state) { 22146 return this._states.current[state] && this._states.current[state] > 0; 22147 }; 22148 22149 /** 22150 * Sets the absolute position of the current item. 22151 * @public 22152 * @param {Number} [position] - The new absolute position or nothing to leave it unchanged. 22153 * @returns {Number} - The absolute position of the current item. 22154 */ 22155 Owl.prototype.current = function(position) { 22156 if (position === undefined) { 22157 return this._current; 22158 } 22159 22160 if (this._items.length === 0) { 22161 return undefined; 22162 } 22163 22164 position = this.normalize(position); 22165 22166 if (this._current !== position) { 22167 var event = this.trigger('change', { property: { name: 'position', value: position } }); 22168 22169 if (event.data !== undefined) { 22170 position = this.normalize(event.data); 22171 } 22172 22173 this._current = position; 22174 22175 this.invalidate('position'); 22176 22177 this.trigger('changed', { property: { name: 'position', value: this._current } }); 22178 } 22179 22180 return this._current; 22181 }; 22182 22183 /** 22184 * Invalidates the given part of the update routine. 22185 * @param {String} [part] - The part to invalidate. 22186 * @returns {Array.<String>} - The invalidated parts. 22187 */ 22188 Owl.prototype.invalidate = function(part) { 22189 if ($.type(part) === 'string') { 22190 this._invalidated[part] = true; 22191 this.is('valid') && this.leave('valid'); 22192 } 22193 return $.map(this._invalidated, function(v, i) { return i }); 22194 }; 22195 22196 /** 22197 * Resets the absolute position of the current item. 22198 * @public 22199 * @param {Number} position - The absolute position of the new item. 22200 */ 22201 Owl.prototype.reset = function(position) { 22202 position = this.normalize(position); 22203 22204 if (position === undefined) { 22205 return; 22206 } 22207 22208 this._speed = 0; 22209 this._current = position; 22210 22211 this.suppress([ 'translate', 'translated' ]); 22212 22213 this.animate(this.coordinates(position)); 22214 22215 this.release([ 'translate', 'translated' ]); 22216 }; 22217 22218 /** 22219 * Normalizes an absolute or a relative position of an item. 22220 * @public 22221 * @param {Number} position - The absolute or relative position to normalize. 22222 * @param {Boolean} [relative=false] - Whether the given position is relative or not. 22223 * @returns {Number} - The normalized position. 22224 */ 22225 Owl.prototype.normalize = function(position, relative) { 22226 var n = this._items.length, 22227 m = relative ? 0 : this._clones.length; 22228 22229 if (!this.isNumeric(position) || n < 1) { 22230 position = undefined; 22231 } else if (position < 0 || position >= n + m) { 22232 position = ((position - m / 2) % n + n) % n + m / 2; 22233 } 22234 22235 return position; 22236 }; 22237 22238 /** 22239 * Converts an absolute position of an item into a relative one. 22240 * @public 22241 * @param {Number} position - The absolute position to convert. 22242 * @returns {Number} - The converted position. 22243 */ 22244 Owl.prototype.relative = function(position) { 22245 position -= this._clones.length / 2; 22246 return this.normalize(position, true); 22247 }; 22248 22249 /** 22250 * Gets the maximum position for the current item. 22251 * @public 22252 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 22253 * @returns {Number} 22254 */ 22255 Owl.prototype.maximum = function(relative) { 22256 var settings = this.settings, 22257 maximum = this._coordinates.length, 22258 iterator, 22259 reciprocalItemsWidth, 22260 elementWidth; 22261 22262 if (settings.loop) { 22263 maximum = this._clones.length / 2 + this._items.length - 1; 22264 } else if (settings.autoWidth || settings.merge) { 22265 iterator = this._items.length; 22266 reciprocalItemsWidth = this._items[--iterator].width(); 22267 elementWidth = this.$element.width(); 22268 while (iterator--) { 22269 reciprocalItemsWidth += this._items[iterator].width() + this.settings.margin; 22270 if (reciprocalItemsWidth > elementWidth) { 22271 break; 22272 } 22273 } 22274 maximum = iterator + 1; 22275 } else if (settings.center) { 22276 maximum = this._items.length - 1; 22277 } else { 22278 maximum = this._items.length - settings.items; 22279 } 22280 22281 if (relative) { 22282 maximum -= this._clones.length / 2; 22283 } 22284 22285 return Math.max(maximum, 0); 22286 }; 22287 22288 /** 22289 * Gets the minimum position for the current item. 22290 * @public 22291 * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position. 22292 * @returns {Number} 22293 */ 22294 Owl.prototype.minimum = function(relative) { 22295 return relative ? 0 : this._clones.length / 2; 22296 }; 22297 22298 /** 22299 * Gets an item at the specified relative position. 22300 * @public 22301 * @param {Number} [position] - The relative position of the item. 22302 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 22303 */ 22304 Owl.prototype.items = function(position) { 22305 if (position === undefined) { 22306 return this._items.slice(); 22307 } 22308 22309 position = this.normalize(position, true); 22310 return this._items[position]; 22311 }; 22312 22313 /** 22314 * Gets an item at the specified relative position. 22315 * @public 22316 * @param {Number} [position] - The relative position of the item. 22317 * @return {jQuery|Array.<jQuery>} - The item at the given position or all items if no position was given. 22318 */ 22319 Owl.prototype.mergers = function(position) { 22320 if (position === undefined) { 22321 return this._mergers.slice(); 22322 } 22323 22324 position = this.normalize(position, true); 22325 return this._mergers[position]; 22326 }; 22327 22328 /** 22329 * Gets the absolute positions of clones for an item. 22330 * @public 22331 * @param {Number} [position] - The relative position of the item. 22332 * @returns {Array.<Number>} - The absolute positions of clones for the item or all if no position was given. 22333 */ 22334 Owl.prototype.clones = function(position) { 22335 var odd = this._clones.length / 2, 22336 even = odd + this._items.length, 22337 map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 }; 22338 22339 if (position === undefined) { 22340 return $.map(this._clones, function(v, i) { return map(i) }); 22341 } 22342 22343 return $.map(this._clones, function(v, i) { return v === position ? map(i) : null }); 22344 }; 22345 22346 /** 22347 * Sets the current animation speed. 22348 * @public 22349 * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged. 22350 * @returns {Number} - The current animation speed in milliseconds. 22351 */ 22352 Owl.prototype.speed = function(speed) { 22353 if (speed !== undefined) { 22354 this._speed = speed; 22355 } 22356 22357 return this._speed; 22358 }; 22359 22360 /** 22361 * Gets the coordinate of an item. 22362 * @todo The name of this method is missleanding. 22363 * @public 22364 * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`. 22365 * @returns {Number|Array.<Number>} - The coordinate of the item in pixel or all coordinates. 22366 */ 22367 Owl.prototype.coordinates = function(position) { 22368 var multiplier = 1, 22369 newPosition = position - 1, 22370 coordinate; 22371 22372 if (position === undefined) { 22373 return $.map(this._coordinates, $.proxy(function(coordinate, index) { 22374 return this.coordinates(index); 22375 }, this)); 22376 } 22377 22378 if (this.settings.center) { 22379 if (this.settings.rtl) { 22380 multiplier = -1; 22381 newPosition = position + 1; 22382 } 22383 22384 coordinate = this._coordinates[position]; 22385 coordinate += (this.width() - coordinate + (this._coordinates[newPosition] || 0)) / 2 * multiplier; 22386 } else { 22387 coordinate = this._coordinates[newPosition] || 0; 22388 } 22389 22390 coordinate = Math.ceil(coordinate); 22391 22392 return coordinate; 22393 }; 22394 22395 /** 22396 * Calculates the speed for a translation. 22397 * @protected 22398 * @param {Number} from - The absolute position of the start item. 22399 * @param {Number} to - The absolute position of the target item. 22400 * @param {Number} [factor=undefined] - The time factor in milliseconds. 22401 * @returns {Number} - The time in milliseconds for the translation. 22402 */ 22403 Owl.prototype.duration = function(from, to, factor) { 22404 if (factor === 0) { 22405 return 0; 22406 } 22407 22408 return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed)); 22409 }; 22410 22411 /** 22412 * Slides to the specified item. 22413 * @public 22414 * @param {Number} position - The position of the item. 22415 * @param {Number} [speed] - The time in milliseconds for the transition. 22416 */ 22417 Owl.prototype.to = function(position, speed) { 22418 var current = this.current(), 22419 revert = null, 22420 distance = position - this.relative(current), 22421 direction = (distance > 0) - (distance < 0), 22422 items = this._items.length, 22423 minimum = this.minimum(), 22424 maximum = this.maximum(); 22425 22426 if (this.settings.loop) { 22427 if (!this.settings.rewind && Math.abs(distance) > items / 2) { 22428 distance += direction * -1 * items; 22429 } 22430 22431 position = current + distance; 22432 revert = ((position - minimum) % items + items) % items + minimum; 22433 22434 if (revert !== position && revert - distance <= maximum && revert - distance > 0) { 22435 current = revert - distance; 22436 position = revert; 22437 this.reset(current); 22438 } 22439 } else if (this.settings.rewind) { 22440 maximum += 1; 22441 position = (position % maximum + maximum) % maximum; 22442 } else { 22443 position = Math.max(minimum, Math.min(maximum, position)); 22444 } 22445 22446 this.speed(this.duration(current, position, speed)); 22447 this.current(position); 22448 22449 if (this.$element.is(':visible')) { 22450 this.update(); 22451 } 22452 }; 22453 22454 /** 22455 * Slides to the next item. 22456 * @public 22457 * @param {Number} [speed] - The time in milliseconds for the transition. 22458 */ 22459 Owl.prototype.next = function(speed) { 22460 speed = speed || false; 22461 this.to(this.relative(this.current()) + 1, speed); 22462 }; 22463 22464 /** 22465 * Slides to the previous item. 22466 * @public 22467 * @param {Number} [speed] - The time in milliseconds for the transition. 22468 */ 22469 Owl.prototype.prev = function(speed) { 22470 speed = speed || false; 22471 this.to(this.relative(this.current()) - 1, speed); 22472 }; 22473 22474 /** 22475 * Handles the end of an animation. 22476 * @protected 22477 * @param {Event} event - The event arguments. 22478 */ 22479 Owl.prototype.onTransitionEnd = function(event) { 22480 22481 // if css2 animation then event object is undefined 22482 if (event !== undefined) { 22483 event.stopPropagation(); 22484 22485 // Catch only owl-stage transitionEnd event 22486 if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) { 22487 return false; 22488 } 22489 } 22490 22491 this.leave('animating'); 22492 this.trigger('translated'); 22493 }; 22494 22495 /** 22496 * Gets viewport width. 22497 * @protected 22498 * @return {Number} - The width in pixel. 22499 */ 22500 Owl.prototype.viewport = function() { 22501 var width; 22502 if (this.options.responsiveBaseElement !== window) { 22503 width = $(this.options.responsiveBaseElement).width(); 22504 } else if (window.innerWidth) { 22505 width = window.innerWidth; 22506 } else if (document.documentElement && document.documentElement.clientWidth) { 22507 width = document.documentElement.clientWidth; 22508 } else { 22509 console.warn('Can not detect viewport width.'); 22510 } 22511 return width; 22512 }; 22513 22514 /** 22515 * Replaces the current content. 22516 * @public 22517 * @param {HTMLElement|jQuery|String} content - The new content. 22518 */ 22519 Owl.prototype.replace = function(content) { 22520 this.$stage.empty(); 22521 this._items = []; 22522 22523 if (content) { 22524 content = (content instanceof jQuery) ? content : $(content); 22525 } 22526 22527 if (this.settings.nestedItemSelector) { 22528 content = content.find('.' + this.settings.nestedItemSelector); 22529 } 22530 22531 content.filter(function() { 22532 return this.nodeType === 1; 22533 }).each($.proxy(function(index, item) { 22534 item = this.prepare(item); 22535 this.$stage.append(item); 22536 this._items.push(item); 22537 this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); 22538 }, this)); 22539 22540 this.reset(this.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0); 22541 22542 this.invalidate('items'); 22543 }; 22544 22545 /** 22546 * Adds an item. 22547 * @todo Use `item` instead of `content` for the event arguments. 22548 * @public 22549 * @param {HTMLElement|jQuery|String} content - The item content to add. 22550 * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end. 22551 */ 22552 Owl.prototype.add = function(content, position) { 22553 var current = this.relative(this._current); 22554 22555 position = position === undefined ? this._items.length : this.normalize(position, true); 22556 content = content instanceof jQuery ? content : $(content); 22557 22558 this.trigger('add', { content: content, position: position }); 22559 22560 content = this.prepare(content); 22561 22562 if (this._items.length === 0 || position === this._items.length) { 22563 this._items.length === 0 && this.$stage.append(content); 22564 this._items.length !== 0 && this._items[position - 1].after(content); 22565 this._items.push(content); 22566 this._mergers.push(content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); 22567 } else { 22568 this._items[position].before(content); 22569 this._items.splice(position, 0, content); 22570 this._mergers.splice(position, 0, content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1); 22571 } 22572 22573 this._items[current] && this.reset(this._items[current].index()); 22574 22575 this.invalidate('items'); 22576 22577 this.trigger('added', { content: content, position: position }); 22578 }; 22579 22580 /** 22581 * Removes an item by its position. 22582 * @todo Use `item` instead of `content` for the event arguments. 22583 * @public 22584 * @param {Number} position - The relative position of the item to remove. 22585 */ 22586 Owl.prototype.remove = function(position) { 22587 position = this.normalize(position, true); 22588 22589 if (position === undefined) { 22590 return; 22591 } 22592 22593 this.trigger('remove', { content: this._items[position], position: position }); 22594 22595 this._items[position].remove(); 22596 this._items.splice(position, 1); 22597 this._mergers.splice(position, 1); 22598 22599 this.invalidate('items'); 22600 22601 this.trigger('removed', { content: null, position: position }); 22602 }; 22603 22604 /** 22605 * Preloads images with auto width. 22606 * @todo Replace by a more generic approach 22607 * @protected 22608 */ 22609 Owl.prototype.preloadAutoWidthImages = function(images) { 22610 images.each($.proxy(function(i, element) { 22611 this.enter('pre-loading'); 22612 element = $(element); 22613 $(new Image()).one('load', $.proxy(function(e) { 22614 element.attr('src', e.target.src); 22615 element.css('opacity', 1); 22616 this.leave('pre-loading'); 22617 !this.is('pre-loading') && !this.is('initializing') && this.refresh(); 22618 }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina')); 22619 }, this)); 22620 }; 22621 22622 /** 22623 * Destroys the carousel. 22624 * @public 22625 */ 22626 Owl.prototype.destroy = function() { 22627 22628 this.$element.off('.owl.core'); 22629 this.$stage.off('.owl.core'); 22630 $(document).off('.owl.core'); 22631 22632 if (this.settings.responsive !== false) { 22633 window.clearTimeout(this.resizeTimer); 22634 this.off(window, 'resize', this._handlers.onThrottledResize); 22635 } 22636 22637 for (var i in this._plugins) { 22638 this._plugins[i].destroy(); 22639 } 22640 22641 this.$stage.children('.cloned').remove(); 22642 22643 this.$stage.unwrap(); 22644 this.$stage.children().contents().unwrap(); 22645 this.$stage.children().unwrap();
vendor: 8,263 bytes, lines 22646-22931
22646 22647 this.$element 22648 .removeClass(this.options.refreshClass) 22649 .removeClass(this.options.loadingClass) 22650 .removeClass(this.options.loadedClass) 22651 .removeClass(this.options.rtlClass) 22652 .removeClass(this.options.dragClass) 22653 .removeClass(this.options.grabClass) 22654 .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), '')) 22655 .removeData('owl.carousel'); 22656 }; 22657 22658 /** 22659 * Operators to calculate right-to-left and left-to-right. 22660 * @protected 22661 * @param {Number} [a] - The left side operand. 22662 * @param {String} [o] - The operator. 22663 * @param {Number} [b] - The right side operand. 22664 */ 22665 Owl.prototype.op = function(a, o, b) { 22666 var rtl = this.settings.rtl; 22667 switch (o) { 22668 case '<': 22669 return rtl ? a > b : a < b; 22670 case '>': 22671 return rtl ? a < b : a > b; 22672 case '>=': 22673 return rtl ? a <= b : a >= b; 22674 case '<=': 22675 return rtl ? a >= b : a <= b; 22676 default: 22677 break; 22678 } 22679 }; 22680 22681 /** 22682 * Attaches to an internal event. 22683 * @protected 22684 * @param {HTMLElement} element - The event source. 22685 * @param {String} event - The event name. 22686 * @param {Function} listener - The event handler to attach. 22687 * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not. 22688 */ 22689 Owl.prototype.on = function(element, event, listener, capture) { 22690 if (element.addEventListener) { 22691 element.addEventListener(event, listener, capture); 22692 } else if (element.attachEvent) { 22693 element.attachEvent('on' + event, listener); 22694 } 22695 }; 22696 22697 /** 22698 * Detaches from an internal event. 22699 * @protected 22700 * @param {HTMLElement} element - The event source. 22701 * @param {String} event - The event name. 22702 * @param {Function} listener - The attached event handler to detach. 22703 * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not. 22704 */ 22705 Owl.prototype.off = function(element, event, listener, capture) { 22706 if (element.removeEventListener) { 22707 element.removeEventListener(event, listener, capture); 22708 } else if (element.detachEvent) { 22709 element.detachEvent('on' + event, listener); 22710 } 22711 }; 22712 22713 /** 22714 * Triggers a public event. 22715 * @todo Remove `status`, `relatedTarget` should be used instead. 22716 * @protected 22717 * @param {String} name - The event name. 22718 * @param {*} [data=null] - The event data. 22719 * @param {String} [namespace=carousel] - The event namespace. 22720 * @param {String} [state] - The state which is associated with the event. 22721 * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not. 22722 * @returns {Event} - The event arguments. 22723 */ 22724 Owl.prototype.trigger = function(name, data, namespace, state, enter) { 22725 var status = { 22726 item: { count: this._items.length, index: this.current() } 22727 }, handler = $.camelCase( 22728 $.grep([ 'on', name, namespace ], function(v) { return v }) 22729 .join('-').toLowerCase() 22730 ), event = $.Event( 22731 [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(), 22732 $.extend({ relatedTarget: this }, status, data) 22733 ); 22734 22735 if (!this._supress[name]) { 22736 $.each(this._plugins, function(name, plugin) { 22737 if (plugin.onTrigger) { 22738 plugin.onTrigger(event); 22739 } 22740 }); 22741 22742 this.register({ type: Owl.Type.Event, name: name }); 22743 this.$element.trigger(event); 22744 22745 if (this.settings && typeof this.settings[handler] === 'function') { 22746 this.settings[handler].call(this, event); 22747 } 22748 } 22749 22750 return event; 22751 }; 22752 22753 /** 22754 * Enters a state. 22755 * @param name - The state name. 22756 */ 22757 Owl.prototype.enter = function(name) { 22758 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 22759 if (this._states.current[name] === undefined) { 22760 this._states.current[name] = 0; 22761 } 22762 22763 this._states.current[name]++; 22764 }, this)); 22765 }; 22766 22767 /** 22768 * Leaves a state. 22769 * @param name - The state name. 22770 */ 22771 Owl.prototype.leave = function(name) { 22772 $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) { 22773 this._states.current[name]--; 22774 }, this)); 22775 }; 22776 22777 /** 22778 * Registers an event or state. 22779 * @public 22780 * @param {Object} object - The event or state to register. 22781 */ 22782 Owl.prototype.register = function(object) { 22783 if (object.type === Owl.Type.Event) { 22784 if (!$.event.special[object.name]) { 22785 $.event.special[object.name] = {}; 22786 } 22787 22788 if (!$.event.special[object.name].owl) { 22789 var _default = $.event.special[object.name]._default; 22790 $.event.special[object.name]._default = function(e) { 22791 if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) { 22792 return _default.apply(this, arguments); 22793 } 22794 return e.namespace && e.namespace.indexOf('owl') > -1; 22795 }; 22796 $.event.special[object.name].owl = true; 22797 } 22798 } else if (object.type === Owl.Type.State) { 22799 if (!this._states.tags[object.name]) { 22800 this._states.tags[object.name] = object.tags; 22801 } else { 22802 this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags); 22803 } 22804 22805 this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) { 22806 return $.inArray(tag, this._states.tags[object.name]) === i; 22807 }, this)); 22808 } 22809 }; 22810 22811 /** 22812 * Suppresses events. 22813 * @protected 22814 * @param {Array.<String>} events - The events to suppress. 22815 */ 22816 Owl.prototype.suppress = function(events) { 22817 $.each(events, $.proxy(function(index, event) { 22818 this._supress[event] = true; 22819 }, this)); 22820 }; 22821 22822 /** 22823 * Releases suppressed events. 22824 * @protected 22825 * @param {Array.<String>} events - The events to release. 22826 */ 22827 Owl.prototype.release = function(events) { 22828 $.each(events, $.proxy(function(index, event) { 22829 delete this._supress[event]; 22830 }, this)); 22831 }; 22832 22833 /** 22834 * Gets unified pointer coordinates from event. 22835 * @todo #261 22836 * @protected 22837 * @param {Event} - The `mousedown` or `touchstart` event. 22838 * @returns {Object} - Contains `x` and `y` coordinates of current pointer position. 22839 */ 22840 Owl.prototype.pointer = function(event) { 22841 var result = { x: null, y: null }; 22842 22843 event = event.originalEvent || event || window.event; 22844 22845 event = event.touches && event.touches.length ? 22846 event.touches[0] : event.changedTouches && event.changedTouches.length ? 22847 event.changedTouches[0] : event; 22848 22849 if (event.pageX) { 22850 result.x = event.pageX; 22851 result.y = event.pageY; 22852 } else { 22853 result.x = event.clientX; 22854 result.y = event.clientY; 22855 } 22856 22857 return result; 22858 }; 22859 22860 /** 22861 * Determines if the input is a Number or something that can be coerced to a Number 22862 * @protected 22863 * @param {Number|String|Object|Array|Boolean|RegExp|Function|Symbol} - The input to be tested 22864 * @returns {Boolean} - An indication if the input is a Number or can be coerced to a Number 22865 */ 22866 Owl.prototype.isNumeric = function(number) { 22867 return !isNaN(parseFloat(number)); 22868 }; 22869 22870 /** 22871 * Gets the difference of two vectors. 22872 * @todo #261 22873 * @protected 22874 * @param {Object} - The first vector. 22875 * @param {Object} - The second vector. 22876 * @returns {Object} - The difference. 22877 */ 22878 Owl.prototype.difference = function(first, second) { 22879 return { 22880 x: first.x - second.x, 22881 y: first.y - second.y 22882 }; 22883 }; 22884 22885 /** 22886 * The jQuery Plugin for the Owl Carousel 22887 * @todo Navigation plugin `next` and `prev` 22888 * @public 22889 */ 22890 $.fn.owlCarousel = function(option) { 22891 var args = Array.prototype.slice.call(arguments, 1); 22892 22893 return this.each(function() { 22894 var $this = $(this), 22895 data = $this.data('owl.carousel'); 22896 22897 if (!data) { 22898 data = new Owl(this, typeof option == 'object' && option); 22899 $this.data('owl.carousel', data); 22900 22901 $.each([ 22902 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove' 22903 ], function(i, event) { 22904 data.register({ type: Owl.Type.Event, name: event }); 22905 data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) { 22906 if (e.namespace && e.relatedTarget !== this) { 22907 this.suppress([ event ]); 22908 data[event].apply(this, [].slice.call(arguments, 1)); 22909 this.release([ event ]); 22910 } 22911 }, data)); 22912 }); 22913 } 22914 22915 if (typeof option == 'string' && option.charAt(0) !== '_') { 22916 data[option].apply(data, args); 22917 } 22918 }); 22919 }; 22920 22921 /** 22922 * The constructor for the jQuery Plugin 22923 * @public 22924 */ 22925 $.fn.owlCarousel.Constructor = Owl; 22926 22927})(window.Zepto || window.jQuery, window, document); 22928 22929/** 22930 * AutoRefresh Plugin 22931 * @version 2.
vendor: 22,802 bytes, lines 22931-23831
229311.0 22932 * @author Artus Kolanowski 22933 * @author David Deutsch 22934 * @license The MIT License (MIT) 22935 */ 22936;(function($, window, document, undefined) { 22937 22938 /** 22939 * Creates the auto refresh plugin. 22940 * @class The Auto Refresh Plugin 22941 * @param {Owl} carousel - The Owl Carousel 22942 */ 22943 var AutoRefresh = function(carousel) { 22944 /** 22945 * Reference to the core. 22946 * @protected 22947 * @type {Owl} 22948 */ 22949 this._core = carousel; 22950 22951 /** 22952 * Refresh interval. 22953 * @protected 22954 * @type {number} 22955 */ 22956 this._interval = null; 22957 22958 /** 22959 * Whether the element is currently visible or not. 22960 * @protected 22961 * @type {Boolean} 22962 */ 22963 this._visible = null; 22964 22965 /** 22966 * All event handlers. 22967 * @protected 22968 * @type {Object} 22969 */ 22970 this._handlers = { 22971 'initialized.owl.carousel': $.proxy(function(e) { 22972 if (e.namespace && this._core.settings.autoRefresh) { 22973 this.watch(); 22974 } 22975 }, this) 22976 }; 22977 22978 // set default options 22979 this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options); 22980 22981 // register event handlers 22982 this._core.$element.on(this._handlers); 22983 }; 22984 22985 /** 22986 * Default options. 22987 * @public 22988 */ 22989 AutoRefresh.Defaults = { 22990 autoRefresh: true, 22991 autoRefreshInterval: 500 22992 }; 22993 22994 /** 22995 * Watches the element. 22996 */ 22997 AutoRefresh.prototype.watch = function() { 22998 if (this._interval) { 22999 return; 23000 } 23001 23002 this._visible = this._core.$element.is(':visible'); 23003 this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval); 23004 }; 23005 23006 /** 23007 * Refreshes the element. 23008 */ 23009 AutoRefresh.prototype.refresh = function() { 23010 if (this._core.$element.is(':visible') === this._visible) { 23011 return; 23012 } 23013 23014 this._visible = !this._visible; 23015 23016 this._core.$element.toggleClass('owl-hidden', !this._visible); 23017 23018 this._visible && (this._core.invalidate('width') && this._core.refresh()); 23019 }; 23020 23021 /** 23022 * Destroys the plugin. 23023 */ 23024 AutoRefresh.prototype.destroy = function() { 23025 var handler, property; 23026 23027 window.clearInterval(this._interval); 23028 23029 for (handler in this._handlers) { 23030 this._core.$element.off(handler, this._handlers[handler]); 23031 } 23032 for (property in Object.getOwnPropertyNames(this)) { 23033 typeof this[property] != 'function' && (this[property] = null); 23034 } 23035 }; 23036 23037 $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh; 23038 23039})(window.Zepto || window.jQuery, window, document); 23040 23041/** 23042 * Lazy Plugin 23043 * @version 2.1.0 23044 * @author Bartosz Wojciechowski 23045 * @author David Deutsch 23046 * @license The MIT License (MIT) 23047 */ 23048;(function($, window, document, undefined) { 23049 23050 /** 23051 * Creates the lazy plugin. 23052 * @class The Lazy Plugin 23053 * @param {Owl} carousel - The Owl Carousel 23054 */ 23055 var Lazy = function(carousel) { 23056 23057 /** 23058 * Reference to the core. 23059 * @protected 23060 * @type {Owl} 23061 */ 23062 this._core = carousel; 23063 23064 /** 23065 * Already loaded items. 23066 * @protected 23067 * @type {Array.<jQuery>} 23068 */ 23069 this._loaded = []; 23070 23071 /** 23072 * Event handlers. 23073 * @protected 23074 * @type {Object} 23075 */ 23076 this._handlers = { 23077 'initialized.owl.carousel change.owl.carousel resized.owl.carousel': $.proxy(function(e) { 23078 if (!e.namespace) { 23079 return; 23080 } 23081 23082 if (!this._core.settings || !this._core.settings.lazyLoad) { 23083 return; 23084 } 23085 23086 if ((e.property && e.property.name == 'position') || e.type == 'initialized') { 23087 var settings = this._core.settings, 23088 n = (settings.center && Math.ceil(settings.items / 2) || settings.items), 23089 i = ((settings.center && n * -1) || 0), 23090 position = (e.property && e.property.value !== undefined ? e.property.value : this._core.current()) + i, 23091 clones = this._core.clones().length, 23092 load = $.proxy(function(i, v) { this.load(v) }, this); 23093 23094 while (i++ < n) { 23095 this.load(clones / 2 + this._core.relative(position)); 23096 clones && $.each(this._core.clones(this._core.relative(position)), load); 23097 position++; 23098 } 23099 } 23100 }, this) 23101 }; 23102 23103 // set the default options 23104 this._core.options = $.extend({}, Lazy.Defaults, this._core.options); 23105 23106 // register event handler 23107 this._core.$element.on(this._handlers); 23108 }; 23109 23110 /** 23111 * Default options. 23112 * @public 23113 */ 23114 Lazy.Defaults = { 23115 lazyLoad: false 23116 }; 23117 23118 /** 23119 * Loads all resources of an item at the specified position. 23120 * @param {Number} position - The absolute position of the item. 23121 * @protected 23122 */ 23123 Lazy.prototype.load = function(position) { 23124 var $item = this._core.$stage.children().eq(position), 23125 $elements = $item && $item.find('.owl-lazy'); 23126 23127 if (!$elements || $.inArray($item.get(0), this._loaded) > -1) { 23128 return; 23129 } 23130 23131 $elements.each($.proxy(function(index, element) { 23132 var $element = $(element), image, 23133 url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src'); 23134 23135 this._core.trigger('load', { element: $element, url: url }, 'lazy'); 23136 23137 if ($element.is('img')) { 23138 $element.one('load.owl.lazy', $.proxy(function() { 23139 $element.css('opacity', 1); 23140 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 23141 }, this)).attr('src', url); 23142 } else { 23143 image = new Image(); 23144 image.onload = $.proxy(function() { 23145 $element.css({ 23146 'background-image': 'url("' + url + '")', 23147 'opacity': '1' 23148 }); 23149 this._core.trigger('loaded', { element: $element, url: url }, 'lazy'); 23150 }, this); 23151 image.src = url; 23152 } 23153 }, this)); 23154 23155 this._loaded.push($item.get(0)); 23156 }; 23157 23158 /** 23159 * Destroys the plugin. 23160 * @public 23161 */ 23162 Lazy.prototype.destroy = function() { 23163 var handler, property; 23164 23165 for (handler in this.handlers) { 23166 this._core.$element.off(handler, this.handlers[handler]); 23167 } 23168 for (property in Object.getOwnPropertyNames(this)) { 23169 typeof this[property] != 'function' && (this[property] = null); 23170 } 23171 }; 23172 23173 $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy; 23174 23175})(window.Zepto || window.jQuery, window, document); 23176 23177/** 23178 * AutoHeight Plugin 23179 * @version 2.1.0 23180 * @author Bartosz Wojciechowski 23181 * @author David Deutsch 23182 * @license The MIT License (MIT) 23183 */ 23184;(function($, window, document, undefined) { 23185 23186 /** 23187 * Creates the auto height plugin. 23188 * @class The Auto Height Plugin 23189 * @param {Owl} carousel - The Owl Carousel 23190 */ 23191 var AutoHeight = function(carousel) { 23192 /** 23193 * Reference to the core. 23194 * @protected 23195 * @type {Owl} 23196 */ 23197 this._core = carousel; 23198 23199 /** 23200 * All event handlers. 23201 * @protected 23202 * @type {Object} 23203 */ 23204 this._handlers = { 23205 'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) { 23206 if (e.namespace && this._core.settings.autoHeight) { 23207 this.update(); 23208 } 23209 }, this), 23210 'changed.owl.carousel': $.proxy(function(e) { 23211 if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){ 23212 this.update(); 23213 } 23214 }, this), 23215 'loaded.owl.lazy': $.proxy(function(e) { 23216 if (e.namespace && this._core.settings.autoHeight 23217 && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) { 23218 this.update(); 23219 } 23220 }, this) 23221 }; 23222 23223 // set default options 23224 this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options); 23225 23226 // register event handlers 23227 this._core.$element.on(this._handlers); 23228 }; 23229 23230 /** 23231 * Default options. 23232 * @public 23233 */ 23234 AutoHeight.Defaults = { 23235 autoHeight: false, 23236 autoHeightClass: 'owl-height' 23237 }; 23238 23239 /** 23240 * Updates the view. 23241 */ 23242 AutoHeight.prototype.update = function() { 23243 var start = this._core._current, 23244 end = start + this._core.settings.items, 23245 visible = this._core.$stage.children().toArray().slice(start, end), 23246 heights = [], 23247 maxheight = 0; 23248 23249 $.each(visible, function(index, item) { 23250 heights.push($(item).height()); 23251 }); 23252 23253 maxheight = Math.max.apply(null, heights); 23254 23255 this._core.$stage.parent() 23256 .height(maxheight) 23257 .addClass(this._core.settings.autoHeightClass); 23258 }; 23259 23260 AutoHeight.prototype.destroy = function() { 23261 var handler, property; 23262 23263 for (handler in this._handlers) { 23264 this._core.$element.off(handler, this._handlers[handler]); 23265 } 23266 for (property in Object.getOwnPropertyNames(this)) { 23267 typeof this[property] != 'function' && (this[property] = null); 23268 } 23269 }; 23270 23271 $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight; 23272 23273})(window.Zepto || window.jQuery, window, document); 23274 23275/** 23276 * Video Plugin 23277 * @version 2.1.0 23278 * @author Bartosz Wojciechowski 23279 * @author David Deutsch 23280 * @license The MIT License (MIT) 23281 */ 23282;(function($, window, document, undefined) { 23283 23284 /** 23285 * Creates the video plugin. 23286 * @class The Video Plugin 23287 * @param {Owl} carousel - The Owl Carousel 23288 */ 23289 var Video = function(carousel) { 23290 /** 23291 * Reference to the core. 23292 * @protected 23293 * @type {Owl} 23294 */ 23295 this._core = carousel; 23296 23297 /** 23298 * Cache all video URLs. 23299 * @protected 23300 * @type {Object} 23301 */ 23302 this._videos = {}; 23303 23304 /** 23305 * Current playing item. 23306 * @protected 23307 * @type {jQuery} 23308 */ 23309 this._playing = null; 23310 23311 /** 23312 * All event handlers. 23313 * @todo The cloned content removale is too late 23314 * @protected 23315 * @type {Object} 23316 */ 23317 this._handlers = { 23318 'initialized.owl.carousel': $.proxy(function(e) { 23319 if (e.namespace) { 23320 this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] }); 23321 } 23322 }, this), 23323 'resize.owl.carousel': $.proxy(function(e) { 23324 if (e.namespace && this._core.settings.video && this.isInFullScreen()) { 23325 e.preventDefault(); 23326 } 23327 }, this), 23328 'refreshed.owl.carousel': $.proxy(function(e) { 23329 if (e.namespace && this._core.is('resizing')) { 23330 this._core.$stage.find('.cloned .owl-video-frame').remove(); 23331 } 23332 }, this), 23333 'changed.owl.carousel': $.proxy(function(e) { 23334 if (e.namespace && e.property.name === 'position' && this._playing) { 23335 this.stop(); 23336 } 23337 }, this), 23338 'prepared.owl.carousel': $.proxy(function(e) { 23339 if (!e.namespace) { 23340 return; 23341 } 23342 23343 var $element = $(e.content).find('.owl-video'); 23344 23345 if ($element.length) { 23346 $element.css('display', 'none'); 23347 this.fetch($element, $(e.content)); 23348 } 23349 }, this) 23350 }; 23351 23352 // set default options 23353 this._core.options = $.extend({}, Video.Defaults, this._core.options); 23354 23355 // register event handlers 23356 this._core.$element.on(this._handlers); 23357 23358 this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) { 23359 this.play(e); 23360 }, this)); 23361 }; 23362 23363 /** 23364 * Default options. 23365 * @public 23366 */ 23367 Video.Defaults = { 23368 video: false, 23369 videoHeight: false, 23370 videoWidth: false 23371 }; 23372 23373 /** 23374 * Gets the video ID and the type (YouTube/Vimeo/vzaar only). 23375 * @protected 23376 * @param {jQuery} target - The target containing the video data. 23377 * @param {jQuery} item - The item containing the video. 23378 */ 23379 Video.prototype.fetch = function(target, item) { 23380 var type = (function() { 23381 if (target.attr('data-vimeo-id')) { 23382 return 'vimeo'; 23383 } else if (target.attr('data-vzaar-id')) { 23384 return 'vzaar' 23385 } else { 23386 return 'youtube'; 23387 } 23388 })(), 23389 id = target.attr('data-vimeo-id') || target.attr('data-youtube-id') || target.attr('data-vzaar-id'), 23390 width = target.attr('data-width') || this._core.settings.videoWidth, 23391 height = target.attr('data-height') || this._core.settings.videoHeight, 23392 url = target.attr('href'); 23393 23394 if (url) { 23395 23396 /* 23397 Parses the id's out of the following urls (and probably more): 23398 https://www.youtube.com/watch?v=:id 23399 https://youtu.be/:id 23400 https://vimeo.com/:id 23401 https://vimeo.com/channels/:channel/:id 23402 https://vimeo.com/groups/:group/videos/:id 23403 https://app.vzaar.com/videos/:id 23404 23405 Visual example: https://regexper.com/#(http%3A%7Chttps%3A%7C)%5C%2F%5C%2F(player.%7Cwww.%7Capp.)%3F(vimeo%5C.com%7Cyoutu(be%5C.com%7C%5C.be%7Cbe%5C.googleapis%5C.com)%7Cvzaar%5C.com)%5C%2F(video%5C%2F%7Cvideos%5C%2F%7Cembed%5C%2F%7Cchannels%5C%2F.%2B%5C%2F%7Cgroups%5C%2F.%2B%5C%2F%7Cwatch%5C%3Fv%3D%7Cv%5C%2F)%3F(%5BA-Za-z0-9._%25-%5D*)(%5C%26%5CS%2B)%3F 23406 */ 23407 23408 id = url.match(/(http:|https:|)\/\/(player.|www.|app.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com)|vzaar\.com)\/(video\/|videos\/|embed\/|channels\/.+\/|groups\/.+\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/); 23409 23410 if (id[3].indexOf('youtu') > -1) { 23411 type = 'youtube'; 23412 } else if (id[3].indexOf('vimeo') > -1) { 23413 type = 'vimeo'; 23414 } else if (id[3].indexOf('vzaar') > -1) { 23415 type = 'vzaar'; 23416 } else { 23417 throw new Error('Video URL not supported.'); 23418 } 23419 id = id[6]; 23420 } else { 23421 throw new Error('Missing video URL.'); 23422 } 23423 23424 this._videos[url] = { 23425 type: type, 23426 id: id, 23427 width: width, 23428 height: height 23429 }; 23430 23431 item.attr('data-video', url); 23432 23433 this.thumbnail(target, this._videos[url]); 23434 }; 23435 23436 /** 23437 * Creates video thumbnail. 23438 * @protected 23439 * @param {jQuery} target - The target containing the video data. 23440 * @param {Object} info - The video info object. 23441 * @see `fetch` 23442 */ 23443 Video.prototype.thumbnail = function(target, video) { 23444 var tnLink, 23445 icon, 23446 path, 23447 dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '', 23448 customTn = target.find('img'), 23449 srcType = 'src', 23450 lazyClass = '', 23451 settings = this._core.settings, 23452 create = function(path) { 23453 icon = '<div class="owl-video-play-icon"></div>'; 23454 23455 if (settings.lazyLoad) { 23456 tnLink = '<div class="owl-video-tn ' + lazyClass + '" ' + srcType + '="' + path + '"></div>'; 23457 } else { 23458 tnLink = '<div class="owl-video-tn" style="opacity:1;background-image:url(' + path + ')"></div>'; 23459 } 23460 target.after(tnLink); 23461 target.after(icon); 23462 }; 23463 23464 // wrap video content into owl-video-wrapper div 23465 target.wrap('<div class="owl-video-wrapper"' + dimensions + '></div>'); 23466 23467 if (this._core.settings.lazyLoad) { 23468 srcType = 'data-src'; 23469 lazyClass = 'owl-lazy'; 23470 } 23471 23472 // custom thumbnail 23473 if (customTn.length) { 23474 create(customTn.attr(srcType)); 23475 customTn.remove(); 23476 return false; 23477 } 23478 23479 if (video.type === 'youtube') { 23480 path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg"; 23481 create(path); 23482 } else if (video.type === 'vimeo') { 23483 $.ajax({ 23484 type: 'GET', 23485 url: '//vimeo.com/api/v2/video/' + video.id + '.json', 23486 jsonp: 'callback', 23487 dataType: 'jsonp', 23488 success: function(data) { 23489 path = data[0].thumbnail_large; 23490 create(path); 23491 } 23492 }); 23493 } else if (video.type === 'vzaar') { 23494 $.ajax({ 23495 type: 'GET', 23496 url: '//vzaar.com/api/videos/' + video.id + '.json', 23497 jsonp: 'callback', 23498 dataType: 'jsonp', 23499 success: function(data) { 23500 path = data.framegrab_url; 23501 create(path); 23502 } 23503 }); 23504 } 23505 }; 23506 23507 /** 23508 * Stops the current video. 23509 * @public 23510 */ 23511 Video.prototype.stop = function() { 23512 this._core.trigger('stop', null, 'video'); 23513 this._playing.find('.owl-video-frame').remove(); 23514 this._playing.removeClass('owl-video-playing'); 23515 this._playing = null; 23516 this._core.leave('playing'); 23517 this._core.trigger('stopped', null, 'video'); 23518 }; 23519 23520 /** 23521 * Starts the current video. 23522 * @public 23523 * @param {Event} event - The event arguments. 23524 */ 23525 Video.prototype.play = function(event) { 23526 var target = $(event.target), 23527 item = target.closest('.' + this._core.settings.itemClass), 23528 video = this._videos[item.attr('data-video')], 23529 width = video.width || '100%', 23530 height = video.height || this._core.$stage.height(), 23531 html; 23532 23533 if (this._playing) { 23534 return; 23535 } 23536 23537 this._core.enter('playing'); 23538 this._core.trigger('play', null, 'video'); 23539 23540 item = this._core.items(this._core.relative(item.index())); 23541 23542 this._core.reset(item.index()); 23543 23544 if (video.type === 'youtube') { 23545 html = '<iframe width="' + width + '" height="' + height + '" src="//www.youtube.com/embed/' + 23546 video.id + '?autoplay=1&rel=0&v=' + video.id + '" frameborder="0" allowfullscreen></iframe>'; 23547 } else if (video.type === 'vimeo') { 23548 html = '<iframe src="//player.vimeo.com/video/' + video.id + 23549 '?autoplay=1" width="' + width + '" height="' + height + 23550 '" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>'; 23551 } else if (video.type === 'vzaar') { 23552 html = '<iframe frameborder="0"' + 'height="' + height + '"' + 'width="' + width + 23553 '" allowfullscreen mozallowfullscreen webkitAllowFullScreen ' + 23554 'src="//view.vzaar.com/' + video.id + '/player?autoplay=true"></iframe>'; 23555 } 23556 23557 $('<div class="owl-video-frame">' + html + '</div>').insertAfter(item.find('.owl-video')); 23558 23559 this._playing = item.addClass('owl-video-playing'); 23560 }; 23561 23562 /** 23563 * Checks whether an video is currently in full screen mode or not. 23564 * @todo Bad style because looks like a readonly method but changes members. 23565 * @protected 23566 * @returns {Boolean} 23567 */ 23568 Video.prototype.isInFullScreen = function() { 23569 var element = document.fullscreenElement || document.mozFullScreenElement || 23570 document.webkitFullscreenElement; 23571 23572 return element && $(element).parent().hasClass('owl-video-frame'); 23573 }; 23574 23575 /** 23576 * Destroys the plugin. 23577 */ 23578 Video.prototype.destroy = function() { 23579 var handler, property; 23580 23581 this._core.$element.off('click.owl.video'); 23582 23583 for (handler in this._handlers) { 23584 this._core.$element.off(handler, this._handlers[handler]); 23585 } 23586 for (property in Object.getOwnPropertyNames(this)) { 23587 typeof this[property] != 'function' && (this[property] = null); 23588 } 23589 }; 23590 23591 $.fn.owlCarousel.Constructor.Plugins.Video = Video; 23592 23593})(window.Zepto || window.jQuery, window, document); 23594 23595/** 23596 * Animate Plugin 23597 * @version 2.1.0 23598 * @author Bartosz Wojciechowski 23599 * @author David Deutsch 23600 * @license The MIT License (MIT) 23601 */ 23602;(function($, window, document, undefined) { 23603 23604 /** 23605 * Creates the animate plugin. 23606 * @class The Navigation Plugin 23607 * @param {Owl} scope - The Owl Carousel 23608 */ 23609 var Animate = function(scope) { 23610 this.core = scope; 23611 this.core.options = $.extend({}, Animate.Defaults, this.core.options); 23612 this.swapping = true; 23613 this.previous = undefined; 23614 this.next = undefined; 23615 23616 this.handlers = { 23617 'change.owl.carousel': $.proxy(function(e) { 23618 if (e.namespace && e.property.name == 'position') { 23619 this.previous = this.core.current(); 23620 this.next = e.property.value; 23621 } 23622 }, this), 23623 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) { 23624 if (e.namespace) { 23625 this.swapping = e.type == 'translated'; 23626 } 23627 }, this), 23628 'translate.owl.carousel': $.proxy(function(e) { 23629 if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) { 23630 this.swap(); 23631 } 23632 }, this) 23633 }; 23634 23635 this.core.$element.on(this.handlers); 23636 }; 23637 23638 /** 23639 * Default options. 23640 * @public 23641 */ 23642 Animate.Defaults = { 23643 animateOut: false, 23644 animateIn: false 23645 }; 23646 23647 /** 23648 * Toggles the animation classes whenever an translations starts. 23649 * @protected 23650 * @returns {Boolean|undefined} 23651 */ 23652 Animate.prototype.swap = function() { 23653 23654 if (this.core.settings.items !== 1) { 23655 return; 23656 } 23657 23658 if (!$.support.animation || !$.support.transition) { 23659 return; 23660 } 23661 23662 this.core.speed(0); 23663 23664 var left, 23665 clear = $.proxy(this.clear, this), 23666 previous = this.core.$stage.children().eq(this.previous), 23667 next = this.core.$stage.children().eq(this.next), 23668 incoming = this.core.settings.animateIn, 23669 outgoing = this.core.settings.animateOut; 23670 23671 if (this.core.current() === this.previous) { 23672 return; 23673 } 23674 23675 if (outgoing) { 23676 left = this.core.coordinates(this.previous) - this.core.coordinates(this.next); 23677 previous.one($.support.animation.end, clear) 23678 .css( { 'left': left + 'px' } ) 23679 .addClass('animated owl-animated-out') 23680 .addClass(outgoing); 23681 } 23682 23683 if (incoming) { 23684 next.one($.support.animation.end, clear) 23685 .addClass('animated owl-animated-in') 23686 .addClass(incoming); 23687 } 23688 }; 23689 23690 Animate.prototype.clear = function(e) { 23691 $(e.target).css( { 'left': '' } ) 23692 .removeClass('animated owl-animated-out owl-animated-in') 23693 .removeClass(this.core.settings.animateIn) 23694 .removeClass(this.core.settings.animateOut); 23695 this.core.onTransitionEnd(); 23696 }; 23697 23698 /** 23699 * Destroys the plugin. 23700 * @public 23701 */ 23702 Animate.prototype.destroy = function() { 23703 var handler, property; 23704 23705 for (handler in this.handlers) { 23706 this.core.$element.off(handler, this.handlers[handler]); 23707 } 23708 for (property in Object.getOwnPropertyNames(this)) { 23709 typeof this[property] != 'function' && (this[property] = null); 23710 } 23711 }; 23712 23713 $.fn.owlCarousel.Constructor.Plugins.Animate = Animate; 23714 23715})(window.Zepto || window.jQuery, window, document); 23716 23717/** 23718 * Autoplay Plugin 23719 * @version 2.1.0 23720 * @author Bartosz Wojciechowski 23721 * @author Artus Kolanowski 23722 * @author David Deutsch 23723 * @license The MIT License (MIT) 23724 */ 23725;(function($, window, document, undefined) { 23726 23727 /** 23728 * Creates the autoplay plugin. 23729 * @class The Autoplay Plugin 23730 * @param {Owl} scope - The Owl Carousel 23731 */ 23732 var Autoplay = function(carousel) { 23733 /** 23734 * Reference to the core. 23735 * @protected 23736 * @type {Owl} 23737 */ 23738 this._core = carousel; 23739 23740 /** 23741 * The autoplay timeout. 23742 * @type {Timeout} 23743 */ 23744 this._timeout = null; 23745 23746 /** 23747 * Indicates whenever the autoplay is paused. 23748 * @type {Boolean} 23749 */ 23750 this._paused = false; 23751 23752 /** 23753 * All event handlers. 23754 * @protected 23755 * @type {Object} 23756 */ 23757 this._handlers = { 23758 'changed.owl.carousel': $.proxy(function(e) { 23759 if (e.namespace && e.property.name === 'settings') { 23760 if (this._core.settings.autoplay) { 23761 this.play(); 23762 } else { 23763 this.stop(); 23764 } 23765 } else if (e.namespace && e.property.name === 'position') { 23766 //console.log('play?', e); 23767 if (this._core.settings.autoplay) { 23768 this._setAutoPlayInterval(); 23769 } 23770 } 23771 }, this), 23772 'initialized.owl.carousel': $.proxy(function(e) { 23773 if (e.namespace && this._core.settings.autoplay) { 23774 this.play(); 23775 } 23776 }, this), 23777 'play.owl.autoplay': $.proxy(function(e, t, s) { 23778 if (e.namespace) { 23779 this.play(t, s); 23780 } 23781 }, this), 23782 'stop.owl.autoplay': $.proxy(function(e) { 23783 if (e.namespace) { 23784 this.stop(); 23785 } 23786 }, this), 23787 'mouseover.owl.autoplay': $.proxy(function() { 23788 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 23789 this.pause(); 23790 } 23791 }, this), 23792 'mouseleave.owl.autoplay': $.proxy(function() { 23793 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 23794 this.play(); 23795 } 23796 }, this), 23797 'touchstart.owl.core': $.proxy(function() { 23798 if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) { 23799 this.pause(); 23800 } 23801 }, this), 23802 'touchend.owl.core': $.proxy(function() { 23803 if (this._core.settings.autoplayHoverPause) { 23804 this.play(); 23805 } 23806 }, this) 23807 }; 23808 23809 // register event handlers 23810 this._core.$element.on(this._handlers); 23811 23812 // set default options 23813 this._core.options = $.extend({}, Autoplay.Defaults, this._core.options); 23814 }; 23815 23816 /** 23817 * Default options. 23818 * @public 23819 */ 23820 Autoplay.Defaults = { 23821 autoplay: false, 23822 autoplayTimeout: 5000, 23823 autoplayHoverPause: false, 23824 autoplaySpeed: false 23825 }; 23826 23827 /** 23828 * Starts the autoplay. 23829 * @public 23830 * @param {Number} [timeout] - The interval before the next animation starts. 23831 * @param {Number}
23831 [speed] - The animation speed for the animations. 23832 */ 23833 Autoplay.prototype.play = function(timeout, speed) { 23834 this._paused = false; 23835 23836 if (this._core.is('rotating')) { 23837 return; 23838 } 23839 23840 this._core.enter('rotating'); 23841 23842 this._setAutoPlayInterval(); 23843 }; 23844 23845 /** 23846 * Gets a new timeout 23847 * @private 23848 * @param {Number} [timeout] - The interval before the next animation starts. 23849 * @param {Number} [speed] - The animation speed for the animations. 23850 * @return {Timeout} 23851 */ 23852 Autoplay.prototype._getNextTimeout = function(timeout, speed) { 23853 if ( this._timeout ) { 23854 window.clearTimeout(this._timeout); 23855 } 23856 return window.setTimeout($.proxy(function() { 23857 if (this._paused || this._core.is('busy') || this._core.is('interacting') || document.hidden) { 23858 return; 23859 } 23860 this._core.next(speed || this._core.settings.autoplaySpeed); 23861 }, this), timeout || this._core.settings.autoplayTimeout); 23862 }; 23863 23864 /** 23865 * Sets autoplay in motion. 23866 * @private 23867 */ 23868 Autoplay.prototype._setAutoPlayInterval = function() { 23869 this._timeout = this._getNextTimeout(); 23870 }; 23871 23872 /** 23873 * Stops the autoplay. 23874 * @public 23875 */ 23876 Autoplay.prototype.stop = function() { 23877 if (!this._core.is('rotating')) { 23878 return; 23879 } 23880 23881 window.clearTimeout(this._timeout); 23882 this._core.leave('rotating'); 23883 }; 23884 23885 /** 23886 * Stops the autoplay. 23887 * @public 23888 */ 23889 Autoplay.prototype.pause = function() { 23890 if (!this._core.is('rotating')) { 23891 return; 23892 } 23893 23894 this._paused = true; 23895 }; 23896 23897 /** 23898 * Destroys the plugin. 23899 */ 23900 Autoplay.prototype.destroy = function() { 23901 var handler, property; 23902 23903 this.stop(); 23904 23905 for (handler in this._handlers) { 23906 this._core.$element.off(handler, this._handlers[handler]); 23907 } 23908 for (property in Object.getOwnPropertyNames(this)) { 23909 typeof this[property] != 'function' && (this[property] = null); 23910 } 23911 }; 23912 23913 $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay; 23914 23915})(window.Zepto || window.jQuery, window, document); 23916 23917/** 23918 * Navigation Plugin 23919 * @version 2.1.0 23920 * @author Artus Kolanowski 23921 * @author David Deutsch 23922 * @license The MIT License (MIT) 23923 */ 23924;(function($, window, document, undefined) { 23925 'use strict'; 23926 23927 /** 23928 * Creates the navigation plugin. 23929 * @class The Navigation Plugin 23930 * @param {Owl} carousel - The Owl Carousel. 23931 */ 23932 var Navigation = function(carousel) { 23933 /** 23934 * Reference to the core. 23935 * @protected 23936 * @type {Owl} 23937 */ 23938 this._core = carousel; 23939 23940 /** 23941 * Indicates whether the plugin is initialized or not. 23942 * @protected 23943 * @type {Boolean} 23944 */ 23945 this._initialized = false; 23946 23947 /** 23948 * The current paging indexes. 23949 * @protected 23950 * @type {Array} 23951 */ 23952 this._pages = []; 23953 23954 /** 23955 * All DOM elements of the user interface. 23956 * @protected 23957 * @type {Object} 23958 */ 23959 this._controls = {}; 23960 23961 /** 23962 * Markup for an indicator. 23963 * @protected 23964 * @type {Array.<String>} 23965 */ 23966 this._templates = []; 23967 23968 /** 23969 * The carousel element. 23970 * @type {jQuery} 23971 */ 23972 this.$element = this._core.$element; 23973 23974 /** 23975 * Overridden methods of the carousel. 23976 * @protected 23977 * @type {Object} 23978 */ 23979 this._overrides = { 23980 next: this._core.next, 23981 prev: this._core.prev, 23982 to: this._core.to 23983 }; 23984 23985 /** 23986 * All event handlers. 23987 * @protected 23988 * @type {Object} 23989 */ 23990 this._handlers = { 23991 'prepared.owl.carousel': $.proxy(function(e) { 23992 if (e.namespace && this._core.settings.dotsData) { 23993 this._templates.push('<div class="' + this._core.settings.dotClass + '">' + 23994 $(e.content).find('[data-dot]').addBack('[data-dot]').attr('data-dot') + '</div>'); 23995 } 23996 }, this), 23997 'added.owl.carousel': $.proxy(function(e) { 23998 if (e.namespace && this._core.settings.dotsData) { 23999 this._templates.splice(e.position, 0, this._templates.pop()); 24000 } 24001 }, this), 24002 'remove.owl.carousel': $.proxy(function(e) { 24003 if (e.namespace && this._core.settings.dotsData) { 24004 this._templates.splice(e.position, 1); 24005 } 24006 }, this), 24007 'changed.owl.carousel': $.proxy(function(e) { 24008 if (e.namespace && e.property.name == 'position') { 24009 this.draw(); 24010 } 24011 }, this), 24012 'initialized.owl.carousel': $.proxy(function(e) { 24013 if (e.namespace && !this._initialized) { 24014 this._core.trigger('initialize', null, 'navigation'); 24015 this.initialize(); 24016 this.update(); 24017 this.draw(); 24018 this._initialized = true; 24019 this._core.trigger('initialized', null, 'navigation'); 24020 } 24021 }, this), 24022 'refreshed.owl.carousel': $.proxy(function(e) { 24023 if (e.namespace && this._initialized) { 24024 this._core.trigger('refresh', null, 'navigation'); 24025 this.update(); 24026 this.draw(); 24027 this._core.trigger('refreshed', null, 'navigation'); 24028 } 24029 }, this) 24030 }; 24031 24032 // set default options 24033 this._core.options = $.extend({}, Navigation.Defaults, this._core.options); 24034 24035 // register event handlers 24036 this.$element.on(this._handlers); 24037 }; 24038 24039 /** 24040 * Default options. 24041 * @public 24042 * @todo Rename `slideBy` to `navBy` 24043 */ 24044 Navigation.Defaults = { 24045 nav: false, 24046 navText: [ 'prev', 'next' ], 24047 navSpeed: false, 24048 navElement: 'div', 24049 navContainer: false, 24050 navContainerClass: 'owl-nav', 24051 navClass: [ 'owl-prev', 'owl-next' ], 24052 slideBy: 1, 24053 dotClass: 'owl-dot', 24054 dotsClass: 'owl-dots', 24055 dots: true, 24056 dotsEach: false, 24057 dotsData: false, 24058 dotsSpeed: false, 24059 dotsContainer: false 24060 }; 24061 24062 /** 24063 * Initializes the layout of the plugin and extends the carousel. 24064 * @protected 24065 */ 24066 Navigation.prototype.initialize = function() { 24067 var override, 24068 settings = this._core.settings; 24069 24070 // create DOM structure for relative navigation 24071 this._controls.$relative = (settings.navContainer ? $(settings.navContainer) 24072 : $('<div>').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled'); 24073 24074 this._controls.$previous = $('<' + settings.navElement + '>') 24075 .addClass(settings.navClass[0])
vendor: 10,907 bytes, lines 24076-24476
24076 .html(settings.navText[0]) 24077 .prependTo(this._controls.$relative) 24078 .on('click', $.proxy(function(e) { 24079 this.prev(settings.navSpeed); 24080 }, this)); 24081 this._controls.$next = $('<' + settings.navElement + '>') 24082 .addClass(settings.navClass[1]) 24083 .html(settings.navText[1]) 24084 .appendTo(this._controls.$relative) 24085 .on('click', $.proxy(function(e) { 24086 this.next(settings.navSpeed); 24087 }, this)); 24088 24089 // create DOM structure for absolute navigation 24090 if (!settings.dotsData) { 24091 this._templates = [ $('<div>') 24092 .addClass(settings.dotClass) 24093 .append($('<span>')) 24094 .prop('outerHTML') ]; 24095 } 24096 24097 this._controls.$absolute = (settings.dotsContainer ? $(settings.dotsContainer) 24098 : $('<div>').addClass(settings.dotsClass).appendTo(this.$element)).addClass('disabled'); 24099 24100 this._controls.$absolute.on('click', 'div', $.proxy(function(e) { 24101 var index = $(e.target).parent().is(this._controls.$absolute) 24102 ? $(e.target).index() : $(e.target).parent().index(); 24103 24104 e.preventDefault(); 24105 24106 this.to(index, settings.dotsSpeed); 24107 }, this)); 24108 24109 // override public methods of the carousel 24110 for (override in this._overrides) { 24111 this._core[override] = $.proxy(this[override], this); 24112 } 24113 }; 24114 24115 /** 24116 * Destroys the plugin. 24117 * @protected 24118 */ 24119 Navigation.prototype.destroy = function() { 24120 var handler, control, property, override; 24121 24122 for (handler in this._handlers) { 24123 this.$element.off(handler, this._handlers[handler]); 24124 } 24125 for (control in this._controls) { 24126 this._controls[control].remove(); 24127 } 24128 for (override in this.overides) { 24129 this._core[override] = this._overrides[override]; 24130 } 24131 for (property in Object.getOwnPropertyNames(this)) { 24132 typeof this[property] != 'function' && (this[property] = null); 24133 } 24134 }; 24135 24136 /** 24137 * Updates the internal state. 24138 * @protected 24139 */ 24140 Navigation.prototype.update = function() { 24141 var i, j, k, 24142 lower = this._core.clones().length / 2, 24143 upper = lower + this._core.items().length, 24144 maximum = this._core.maximum(true), 24145 settings = this._core.settings, 24146 size = settings.center || settings.autoWidth || settings.dotsData 24147 ? 1 : settings.dotsEach || settings.items; 24148 24149 if (settings.slideBy !== 'page') { 24150 settings.slideBy = Math.min(settings.slideBy, settings.items); 24151 } 24152 24153 if (settings.dots || settings.slideBy == 'page') { 24154 this._pages = []; 24155 24156 for (i = lower, j = 0, k = 0; i < upper; i++) { 24157 if (j >= size || j === 0) { 24158 this._pages.push({ 24159 start: Math.min(maximum, i - lower), 24160 end: i - lower + size - 1 24161 }); 24162 if (Math.min(maximum, i - lower) === maximum) { 24163 break; 24164 } 24165 j = 0, ++k; 24166 } 24167 j += this._core.mergers(this._core.relative(i)); 24168 } 24169 } 24170 }; 24171 24172 /** 24173 * Draws the user interface. 24174 * @todo The option `dotsData` wont work. 24175 * @protected 24176 */ 24177 Navigation.prototype.draw = function() { 24178 var difference, 24179 settings = this._core.settings, 24180 disabled = this._core.items().length <= settings.items, 24181 index = this._core.relative(this._core.current()), 24182 loop = settings.loop || settings.rewind; 24183 24184 this._controls.$relative.toggleClass('disabled', !settings.nav || disabled); 24185 24186 if (settings.nav) { 24187 this._controls.$previous.toggleClass('disabled', !loop && index <= this._core.minimum(true)); 24188 this._controls.$next.toggleClass('disabled', !loop && index >= this._core.maximum(true)); 24189 } 24190 24191 this._controls.$absolute.toggleClass('disabled', !settings.dots || disabled); 24192 24193 if (settings.dots) { 24194 difference = this._pages.length - this._controls.$absolute.children().length; 24195 24196 if (settings.dotsData && difference !== 0) { 24197 this._controls.$absolute.html(this._templates.join('')); 24198 } else if (difference > 0) { 24199 this._controls.$absolute.append(new Array(difference + 1).join(this._templates[0])); 24200 } else if (difference < 0) { 24201 this._controls.$absolute.children().slice(difference).remove(); 24202 } 24203 24204 this._controls.$absolute.find('.active').removeClass('active'); 24205 this._controls.$absolute.children().eq($.inArray(this.current(), this._pages)).addClass('active'); 24206 } 24207 }; 24208 24209 /** 24210 * Extends event data. 24211 * @protected 24212 * @param {Event} event - The event object which gets thrown. 24213 */ 24214 Navigation.prototype.onTrigger = function(event) { 24215 var settings = this._core.settings; 24216 24217 event.page = { 24218 index: $.inArray(this.current(), this._pages), 24219 count: this._pages.length, 24220 size: settings && (settings.center || settings.autoWidth || settings.dotsData 24221 ? 1 : settings.dotsEach || settings.items) 24222 }; 24223 }; 24224 24225 /** 24226 * Gets the current page position of the carousel. 24227 * @protected 24228 * @returns {Number} 24229 */ 24230 Navigation.prototype.current = function() { 24231 var current = this._core.relative(this._core.current()); 24232 return $.grep(this._pages, $.proxy(function(page, index) { 24233 return page.start <= current && page.end >= current; 24234 }, this)).pop(); 24235 }; 24236 24237 /** 24238 * Gets the current succesor/predecessor position. 24239 * @protected 24240 * @returns {Number} 24241 */ 24242 Navigation.prototype.getPosition = function(successor) { 24243 var position, length, 24244 settings = this._core.settings; 24245 24246 if (settings.slideBy == 'page') { 24247 position = $.inArray(this.current(), this._pages); 24248 length = this._pages.length; 24249 successor ? ++position : --position; 24250 position = this._pages[((position % length) + length) % length].start; 24251 } else { 24252 position = this._core.relative(this._core.current()); 24253 length = this._core.items().length; 24254 successor ? position += settings.slideBy : position -= settings.slideBy; 24255 } 24256 24257 return position; 24258 }; 24259 24260 /** 24261 * Slides to the next item or page. 24262 * @public 24263 * @param {Number} [speed=false] - The time in milliseconds for the transition. 24264 */ 24265 Navigation.prototype.next = function(speed) { 24266 $.proxy(this._overrides.to, this._core)(this.getPosition(true), speed); 24267 }; 24268 24269 /** 24270 * Slides to the previous item or page. 24271 * @public 24272 * @param {Number} [speed=false] - The time in milliseconds for the transition. 24273 */ 24274 Navigation.prototype.prev = function(speed) { 24275 $.proxy(this._overrides.to, this._core)(this.getPosition(false), speed); 24276 }; 24277 24278 /** 24279 * Slides to the specified item or page. 24280 * @public 24281 * @param {Number} position - The position of the item or page. 24282 * @param {Number} [speed] - The time in milliseconds for the transition. 24283 * @param {Boolean} [standard=false] - Whether to use the standard behaviour or not. 24284 */ 24285 Navigation.prototype.to = function(position, speed, standard) { 24286 var length; 24287 24288 if (!standard && this._pages.length) { 24289 length = this._pages.length; 24290 $.proxy(this._overrides.to, this._core)(this._pages[((position % length) + length) % length].start, speed); 24291 } else { 24292 $.proxy(this._overrides.to, this._core)(position, speed); 24293 } 24294 }; 24295 24296 $.fn.owlCarousel.Constructor.Plugins.Navigation = Navigation; 24297 24298})(window.Zepto || window.jQuery, window, document); 24299 24300/** 24301 * Hash Plugin 24302 * @version 2.1.0 24303 * @author Artus Kolanowski 24304 * @author David Deutsch 24305 * @license The MIT License (MIT) 24306 */ 24307;(function($, window, document, undefined) { 24308 'use strict'; 24309 24310 /** 24311 * Creates the hash plugin. 24312 * @class The Hash Plugin 24313 * @param {Owl} carousel - The Owl Carousel 24314 */ 24315 var Hash = function(carousel) { 24316 /** 24317 * Reference to the core. 24318 * @protected 24319 * @type {Owl} 24320 */ 24321 this._core = carousel; 24322 24323 /** 24324 * Hash index for the items. 24325 * @protected 24326 * @type {Object} 24327 */ 24328 this._hashes = {}; 24329 24330 /** 24331 * The carousel element. 24332 * @type {jQuery} 24333 */ 24334 this.$element = this._core.$element; 24335 24336 /** 24337 * All event handlers. 24338 * @protected 24339 * @type {Object} 24340 */ 24341 this._handlers = { 24342 'initialized.owl.carousel': $.proxy(function(e) { 24343 if (e.namespace && this._core.settings.startPosition === 'URLHash') { 24344 $(window).trigger('hashchange.owl.navigation'); 24345 } 24346 }, this), 24347 'prepared.owl.carousel': $.proxy(function(e) { 24348 if (e.namespace) { 24349 var hash = $(e.content).find('[data-hash]').addBack('[data-hash]').attr('data-hash'); 24350 24351 if (!hash) { 24352 return; 24353 } 24354 24355 this._hashes[hash] = e.content; 24356 } 24357 }, this), 24358 'changed.owl.carousel': $.proxy(function(e) { 24359 if (e.namespace && e.property.name === 'position') { 24360 var current = this._core.items(this._core.relative(this._core.current())), 24361 hash = $.map(this._hashes, function(item, hash) { 24362 return item === current ? hash : null; 24363 }).join(); 24364 24365 if (!hash || window.location.hash.slice(1) === hash) { 24366 return; 24367 } 24368 24369 window.location.hash = hash; 24370 } 24371 }, this) 24372 }; 24373 24374 // set default options 24375 this._core.options = $.extend({}, Hash.Defaults, this._core.options); 24376 24377 // register the event handlers 24378 this.$element.on(this._handlers); 24379 24380 // register event listener for hash navigation 24381 $(window).on('hashchange.owl.navigation', $.proxy(function(e) { 24382 var hash = window.location.hash.substring(1), 24383 items = this._core.$stage.children(), 24384 position = this._hashes[hash] && items.index(this._hashes[hash]); 24385 24386 if (position === undefined || position === this._core.current()) { 24387 return; 24388 } 24389 24390 this._core.to(this._core.relative(position), false, true); 24391 }, this)); 24392 }; 24393 24394 /** 24395 * Default options. 24396 * @public 24397 */ 24398 Hash.Defaults = { 24399 URLhashListener: false 24400 }; 24401 24402 /** 24403 * Destroys the plugin. 24404 * @public 24405 */ 24406 Hash.prototype.destroy = function() { 24407 var handler, property; 24408 24409 $(window).off('hashchange.owl.navigation'); 24410 24411 for (handler in this._handlers) { 24412 this._core.$element.off(handler, this._handlers[handler]); 24413 } 24414 for (property in Object.getOwnPropertyNames(this)) { 24415 typeof this[property] != 'function' && (this[property] = null); 24416 } 24417 }; 24418 24419 $.fn.owlCarousel.Constructor.Plugins.Hash = Hash; 24420 24421})(window.Zepto || window.jQuery, window, document); 24422 24423/** 24424 * Support Plugin 24425 * 24426 * @version 2.1.0 24427 * @author Vivid Planet Software GmbH 24428 * @author Artus Kolanowski 24429 * @author David Deutsch 24430 * @license The MIT License (MIT) 24431 */ 24432;(function($, window, document, undefined) { 24433 24434 var style = $('<support>').get(0).style, 24435 prefixes = 'Webkit Moz O ms'.split(' '), 24436 events = { 24437 transition: { 24438 end: { 24439 WebkitTransition: 'webkitTransitionEnd', 24440 MozTransition: 'transitionend', 24441 OTransition: 'oTransitionEnd', 24442 transition: 'transitionend' 24443 } 24444 }, 24445 animation: { 24446 end: { 24447 WebkitAnimation: 'webkitAnimationEnd', 24448 MozAnimation: 'animationend', 24449 OAnimation: 'oAnimationEnd', 24450 animation: 'animationend' 24451 } 24452 } 24453 }, 24454 tests = { 24455 csstransforms: function() { 24456 return !!test('transform'); 24457 }, 24458 csstransforms3d: function() { 24459 return !!test('perspective'); 24460 }, 24461 csstransitions: function() { 24462 return !!test('transition'); 24463 }, 24464 cssanimations: function() { 24465 return !!test('animation'); 24466 } 24467 }; 24468 24469 function test(property, prefixed) { 24470 var result = false, 24471 upper = property.charAt(0).toUpperCase() + property.slice(1); 24472 24473 $.each((property + ' ' + prefixes.join(upper + ' ') + upper).split(' '), function(i, property) { 24474 if (style[property] !== undefined) { 24475 result = prefixed ? property : true; 24476 return false;
24477 } 24478 }); 24479 24480 return result; 24481 } 24482 24483 function prefixed(property) { 24484 return test(property, true); 24485 } 24486 24487 if (tests.csstransitions()) { 24488 /* jshint -W053 */ 24489 $.support.transition = new String(prefixed('transition')) 24490 $.support.transition.end = events.transition.end[ $.support.transition ]; 24491 } 24492 24493 if (tests.cssanimations()) { 24494 /* jshint -W053 */ 24495 $.support.animation = new String(prefixed('animation')) 24496 $.support.animation.end = events.animation.end[ $.support.animation ]; 24497 } 24498 24499 if (tests.csstransforms()) { 24500 /* jshint -W053 */ 24501 $.support.transform = new String(prefixed('transform')); 24502 $.support.transform3d = tests.csstransforms3d(); 24503 } 24504 24505})(window.Zepto || window.jQuery, window, document); 24506 24507//Use this class for front-end JS needed to create Richtext based on styles or formatting applied in the RTE. 24508(function($){ 24509 24510 "use strict"; 24511 24512 ns('News.App').RichText = { 24513 24514 load: function() { 24515 24516 //Clone <span class=pullquote> into a pulleDquote 24517 News.App.RichText.createPulledQuote(); 24518 //edit <span class=blockquote> into a blockedquote 24519 News.App.RichText.editBlockedQuote(); 24520 // News.App.RichText.editKeypointBlock(); 24521 24522 }, 24523 createPulledQuote: function() { 24524 $('span.pullquote').each(function() { 24525 var $parentParagraph = $(this).closest('p'); 24526 $parentParagraph.css('position', 'relative'); 24527 $(this).clone().addClass('pulledquote').prependTo($parentParagraph); 24528 }); 24529 }, 24530 editBlockedQuote: function() { 24531 $('span.blockquote').each(function() { 24532 $('<blockquote>' + $(this).html() + '</blockquote>').insertAfter($(this)); 24533 $(this).remove(); 24534 }); 24535 }, 24536 24537 // editKeypointBlock: function () { 24538 // $('span.hrule').each(function() { 24539 // $('<hr class="'+ $(this).attr('class') +'" />').insertAfter($(this)); 24540 // $(this).remove(); 24541 // }); 24542 // $('span.keypointtitle').each(function() { 24543 // $('<div class="'+ $(this).attr('class') +'" >'+ $(this).html() + '</div>').insertAfter($(this)); 24544 // $(this).remove(); 24545 // }); 24546 // } 24547 }; 24548 24549 News.App.RichText.load(); 24550 24551})(jQuery); 24552 24553/* Live Edit functionality */ 24554function isAuthorMode() { 24555 if (typeof CQ != "undefined") { 24556 if (CQ && CQ.WCM && CQ.WCM.isEditMode) { 24557 return CQ.WCM.isEditMode('True') 24558 } 24559 } 24560} 24561 24562 24563 24564// Browser Close Event 24565if (isAuthorMode()) { 24566 let TRACK_OPEN_COMPONENT; 24567 24568 window.addEventListener("load", () => { 24569 let dialogs = ns('News.dialogs') 24570 editButton = $('.cq-editbar .x-btn-text'); 24571 24572 // Checking the live edit event triggering while clicking on each component */ 24573 editButton.on('click',function(){ 24574 24575 let componentListener = { 24576 pageUrl: window.CQURLInfo.requestPath, 24577 pageUserId: window.CQ.User.getCurrentUser().getUserID(), 24578 userName: window.CQ.User.getCurrentUser().data.userName, 24579 componentPath:'' 24580 } 24581 24582 let liveEventFn = { 24583 24584 // Sending the event listener to cq:listener 24585 liveInit: function(comp) { 24586 let postRequestData = { 24587 pageUrl: componentListener.pageUrl, 24588 pageUserId: componentListener.pageUserId, 24589 userName: componentListener.userName, 24590 componentPath: comp.path, 24591 releaseFlag: true, 24592 liveusers:[] 24593 } 24594 componentListener.componentPath = comp.path; 24595 var isLockedCheck, 24596 idWrapper; 24597 24598 // Sending the POST request to java model and saved the values into JCR 24599 function postReq(flagVal){ 24600 $.ajax({ 24601 type: "POST", 24602 url: "/services/news/liveDetails?path="+postRequestData.componentPath+"&userId="+postRequestData.pageUserId+"&isLocked="+flagV
24602al+"&firstName="+postRequestData.userName, 24603 dataType: "html", 24604 contentType:"html/plain; charset=utf-8", 24605 success: function(data, textStatus, xhr) { 24606 if(xhr.status == 200){ 24607 liveEditFn(); 24608 } 24609 } 24610 }); 24611 } 24612 postReq(true); 24613 24614 function liveEditFn(){ 24615 24616 // Fetching the liveData values from the JCR properties and manipulate the functionalities. 24617 $.ajax({ 24618 url: "/services/news/liveDetails?path="+postRequestData.componentPath, 24619 type: 'GET', 24620 dataType: 'json', 24621 success: function(res) { 24622 if(res !== null){ 24623 postRequestData.liveusers = [];
24624 res.userId.forEach(function(value){ 24625 if(( value.userId !== postRequestData.pageUserId) && value.isLocked == true && postRequestData.componentPath == res.path ){ 24626 postRequestData.liveusers.push("<li>"+value.firstName+"</li>"); 24627 isLockedCheck = true; 24628 } 24629 $('.live-editing-wrapper li').innerHTML += value.userId; 24630 return true; 24631 }) 24632 } 24633 24634 // Assign the dialog markups. 24635 let dialogHTML = ` 24636 <div class="live-editing-container"> 24637 <div class="live-editing-wrapper"> 24638 <h3>Another user is currently editing this component. Do you want to proceed?</h3> 24639 <ul>`+postRequestData.liveusers+`</ul> 24640 <div class="btn-wrapper"> 24641 <button class="liveedit-yes">Yes</button> 24642 <button class="liveedit-no">No</button> 24643 </div> 24644 </div> 24645 </div> 24646 ` 24647 // Executed a single function for dialogue visiblity. 24648 function containerVisiblity(_wrapperId,displayItem){ 24649 if(_wrapperId.querySelector('.live-editing-container') !== null){ 24650 _wrapperId.querySelector('.live-editing-container').style.display = displayItem; 24651 } 24652 } 24653 24654 setTimeout(()=>{ 24655 let getComID = comp.bwrap.id; 24656 idWrapper = document.querySelector('#'+getComID).closest('.x-window-bwrap'); 24657 },10); 24658 24659 24660 // Dialogue close button execution 24661 $('.x-window .x-tool-close').off('click'); 24662 $('.x-window .x-tool-close').on('click',()=>{ 24663 isLockedCheck == false; 24664 $('.live-editing-container').remove(); 24665 postReq(false); 24666 }); 24667 24668 24669 // Dialogue cancel button execution 24670 $('.x-panel-fbar .cq-btn-cancel .x-btn-text').off('click'); 24671 $('.x-panel-fbar .cq-btn-cancel .x-btn-text').on('click',()=>{ 24672 isLockedCheck == false; 24673 $('.live-editing-container').remove(); 24674 postReq(false); 24675 }); 24676 24677 // Dialogue ok button execution 24678 $(".x-window .cq-btn-ok").off('click'); 24679 $(".x-window .cq-btn-ok").on('click',()=>{ 24680 setTimeout(function(){ 24681 if($('.ext-mb-content').length < 1){ 24682 $.ajax({ 24683 type: "POST", 24684 url: "/services/news/liveDetails?path="+postRequestData.componentPath+"&userId="+postRequestData.pageUserId+"&isLocked=false&firstName="+postRequestData.userName, 24685 dataType: "html", 24686 contentType:"html/plain; charset=utf-8", 24687 success: function(res) {} 24688 }); 24689 } 24690 },1000); 24691 }); 24692 24693 // Dialogue Proceed Button execution 24694 function proceedBtn(){ 24695 24696 $( document ).delegate( ".liveedit-yes", "click", function() { 24697 $('.live-editing-container').remove(); 24698 containerVisiblity(idWrapper,"none"); 24699 }) 24700 }; 24701 24702 // Dialogue Not-Proceed Button execution 24703 function notProceedBtn(){
24704 $(document).off("click", ".liveedit-no"); 24705 $(document).on("click", ".liveedit-no", function() { 24706 $('.live-editing-container').remove(); 24707 idWrapper.closest('.x-window').querySelector('.cq-btn-cancel').click(); 24708 postReq(false); 24709 }) 24710 } 24711 24712 // Checking the live edit condition and appending the dialogue scenarios. 24713 setTimeout(()=>{ 24714 proceedBtn(); 24715 notProceedBtn(); 24716 if(isLockedCheck == true){ 24717 let shadow = document.querySelector('.x-shadow'); 24718 if(shadow != undefined || shadow != null){shadow.style.display = 'none'} 24719 $(idWrapper).append(dialogHTML); 24720 }else{ 24721 containerVisiblity(idWrapper,"block"); 24722 $('.live-editing-container').remove(); 24723 } 24724 },500); 24725 }, 24726 }); 24727 }; 24728 } 24729 } 24730 24731 // Invoke the entire functionality 24732 dialogs.liveEditEvent = { 24733 liveInit: liveEventFn.liveInit, 24734 } 24735 24736 return TRACK_OPEN_COMPONENT = componentListener; 24737 }) 24738 }); 24739 24740 $(window).bind('beforeunload', ()=> { 24741 24742 if(TRACK_OPEN_COMPONENT && TRACK_OPEN_COMPONENT.componentPath !== ""){ 24743 $.ajax({ 24744 type: "POST", 24745 url: "/services/news/liveDetails?path="+TRACK_OPEN_COMPONENT.componentPath+"&userId="+TRACK_OPEN_COMPONENT.pageUserId+"&isLocked=false&firstName="+TRACK_OPEN_COMPONENT.userName, 24746 dataType: "html", 24747 contentType:"html/plain; charset=utf-8" 24748 }); 24749 } 24750 // To handle browsers alert messages. 24751 let checkBrowserCloseAlert = 0; 24752 let interval = setInterval(function(){ 24753 checkBrowserCloseAlert += 1; 24754 if(checkBrowserCloseAlert === 3){ 24755 if(TRACK_OPEN_COMPONENT.componentPath !== ""){ 24756 $.ajax({ 24757 type: "POST", 24758 url: "/services/news/liveDetails?path="+TRACK_OPEN_COMPONENT.componentPath+"&userId="+TRACK_OPEN_COMPONENT.pageUserId+"&isLocked=true&firstName="+TRACK_OPEN_COMPONENT.userName, 24759 dataType: "html", 24760 contentType:"html/plain; charset=utf-8" 24761 }); 24762 } 24763 clearInterval(interval); 24764 } 24765 }, 1500); 24766 // fallback solution for firefox. 24767 let browser = navigator.userAgent; 24768 if(browser.includes('Firefox') == true){ 24769 console.log('For Firefox'); 24770 } 24771 }); 24772} 24773 24774 24775try { 24776 _.templateSettings = { 24777 interpolate: /\<\@\=(.+?)\@\>/gim, 24778 evaluate: /\<\@(.+?)\@\>/gim 24779 }; 24780} catch (e) {} 24781+function($) { 24782 News.core = News.core || { 24783 URL: function(urlData) { 24784 if (!News.core.URL.reg) { 24785 // Creating the regex object as a static object (Allows for it to only need to be 'compiled' once) 24786 // Regex splits the hostname from the pathname 24787 News.core.URL.reg = new RegExp(/(http(s)?:\/\/[^\/]+)?(\/.+)/); 24788 } 24789 var matches = News.core.URL.reg.exec(urlData); 24790 // 4 is the expected matcher length (0 for 'all,' 1 for hostname, 2 for 's' match, and 3 for pathname) 24791 // If it doesn't match that, then the region good is bad/corrupted/etc 24792 if (matches !== null && matches.length == 4) { 24793 // Doing checks to make sure we don't return any undefined variables, 24794 // else we could end up with "undefined/content/news/ny/buffalo" as a URL we try to redirect to 24795 this.hostname = matches[1] !== undefined ? matches[1] : ''; 24796 this.pathname = matches[3] !== undefined ? matches[3] : ''; 24797 } else { 24798 this.hostname = ''; 24799 this.pathname = ''; 24800 } 24801 }, 24802 getRavenid: function() { 24803 var ravenid = $('.region-data').first().data('ravenid') || $('body').data('ravenid'); 24804 return ravenid 24805 }, 24806 getTimestamp: function() { 24807 var date = new Date(); 24808 var offset = $('body').data('timezone-offset'); 24809 // Making sure we don't hit an exception with an undefined value 24810 if (!isNaN(offset)) { 24811 // offset is a negative number, so addition is required 24812 date.setUTCMilliseconds(date.getUTCMilliseconds() + offset); 24813 }
24814 var month = date.getUTCMonth() + 1; 24815 var day = date.getUTCDate(); 24816 var year = date.getUTCFullYear(); 24817 return year + "/" + month + "/" + day; 24818 } 24819 }; 24820 News.adBlocker = News.adBlocker || { 24821 isAdBlockEnabled: function() { 24822 return typeof window.isAdBlockerEnabled === 'undefined'; 24823 } 24824 }; 24825}(jQuery); 24826+function ($) { 24827 24828 function Megamenu(element, options) { 24829 this.$element = $(element); 24830 this.options = $.extend({}, Megamenu.DEFAULTS, options); 24831 this.$trigger = $('[data-toggle="megamenu"][href="#' + element.id + '"],' + 24832 '[data-toggle="megamenu"][data-target="#' + element.id + '"]'); 24833 24834 this.addAriaAndCollapsedClass(this.$element, this.$trigger); 24835 } 24836 24837 Megamenu.OPEN_DURATION = 350; 24838 24839 Megamenu.DEFAULTS = { }; 24840 24841 Megamenu.prototype.show = function () { 24842 var startEvent = $.Event('show.news.megamenu'); 24843 this.$element.trigger(startEvent); 24844 if (startEvent.isDefaultPrevented()) return; 24845 24846 // Hide other megamenus before showing this one 24847 var megamenuContainerIds = _($('[data-toggle="megamenu"]')) 24848 .map(_.unary(_.partialRight( 24849 $.attr, 'data-target' 24850 ))) 24851 .join(',') 24852 24853 _($(megamenuContainerIds).not(this.$element)).each(function(container) { 24854 Plugin.call($(container), 'hide'); 24855 }); 24856 24857 // Show element and set up event handling 24858 this.$element 24859 .removeClass('collapse') 24860 .addClass('collapse in') 24861 .attr('aria-expanded', true) 24862 .trigger('shown.news.megamenu'); 24863 24864 this.$trigger 24865 .removeClass('collapsed') 24866 .attr('aria-expanded', true); 24867 24868 function keepOpen() { 24869 this.closeTimeout && clearTimeout(this.closeTimeout); 24870 } 24871 24872 var keepOpenHandler = $.proxy(keepOpen, this); 24873 24874 var closeHandler = $.proxy(function setCloseTimeout() { 24875 keepOpen.call(this); 24876 this.closeTimeout = setTimeout(this.hide.bind(this), Megamenu.OPEN_DURATION); 24877 }, this); 24878 24879 this.$trigger 24880 .on('mouseout.news.megamenu.data-api', closeHandler) 24881 .on('mouseover.news.megamenu.data-api', keepOpenHandler); 24882 24883 this.$element 24884 .on('mouseout.news.megamenu.data-api', closeHandler) 24885 .on('mouseover.news.megamenu.data-api', keepOpenHandler); 24886 24887 this.$element.trigger('shown.news.megamenu'); 24888 } 24889 24890 Megamenu.prototype.hide = function() { 24891 this.$element 24892 .removeClass('collapse in') 24893 .addClass('collapse') 24894 .attr('aria-expanded', false) 24895 .trigger('hidden.news.megamenu'); 24896 24897 this.$trigger 24898 .addClass('collapsed') 24899 .attr('aria-expanded', false); 24900 24901 clearTimeout(this.closeTimeout); 24902 24903 this.$element.off('.news.megamenu'); 24904 this.$trigger.off('.news.megamenu'); 24905 } 24906 24907 Megamenu.prototype.toggle = function() { 24908 var isOpen = this.$element.hasClass('in'); 24909 this[isOpen ? 'hide' : 'show'](); 24910 } 24911 24912 Megamenu.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { 24913 var isOpen = $element.hasClass('in'); 24914 24915 $element.attr('aria-expanded', isOpen); 24916 $trigger 24917 .addClass('collapsed', !isOpen) 24918 .attr('aria-expanded', isOpen); 24919 } 24920 24921 function getTargetFromTrigger($trigger) { 24922 var href 24923 var target = $trigger.attr('data-target') 24924 || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 24925 24926 return $(target) 24927 } 24928 24929 function Plugin(option) { 24930 return this.each(function () { 24931 var $this = $(this); 24932 var data = $this.data('news.megamenu'); 24933 if (!data) $this.data('news.megamenu', (data = new Megamenu(this))); 24934 data[option](); 24935 }) 24936 } 24937 24938 var old = $.fn.megamenu 24939 24940 $.fn.megamenu = Plugin 24941 $.fn.megamenu.Constructor = Megamenu 24942 24943 24944 // MEGAMENU NO CONFLICT 24945 // ==================== 24946 24947 $.fn.megamenu.noConflict = function () { 24948 $.fn.megamenu = old 24949 return this 24950 } 24951 24952 $(document).on('click.news.megamenu.data-api', '[data-toggle="megamenu"]', function(e) { 24953 var $this = $(this) 24954 24955 if($this.attr('href')==='#') e.preventDefault(); 24956 24957 var $target = getTargetFromTrigger($this); 24958 Plugin.call($target, 'toggle'); 24959 }) 24960 24961 $(document).on('mouseenter.news.megamenu.data-api', '[data-toggle="megamenu"]', function (e) { 24962 var $this = $(this) 24963 24964 if($this.attr('href')==='#') e.preventDefault(); 24965 24966 if(isMobile.any) { 24967 e.preventDefault(); 24968 return; 24969 } 24970 24971 var $target = getTargetFromTrigger($this); 24972 Plugin.call($target, 'show'); 24973 }) 24974}(jQuery); 24975 24976$(function () { 24977 News.region = News.region || { 24978 24979 ravenApi : $('.redirect').data('ravenapi'), 24980 regionPath:null, 24981 regionName:null, 24982 24983
24984 setCookie: function (name, value) { 24985 Cookies.set(name, value, {expires: 365, path: '/'}); 24986 }, 24987 cookieFactory: function (path) { 24988 // Getting just the path and prepending /content/news if needed 24989 // ('Private' function) 24990 var getPathname = function (url) { 24991 var pathname = url.pathname; 24992 pathname = pathname.replace('/content/news',''); 24993 // regular expression to remove the article path and just take the region path 24994 var path = pathname.match('/([^/]+)(?:/([^/]+))?') 24995 if(path){ 24996 pathname = path[0] 24997 } 24998 // Only adding /content/news if it's not already there 24999 if (pathname.indexOf('/content/news') == -1) { 25000 pathname = '/content/news' + pathname; 25001 } 25002 return pathname 25003 }; 25004 path = path.replace(/.html\b/, ''); 25005 var url = new News.core.URL(path); 25006 var pathname = getPathname(url); 25007 var newCookieVal = url.hostname + pathname; 25008 return newCookieVal; 25009 }, 25010 getRegionCookieVal: function () { 25011 return new Promise( async resolve => { 25012 var locationCookie = Cookies.get('region'), 25013 languageCode; 25014 if (typeof locationCookie === 'string') { 25015 if(locationCookie === "/content/news/us/nacional"){ 25016 locationCookie = "/content/news/us/noticias"; 25017 News.region.setCookie('region', locationCookie); 25018 } 25019 25020 if(locationCookie === "/content/news/us/national"){ 25021 locationCookie = "/content/news/us/snplus"; 25022 News.region.setCookie('region', locationCookie); 25023 } 25024 regionPath = locationCookie 25025 } else { 25026 languageCode = News.region.getLanguageCode(); 25027 regionPath = await News.region.getRegionPath(languageCode,News.region.ravenApi); 25028 25029 if (regionPath) { 25030 localStorage.setItem('displayIPRegionalizationModal', 'true'); 25031 } 25032 } 25033 25034 resolve(regionPath === null ? false : regionPath) 25035 }) 25036 }, 25037 getLanguageCode: function(){ 25038 if(window.location.host.includes('spectrumnoticias.com') || window.location.host.includes('spectrumnoticias1.com')){ 25039 return 'es'; 25040 }else{ 25041 if(navigator.language.startsWith('es')){ 25042 return 'es' 25043 }else { 25044 return 'en' 25045 } 25046 } 25047 }, 25048 25049 isRegionalized: function () { 25050 // If the current page has a navigation on it, then it was able to be regionalized 25051 return $('nav').length > 0; 25052 }, 25053 // To regionalize articles that don't have region information, this method looks at cookies and canonical links. 25054 getPreferredRegionalization: async function () { 25055 var href = window.location.href; 25056 25057 // When we are not regionalized, find a regionalized URL. 25058 if (!News.region.isRegionalized()) { 25059 25060 var cookieRegion = await News.region.cookieRegionPath(); 25061 25062 // If the user has a region cookie, we will use it 25063 25064 if (cookieRegion) { 25065 // Look for the cookieregion in the path already 25066 var cookieIdx = window.location.pathname.indexOf(cookieRegion) 25067 // If href does not already start with the cookie region, then rebuild the URL with the cookie region and the normalized path. 25068 25069 if (cookieIdx < 0) { 25070 var pathname = News.region.normalizeArticlePath(window.location.pathname); 25071 href = window.location.protocol + '//' + window.location.host + cookieRegion + pathname; 25072 } 25073 } 25074 // Else use the current page canonical link directly 25075 else { 25076 href = document.querySelector("link[rel='canonical']").getAttribute("href"); 25077 } 25078 } 25079 return href; 25080 }, 25081 // Function to obtain a region from the user's region cookie 25082 cookieRegionPath: function () { 25083 return new Promise( async resolve => { 25084 let cookieRegion = await News.region.getRegionCookieVal(); 25085 25086 // If the user has a region cookie, we will use it 25087 if (cookieRegion) { 25088 25089 // Locate the start of the content news path 25090 var regionIdx = cookieRegion.indexOf('/content/news'); 25091 25092 // Use the cookie region as the region, after trimming the beginning 25093 25094 if (regionIdx == 0) { 25095 cookieRegion = cookieRegion.substring('/content/news'.length); 25096 } 25097 } 25098 resolve(cookieRegion); 25099 }) 25100 }, 25101 // To obtain the minimum length article path from an article path 25102 // Article Path input may or may not be regionalized. Output is unregionalized. 25103 // e.g. /nyc/all-boroughs/news/2017/12/11/test 25104 // e.g. /news/2017/12/11/myArticle 25105 // e.g. /nyc/dne/crime/2018/02/28/balloon-heist 25106 normalizeArticlePath: function (path) { 25107 25108 var re = /(\/[^\/]+)+(\/\d{4}\/\d{1,2}\/\d{1,2}){1}\/(\S([^\.]+)*)/ 25109 var matches = path.match(re) 25110 if (matches && matches.length > 3) { 25111 return matches[1] + matches[2] + "/" + matches[3] 25112 } else { 25113 return path 25114 } 25115 }, 25116 25117 // Highlight all service area states 25118 highlightServiceAreas: function () { 25119 jQuery('div .state').each(function () { 25120 var stateId = this.getAttribute('data-state-id'); 25121 $('#' + stateId).attr('class', 'state__icon-highlighted'); 25122 }); 25123 }, 25124 25125 //When list is selected, highlight that state and remove all other highlighting 25126 highlightSelectedState: function (stateId) { 25127 // Remove all selections 25128 $('svg .state__icon-selected').removeClass('state__icon-selected').addClass('state__icon-highlighted'); 25129 // Highlight the selected one 25130 var $state = document.getElementById(stateId); 25131 if ($state) { 25132 $($state).removeClass('state__icon-highlighted').addClass('state__icon-selected'); 25133 } 25134 }, 25135 25136 getRegionPath: function (languageCode,ravenApi) { 25137 return new Promise(async (resolve) => { 25138 let regionAPIPath; 25139 regionAPIPath = ravenApi +'/v1/regionalization/paths?lang='+ languageCode;
25140 25141 $.ajax({ 25142 type: 'GET', 25143 url: regionAPIPath, 25144 contentType: "application/json", 25145 success: function (data) { 25146 let paths = data.paths; 25147 let enLevel,enPath; 25148 if(languageCode === "es"){ 25149 $.each(paths, function (i, e) { 25150 if(e.language === "en" && e.consumer === "web"){ 25151 enLevel = e.level; 25152 if(e.path === "/us/national"){ 25153 e.path = "/us/snplus"; 25154 } 25155 enPath = e.path; 25156 } 25157 }) 25158 } 25159 25160 $.each(paths, function (i, e) { 25161 25162 if(languageCode === "en"){ 25163 News.region.setCookie("ipSourceSelectionModalDefaultLang", 'en'); // save language and use it for rendring the ip-reg 2nd modal 25164 if (e.language === "en" && e.consumer === "web") { 25165 News.region.regionName = e.ravenDisplayName; 25166 if(e.path === "/us/national"){ 25167 e.path = "/us/snplus"; 25168 } 25169 News.region.regionPath = e.path; 25170 } 25171 if(e.language === "sp" && e.consumer === "web"){ 25172 let redirectCookiePath = null; 25173 News.region.setCookie('redirectRegionName', e.ravenDisplayName) 25174 if(e.path){ 25175 if(e.path === "/us/nacional"){ 25176 e.path = "/us/noticias"; 25177 } 25178 redirectCookiePath = News.region.cookieFactory(e.path) 25179 } 25180 News.region.setCookie("redirectRegionPath", redirectCookiePath) 25181 // consider sp web path and save it in redirectCookie and use this cookie while calling 'services/api/region/onboarding?pagePath=/' 25182 } 25183 } 25184 if(languageCode === "es"){ 25185 News.region.setCookie("ipSourceSelectionModalDefaultLang", 'es'); 25186 25187 if (e.language === "sp" && e.consumer === "web") { 25188 if(e.level === "NATIONAL" && enLevel !== "NATIONAL" && !(window.location.host.includes('spectrumnoticias.com'))){ 25189 News.region.regionName = e.ravenDisplayName; 25190 News.region.regionPath = enPath; 25191 News.region.setCookie("ipSourceSelectionModalDefaultLang", 'en'); 25192 let redirectCookiePath = null; 25193 if(e.path){ 25194 if(e.path === "/us/nacional"){ 25195 e.path = "/us/noticias"; 25196 } 25197 redirectCookiePath = News.region.cookieFactory(e.path); 25198 News.region.setCookie("redirectRegionPath", redirectCookiePath); 25199 News.region.setCookie('redirectRegionName', e.ravenDisplayName) 25200 } 25201 return false; 25202 }else{ 25203 News.region.regionName = e.ravenDisplayName; 25204 if(e.path === "/us/nacional"){ 25205 e.path = "/us/noticias"; 25206 } 25207 News.region.regionPath = e.path; 25208 } 25209 } 25210 if(e.language === "en" && e.consumer === "web"){ 25211 let redirectCookiePath = null 25212 if(e.path){ 25213 if(e.path === "/us/national"){ 25214 e.path = "/us/snplus"; 25215 } 25216 redirectCookiePath = News.region.cookieFactory(e.path) 25217 } 25218 News.region.setCookie("redirectRegionPath", redirectCookiePath); 25219 News.region.setCookie('redirectRegionName', e.ravenDisplayName) 25220 } 25221 } 25222 }) 25223 25224 if (News.region.regionPath) { 25225 News.region.regionPath = News.region.cookieFactory(News.region.regionPath) 25226 News.region.setCookie('region', News.region.regionPath); 25227 News.region.setCookie('regionName', News.region.regionName) 25228 } 25229 resolve(News.region.regionPath); 25230 }, 25231 error: function (errResp) { 25232 console.error("Error in Regionalization API " + JSON.stringify(errResp)) 25233 resolve(News.region.regionPath); 25234 } 25235 }) 25236 }) 25237 }, 25238 25239 removeHighlighting: function () { 25240 jQuery('div .state').each(function () { 25241 var stateId = this.getAttribute('data-state-id'), 25242 $state = document.getElementById(stateId), 25243 classList = $state.getAttribute('class'); 25244 classList = classList.replace('state__icon-highlighted', ''); 25245 $state.setAttribute('class', classList); 25246 }); 25247 } 25248 }; 25249 25250 // --- Utility: Debounce to prevent rapid-fire clicks --- 25251 function debounce(func, wait) { 25252 let timeout; 25253 return function (...args) { 25254 clearTimeout(timeout); 25255 timeout = setTimeout(() => func.apply(this, args), wait); 25256 }; 25257 } 25258 25259 // --- COLLAPSE EVENTS --- 25260 25261 // Only allow one region list open at a time 25262 $('.region-selection__list').on('show.bs.collapse', '.collapse', function () { 25263 $('.region-selection__list').find('.collapse.in').each(function () { 25264 $(this).collapse('hide'); //close all other open lists 25265 }); 25266 }); 25267 25268 // Highlight the state when its panel is fully shown 25269 $('.region-selection__list').on('shown.bs.collapse', '.collapse', function () { 25270 var stateId = $(this).parent().attr('data-state-id'); 25271 News.region.highlightSelectedState(stateId); 25272 }); 25273 25274 // If all panels are closed, highlight all service areas 25275 $('.region-selection__list').on('hidden.bs.collapse', '.collapse', function () { 25276 if ($('.panel-collapse.in').length === 0) { 25277 News.region.highlightServiceAreas(); 25278 } 25279 }); 25280 25281 // --- PANEL HEADING CLICK --- 25282 25283 // Use debounce to prevent race conditions on rapid clicks 25284 $('.panel-heading').click(debounce(function () { 25285 var stateId = $(this).attr('data-state-id'); 25286 if (!stateId) return; 25287 // The highlighting is handled in the shown.bs.collapse event above 25288 }, 100)); // 100ms debounce 25289 25290 // --- MAP CLICK --- 25291 25292 // When a state on the map is clicked, select and highlight it 25293 $(".region-selection__map path").click(function (event) { 25294 if (!$(event.target).hasClass('state__icon-highlighted')) { 25295 return; 25296 } 25297 // Remove all selections 25298 $('svg .state__icon-selected').removeClass('state__icon-selected').addClass('state__icon-highlighted'); 25299 var state = event.target.id; 25300 // Close all panels 25301 $('.region-selection__list').find('.collapse.in').each(function () { 25302 $(this).parent().find('.panel-title').attr('aria-expanded', 'false');
25303 $(this).removeClass('in').attr('style', 'height: 0px;'); 25304 //remove selection from previous state 25305 News.region.highlightSelectedState(this.parentElement.getAttribute('data-state-id')); 25306 }); 25307 // Highlight the selected state 25308 News.region.highlightSelectedState(state); 25309 // Open the relevant panel and update UI 25310 $('div .state').each(function () { 25311 var statePath = this.getAttribute('data-state-path').toLowerCase(); 25312 var stateId = this.getAttribute('data-state-id'); 25313 if (stateId.toLowerCase() === state.toLowerCase() || statePath.indexOf(state.toLowerCase()) != -1) { 25314 $('#' + stateId).removeClass('state__icon-highlighted').addClass('state__icon-selected'); 25315 $(this).find('.panel-title').attr('aria-expanded', 'true'); 25316 $(this).find('.panel-collapse').addClass('in').attr('style', ''); 25317 //$(this).find('.panel-collapse').addClass('in'); 25318 } else { 25319 if ($('#' + stateId).is('.state__icon-selected')) { 25320 $('#' + stateId).removeClass('state__icon-selected').addClass('state__icon-highlighted'); 25321 } 25322 } 25323 }); 25324 // If nothing is selected, highlight all service areas 25325 if ($('.state__icon-selected').length == 0) { 25326 News.region.highlightServiceAreas(); 25327 } 25328 }); 25329 25330 // --- REGION SELECTION FROM SPLASH PAGE --- 25331 25332 // When a region is selected from the splash page, set cookie and redirect 25333 $('.region-selection .panel-body a').each(function () { 25334 25335 $(this).on('click', function (e) { 25336 e.preventDefault(); 25337 // NEWS-7819 Adobe Analytics locationSelect event 25338 let originalHref = $(this).attr('href'); 25339 let locationName = $(this).text().trim(); 25340 let region = $(this).parents('.panel-collapse').siblings('.panel-title').text().trim(); 25341 25342 let eventPayload = { 25343 action: "locationSelect", 25344 actionPageName: "Splash", 25345 newsMarket: region.includes('National') || region.includes('Nationwide') ? 'U.S.' : locationName, 25346 selectedLocation: locationName + ', ' + region, 25347 selectedNewsLocation: originalHref 25348 } 25349 console.log('locationSelect', eventPayload); 25350 window._satellite && window._satellite.track('trackAction', eventPayload); 25351 25352 // // determine if we'll handle a redirect according to selectors in the URL 25353 // var willRedirect = false; 25354 // var indexOfDotInPathname = window.location.pathname.indexOf('.'); 25355 // if (indexOfDotInPathname > -1) { 25356 // willRedirect = true; 25357 // e.preventDefault(); 25358 // } 25359 let regionPath = News.region.cookieFactory($(this).attr('href')) 25360 regionPath = regionPath.split('?')[0]; 25361 25362 News.region.setCookie('region', regionPath); 25363 25364 // // early return if no redirect will occur 25365 // if (!willRedirect) { 25366 // return; 25367 // } 25368 25369 // // redirect based on selectors 25370 // var selectorString = window.location.pathname.substring(indexOfDotInPathname) + window.location.search; 25371 // var newLocation = selectorString.replace('.', '/'); 25372 if ($(this).attr('target') === '_blank') { 25373 window.open($(this).attr('href'), '_blank'); 25374 } else { 25375 window.location = $(this).attr('href'); 25376 } 25377 }); 25378 }); 25379 var state = window.location.hash.substr(1); 25380 if (state) { 25381 jQuery('div .state').each(function () { 25382 var statePath = this.getAttribute('data-state-path'); 25383 var stateId = this.getAttribute('data-state-id'); 25384 if (stateId && stateId.toLowerCase() === state.toLowerCase() || state.toLowerCase().indexOf(statePath) != -1) { 25385 $('#' + stateId).removeClass('state__icon-highlighted').addClass('state__icon-selected'); 25386 $(this).find('.panel-title').attr('aria-expanded', 'true'); 25387 $(this).find('.panel-collapse').addClass('in'); 25388 } else { 25389 if (!$('#' + stateId).is('.state__icon-selected')) { 25390 $('#' + stateId).removeClass('state__icon-selected').removeClass('state__icon-highlighted'); 25391 } 25392 } 25393 }); 25394 } else { 25395 News.region.highlightServiceAreas(); 25396 } 25397}); 25398+function ($) { 25399 $('.navbar .follow-button').hover(function(){ 25400 var gridFloatBreakpoint = 1200; 25401 25402 //If on desktop view, position Header Social Icon Container below Follow Button 25403 if(window.innerWidth > gridFloatBreakpoint){ 25404 $('.header-social-container').css({ 25405 top: $('.follow-button').position().top + 65, 25406 left: $('.follow-button').position().left - 150, 25407 }); 25408 } 25409 //If not on desktop view, reset position of Header Social Icon Container 25410 else { 25411 $('.header-social-container').css({ 25412 top: 0, left: 0, 25413 }); 25414 } 25415 }); 25416}(jQuery); 25417 25418;(function ($) { 25419 25420 /* Relative Time jQuery Plugin 25421 * 25422 * On page load, queries for ".relative-time" elements and displays the date/time in the `data-time` property as 25423 * a relative time from now. ("3 minutes ago", "9 days ago", etc.) 25424 * 25425 * Currently only accepts the date format from java.util.Date#toString() (see https://goo.gl/dm0H7Y). 25426 * 25427 * This plugin depends on humanize-duration (http://evanhahn.github.io/HumanizeDuration.js/) being loaded beforehand. 25428 */ 25429 25430 function RelativeTime(element /*, options */) { 25431 this.$element = $(element); 25432 } 25433 25434 RelativeTime.prototype.render = function render() { 25435 25436 var time = this.$element.data('time'); 25437 25438 if (!time) { 25439 return; 25440 } 25441 25442 var duration = Date.now() - time; 25443 25444 if (duration < 3600000) { 25445 //adds data-recent attribute in order to decorate via CSS 25446 this.$element.attr('data-recent','true'); 25447 } 25448 25449 var duration = Date.now() - time, 25450 language = $('html').attr('lang'), 25451 text = humanizeDuration(duration, { largest: 1 , language: language, ago: true}); // get relative time text (1 week, etc) 25452 this.$element.text(text); 25453 } 25454 25455 function Plugin(/* option */) { 25456 return this.each(function () { 25457 var $this = $(this), 25458 data = $this.data('news.relativeTime'); 25459 25460 if (!data) $this.data('news.relativeTime', (data = new RelativeTime(this))); 25461 data.render(); 25462 }) 25463 } 25464 25465 var old = $.fn.relativeTime; 25466 25467 $.fn.relativeTime = Plugin; 25468 $.fn.relativeTime.Constructor = RelativeTime; 25469 25470 // RELATIVE TIME NO CONFLICT 25471 // ==================== 25472 25473 $.fn.relativeTime.noConflict = function () { 25474 $.fn.relativeTime = old 25475 return this 25476 } 25477 25478 // RELATIVE TIME DATA-API 25479 // ==================== 25480 $(document).ready(function () { 25481 $('.relative-time, .article__relative-time').each(function () { 25482 Plugin.call($(this)); 25483 }); 25484 }); 25485 25486 // call plugin on articles added after initial page load 25487 $(window).on('article-append', function(e) { 25488 $(e.target).find('.relative-time, .article__relative-time').each(function() { 25489 Plugin.call($(this)); 25490 }); 25491 }) 25492 25493}(jQuery)); 25494 25495/* Tests whether a URL in an article matches our format for other article urls */ 25496 25497function isArticleUrl (url) { 25498 // Requires format: /state/loc/vertical/yyyy/mm/dd 25499 const articleRE = /(\/([^\/]*)){3}(\/\d{4}\/(\d{1,2})\/(\d{1,2})\/)/; 25500 var m = void 0; 25501 25502 if (m = articleRE.exec(url) !== null) { 25503 return true; 25504 } 25505 return false;
25506} 25507 25508;(function ($) { 25509 var regionRegex = /(\/[^\/\.]+){2}/; 25510 var locURL = location.pathname; 25511 var m = void 0; 25512 var locationRegion = null; 25513 if ((m = regionRegex.exec(locURL)) !== null) { 25514 locationRegion = m[0]; 25515 } 25516 $.fn.regionalizeURL = function () { 25517 $(this).filter(function (locationRegion) { 25518 return $(this).prop('href').indexOf(location.origin) === 0; 25519 }).each(function(index, el){ 25520 try { 25521 var linkURL = new URL($(el).prop("href")); 25522 var m = void 0; 25523 var href = $(el).attr("href"); 25524 if ((m = regionRegex.exec(linkURL)) !== null) { 25525 $(el).attr("href", href.replace(/(\/[^\/]+){2}/, locationRegion)); 25526 } 25527 } catch (err) { 25528 } 25529 return this; 25530 }); 25531 }; 25532})(jQuery); 25533 25534$(document).ready(function () { 25535 $('.content-list-layout a,.wxAlertBar a').filter(function (locationRegion) { 25536 // Filter links to ensure: 25537 // the link is relative 25538 // the link is not on a view more button. 25539 // Note: .attr can detect relative links, .prop can not 25540 25541 return $(this).attr('href') && 25542 $(this).attr('href').indexOf('/') === 0 && 25543 $(this).closest("a[class*='view-more']").length === 0; 25544 }).regionalizeURL(); 25545 // For article-body links, apply an additional filter to determine if the URL is to an article or not 25546 $('.article-body a').filter(function(){ 25547 return isArticleUrl($(this).attr('href')) 25548 }).filter(function (locationRegion) { 25549 // Filter links to ensure: 25550 // the link is relative 25551 // the link is not on a view more button. 25552 // Note: .attr can detect relative links, .prop can not 25553 25554 return $(this).attr('href') && 25555 $(this).attr('href').indexOf('/') === 0 && 25556 $(this).closest("a[class*='view-more']").length === 0; 25557 }).regionalizeURL(); 25558 25559 // call plugin on articles added after initial page load 25560 $(window).on('article-append', function(e) { 25561 if(document.querySelector('.site-header')){ 25562 $(e.target).find('a').regionalizeURL(); 25563 } 25564 }) 25565 25566}); 25567 25568/* 25569 * Looks for inline CSS divs and appends them to the head. 25570 */ 25571+function($) { 25572 $("div[data-clientlibsource]").each(function(){ 25573 var cssClientLibSrc = $(this).attr("data-clientlibsource"); 25574 $('head').append('<link rel="stylesheet" href="' + cssClientLibSrc + '" type="text/css" />'); 25575 $(this).remove(); 25576 }); 25577}(jQuery); 25578 25579"use strict"; 25580$(function() { 25581 25582 if (! isMobile.any) { 25583 var href = $('#login-button').attr('href'); 25584 var loginText = $('#login-button').text(); 25585 25586 $('#spectrumSignup .signup-title').html($('.signup-title').data('logintitle')); 25587 $('#spectrumSignup .signup-body').html($('.signup-body').data('logintext')); 25588 $('#spectrumSignup .signupButton a').html($('.signupButton').data('buttontext')); 25589 $('#spectrumSignup .loginwrapper a').attr('href', href); 25590 $('#spectrumSignup .loginwrapper a').html(loginText); 25591 } 25592 else { 25593 var url; 25594 if(isMobile.apple.device) { 25595 url = $('.signupButton').data('app-store-url') || 'https://itunes.apple.com/us/app/twc-news/id740948885?ls=1&mt=8'; 25596 } 25597 else { 25598 url = $('.signupButton').data('play-store-url') || 'https://play.google.com/store/apps/details?id=com.twcable.twcnews'; 25599 } 25600 25601 $('#spectrumSignup .signupButton a').attr('href', url); 25602 } 25603 25604}); 25605/** 25606 * CSS hides flair when div empty via :empty pseudo class 25607 * applyFlair() checks off time and places flair-text in div. 25608 * 25609 * @param $ 25610 * @returns {Object} this 25611 */ 25612+(function ($) { 25613 $(document).ready(function () { 25614 $('.flair').applyFlair(); 25615 }); 25616 25617 // Apply flair on articles added after initial page load 25618 $(window).on('article-append', function(e) { 25619 $(e.target).find('.flair').applyFlair(); 25620 }) 25621 25622 $.fn.applyFlair = function () { 25623 var currentUTC = new Date().getTime(); 25624 25625 $(this).each(function (index, element) { 25626 var offTime = $(element).data("flair-off-time") || 0, 25627 flairText = $(element).data("flair-text") || ""; 25628 25629 if ((offTime === 0 || (currentUTC < offTime)) && flairText.length > 0) { 25630 if ($(element).css('display') == 'none') { 25631 // if element was hidden by this function on first run, unhide it 25632 $(element).show(); 25633 } 25634 $(element).text(flairText); 25635 } else { 25636 $(element).hide(); 25637 } 25638 }); 25639 return this; 25640 } 25641})(jQuery); 25642"use strict"; 25643$(function() { 25644 // This function is needed for backward compatibility and may be removed in the future 25645 $('span._rte_replace_tag').each(function(){ 25646 var tmpTag = this.innerText.replace("<_", "<"), 25647 _html = $.parseHTML(tmpTag, true), 25648 _tag = document.createElement(_html[0].tagName), 25649 _attrs = _html[0].attributes; 25650 if(_attrs){ 25651 for(var i = _attrs.length - 1; i >= 0; i--){ 25652 _tag.setAttribute(_attrs[i].name, _attrs[i].value); 25653 } 25654 } 25655 25656 $('body').append(_tag); 25657 this.parentNode.removeChild(this); 25658 }); 25659 25660 $('.embedcode iframe:not([id*="twitter"])').each(function(){ 25661 var element = this, 25662 instagramRegEx = /(http(s)?:)?\/\/.*instagram.*/, 25663 facebookPostRegEx = /(http(s)?:)?\/\/.*facebook.com\/plugins\/post.php*/, 25664 threadsRegEx = /(http(s)?:)?\/\/.*threads.*/, 25665 truthSocialRegEx = /(http(s)?:)?\/\/.*truthsocial.com\/.*/, 25666 infogramRegEx = /(http(s)?:)?\/\/.*infogram.com\/.*/; 25667 25668 if(facebookPostRegEx.test(element.src) == true && element.parentNode.nodeName == 'CENTER'){ 25669 element.style.minWidth='unset'; 25670 element.style.width = element.width+'px'; 25671 } 25672 25673 // Don't do anything for Instagram, FB, or Infogram 25674 if (instagramRegEx.test(element.src) == true) return; 25675 else if (threadsRegEx.test(element.src) == true) return; 25676 else if (truthSocialRegEx.test(element.src) == true) return; 25677 else if (facebookPostRegEx.test(element.src) == true) return; 25678 else if (infogramRegEx.test(element.src) == true) return; 25679 25680 //If height/width is already 100%, skip setting manually. 25681 if(element.width == '100%' || element.height == '100%'){ 25682 return; 25683 } 25684 var parentCss = "", 25685 cssText = 'height: 100%;'; 25686 25687 var ratio = ((element.height/element.width)*100).toPrecision(4) + '%;'; 25688 parentCss += "height:0;padding-bottom:" + ratio; 25689 if(element.src.includes('youtube')){ 25690 parentCss = parentCss+'clear:both;' 25691 } 25692 cssText += 'position:absolute;'; 25693 25694 element.style.cssText += cssText; 25695 element.parentNode.style.cssText += parentCss; 25696 25697 }); 25698}); 25699 25700/** @license Hyphenator 5.3.0 - client side hyphenation for webbrowsers 25701 * Copyright (C) 2017 Mathias Nater, Zürich (mathiasnater at gmail dot com) 25702 * https://github.com/mnater/Hyphenator 25703 * 25704 * Released under the MIT license 25705 * http://mnater.github.io/Hyphenator/LICENSE.txt 25706 */ 25707 25708/* 25709 * Comments are jsdoc3 formatted. See http://usejsdoc.org 25710 * Use mergeAndPack.html to get rid of the comments and to reduce the file size of this script! 25711 */ 25712
25713/* The following comment is for JSLint: */ 25714/*jslint browser: true, multivar: true, eval: true*/ 25715/*global Hyphenator window*/ 25716 25717/** 25718 * @desc Provides all functionality to do hyphenation, except the patterns that are loaded externally 25719 * @global 25720 * @namespace Hyphenator 25721 * @author Mathias Nater, <[email protected]> 25722 * @version 5.3.0 25723 * @example 25724 * <script src = "Hyphenator.js" type = "text/javascript"></script> 25725 * <script type = "text/javascript"> 25726 * Hyphenator.run(); 25727 * </script> 25728 */ 25729var Hyphenator; 25730Hyphenator = (function (window) { 25731 "use strict"; 25732 25733 /** 25734 * @member Hyphenator~contextWindow 25735 * @access private 25736 * @desc 25737 * contextWindow stores the window for the actual document to be hyphenated. 25738 * If there are frames this will change. 25739 * So use contextWindow instead of window! 25740 */ 25741 var contextWindow = window; 25742 25743 25744 /** 25745 * @member {Object.<string, Hyphenator~supportedLangs~supportedLanguage>} Hyphenator~supportedLangs 25746 * @desc 25747 * A generated key-value object that stores supported languages and meta data. 25748 * The key is the {@link http://tools.ietf.org/rfc/bcp/bcp47.txt bcp47} code of the language and the value 25749 * is an object of type {@link Hyphenator~supportedLangs~supportedLanguage} 25750 * @namespace Hyphenator~supportedLangs 25751 * @access private 25752 * //Check if language lang is supported: 25753 * if (supportedLangs.hasOwnProperty(lang)) 25754 */ 25755 var supportedLangs = (function () { 25756 /** 25757 * @typedef {Object} Hyphenator~supportedLangs~supportedLanguage 25758 * @property {string} file - The name of the pattern file 25759 * @property {number} script - The script type of the language (e.g. "latin" for english), this type is abbreviated by an id 25760 * @property {string} prompt - The sentence prompted to the user, if Hyphenator.js doesn"t find a language hint 25761 */ 25762 25763 /** 25764 * @lends Hyphenator~supportedLangs 25765 */ 25766 var r = {}, 25767 /** 25768 * @method Hyphenator~supportedLangs~o 25769 * @desc 25770 * Sets a value of Hyphenator~supportedLangs 25771 * @access protected 25772 * @param {string} code The {@link http://tools.ietf.org/rfc/bcp/bcp47.txt bcp47} code of the language 25773 * @param {string} file The name of the pattern file 25774 * @param {Number} script A shortcut for a specific script: latin:0, cyrillic: 1, arabic: 2, armenian:3, bengali: 4, devangari: 5, greek: 6 25775 * gujarati: 7, kannada: 8, lao: 9, malayalam: 10, oriya: 11, persian: 12, punjabi: 13, tamil: 14, telugu: 15, georgian: 16 25776 * @param {string} prompt The sentence prompted to the user, if Hyphenator.js doesn"t find a language hint 25777 */ 25778 o = function (code, file, script, prompt) { 25779 r[code] = {"file": file, "script": script, "prompt": prompt}; 25780 }; 25781 25782 o("be", "be.js", 1, "Ðова гÑÑага ÑайÑа не можа бÑÑÑ Ð²ÑзнаÑÐ°Ð½Ñ Ð°ÑÑамаÑÑÑна. ÐÐ°Ð»Ñ Ð»Ð°Ñка пакажÑÑе мовÑ:"); 25783 o("ca", "ca.js", 0, ""); 25784 o("cs", "cs.js", 0, "Jazyk této internetové stránky nebyl automaticky rozpoznán. UrÄete prosÃm jejà jazyk:"); 25785 o("cu", "cu.js", 1, "êÒзÑÌÐºÑ ÑÐµÐ³Ñ¡Ì ÑаÌйÑа не моÌжеÑÑ Ñ¡ÒпÑедѣлеÌÐ½Ñ Ð±ÑÌÑи. ÐÑоÑêÌ Ñѧ á²ÑÒказаÌÑи êÒзÑÌкÑ:"); 25786 o("da", "da.js", 0, "Denne websides sprog kunne ikke bestemmes. Angiv venligst sprog:"); 25787 o("bn", "bn.js", 4, ""); 25788 o("de", "de.js", 0, "Die Sprache dieser Webseite konnte nicht automatisch bestimmt werden. Bitte Sprache angeben:"); 25789 o("el", "el-monoton.js", 6, ""); 25790 o("el-monoton", "el-monoton.js", 6, ""); 25791 o("el-polyton", "el-polyton.js", 6, ""); 25792 o("en", "en-us.js", 0, "The language of this website could not be determined automatically. Please indicate the main language:"); 25793 o("en-gb", "en-gb.js", 0, "The language of this website could not be determined automatically. Please indicate the main language:"); 25794 o("en-us", "en-us.js", 0, "The language of this website could not be determined automatically. Please indicate the main language:"); 25795 o("eo", "eo.js", 0, "La lingvo de Äi tiu retpaÄo ne rekoneblas aÅtomate. Bonvolu indiki Äian Äeflingvon:"); 25796 o("es", "es.js", 0, "El idioma del sitio no pudo determinarse autom%E1ticamente. Por favor, indique el idioma principal:"); 25797 o("et", "et.js", 0, "Veebilehe keele tuvastamine ebaõnnestus, palun valige kasutatud keel:"); 25798 o("fi", "fi.js", 0, "Sivun kielt%E4 ei tunnistettu automaattisesti. M%E4%E4rit%E4 sivun p%E4%E4kieli:"); 25799 o("fr", "fr.js", 0, "La langue de ce site n%u2019a pas pu %EAtre d%E9termin%E9e automatiquement. Veuillez indiquer une langue, s.v.p.%A0:"); 25800 o("ga", "ga.js", 0, "NÃorbh fhéidir teanga an tsuÃmh a fháil go huathoibrÃoch. Cuir isteach prÃomhtheanga an tsuÃmh:"); 25801 o("grc", "grc.js", 6, ""); 25802 o("gu", "gu.js", 7, ""); 25803 o("hi", "hi.js", 5, ""); 25804 o("hu", "hu.js", 0, "A weboldal nyelvét nem sikerült automatikusan megállapÃtani. Kérem adja meg a nyelvet:"); 25805 o("hy", "hy.js", 3, "ÕÕ°Õ¡Õ»Õ¸Õ²Õ¾Õ¥Ö Õ°Õ¡ÕµÕ¿Õ¶Õ¡Õ¢Õ¥ÖÕ¥Õ¬ Õ¡Õ
25805µÕ½ Õ¯Õ¡ÕµÖÕ« Õ¬Õ¥Õ¦Õ¸ÖÕ¶Ö Ô½Õ¶Õ¤ÖÕ¸ÖÕ´ Õ¥Õ¶Ö Õ¶Õ·Õ¥Ö Õ°Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¬Õ¥Õ¦Õ¸ÖÕ¶Õ"); 25806 o("it", "it.js", 0, "Lingua del sito sconosciuta. Indicare una lingua, per favore:"); 25807 o("ka", "ka.js", 16, ""); 25808 o("kn", "kn.js", 8, "à²à²¾à²² ತಾಣದ à²à²¾à²·à³à²¯à²¨à³à²¨à³ ನಿರà³à²§à²°à²¿à²¸à²²à³ ಸಾಧà³à²¯à²µà²¾à²à³à²¤à³à²¤à²¿à²²à³à²². ದಯವಿà²à³à²à³ ಮà³à²à³à²¯ à²à²¾à²·à³à²¯à²¨à³à²¨à³ ಸà³à²à²¿à²¸à²¿:"); 25809 o("la", "la.js", 0, ""); 25810 o("lt", "lt.js", 0, "Nepavyko automatiÅ¡kai nustatyti Å¡ios svetainÄs kalbos. PraÅ¡ome įvesti kalbÄ :"); 25811 o("lv", "lv.js", 0, "Å Ä«s lapas valodu nevarÄja noteikt automÄtiski. LÅ«dzu norÄdiet pamata valodu:"); 25812 o("ml", "ml.js", 10, "à´ à´µàµ%u0D2C%u0D4D%u200Cà´¸àµà´±àµà´±à´¿à´¨àµà´±àµ à´à´¾à´· à´à´£àµà´àµà´ªà´¿à´à´¿à´¯àµà´àµà´à´¾%u0D28%u0D4D%u200D à´à´´à´¿à´àµà´à´¿à´²àµà´². à´à´¾à´· à´à´¤à´¾à´£àµà´¨àµà´¨àµ തിരà´àµà´àµà´àµà´àµà´àµà´:"); 25813 o("nb", "nb-no.js", 0, "Nettstedets sprÃ¥k kunne ikke finnes automatisk. Vennligst oppgi sprÃ¥k:"); 25814 o("no", "nb-no.js", 0, "Nettstedets sprÃ¥k kunne ikke finnes automatisk. Vennligst oppgi sprÃ¥k:"); 25815 o("nb-no", "nb-no.js", 0, "Nettstedets sprÃ¥k kunne ikke finnes automatisk. Vennligst oppgi sprÃ¥k:"); 25816 o("nl", "nl.js", 0, "De taal van deze website kan niet automatisch worden bepaald. Geef de hoofdtaal op:"); 25817 o("or", "or.js", 11, ""); 25818 o("pa", "pa.js", 13, ""); 25819 o("pl", "pl.js", 0, "JÄzyka tej strony nie można ustaliÄ automatycznie. ProszÄ wskazaÄ jÄzyk:"); 25820 o("pt", "pt.js", 0, "A lÃngua deste site não pôde ser determinada automaticamente. Por favor indique a lÃngua principal:"); 25821 o("ru", "ru.js", 1, "ЯзÑк ÑÑого ÑайÑа не Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¾Ð¿Ñеделен авÑомаÑиÑеÑки. ÐожалÑйÑÑа ÑкажиÑе ÑзÑк:"); 25822 o("sk", "sk.js", 0, ""); 25823 o("sl", "sl.js", 0, "Jezika te spletne strani ni bilo mogoÄe samodejno doloÄiti. Prosim navedite jezik:"); 25824 o("sr-cyrl", "sr-cyrl.js", 1, "Ðезик овог ÑаÑÑа ниÑе деÑекÑован аÑÑомаÑÑки. Ðолим Ð²Ð°Ñ Ð½Ð°Ð²ÐµÐ´Ð¸Ñе Ñезик:"); 25825 o("sr-latn", "sr-latn.js", 0, "Jezika te spletne strani ni bilo mogoÄe samodejno doloÄiti. Prosim navedite jezik:"); 25826 o("sv", "sv.js", 0, "Spr%E5ket p%E5 den h%E4r webbplatsen kunde inte avg%F6ras automatiskt. V%E4nligen ange:"); 25827 o("ta", "ta.js", 14, ""); 25828 o("te", "te.js", 15, ""); 25829 o("tr", "tr.js", 0, "Bu web sitesinin dili otomatik olarak tespit edilememiÅtir. Lütfen dökümanın dilini seçiniz%A0:"); 25830 o("uk", "uk.js", 1, "Ðова ÑÑого веб-ÑайÑÑ Ð½Ðµ може бÑÑи визнаÑена авÑомаÑиÑно. ÐÑÐ´Ñ Ð»Ð°Ñка, вкажÑÑÑ Ð³Ð¾Ð»Ð¾Ð²Ð½Ñ Ð¼Ð¾Ð²Ñ:"); 25831 o("ro", "ro.js", 0, "Limba acestui sit nu a putut fi determinatÄ automat. Alege limba principalÄ:"); 25832 25833 return r; 25834 }()); 25835 25836 25837 25838 /** 25839 * @member {Object} Hyphenator~locality 25840 * @desc 25841 * An object storing isBookmarklet, basePath and isLocal 25842 * @access private 25843 * @see {@link Hyphenator~loadPatterns} 25844 */ 25845 var locality = (function getLocality() { 25846 var r = { 25847 isBookmarklet: false, 25848 basePath: "//mnater.github.io/Hyphenator/", 25849 isLocal: false 25850 }; 25851 var fullPath; 25852 function getBasePath(path) { 25853 if (!path) { 25854 return r.basePath; 25855 } 25856 return path.substring(0, path.lastIndexOf("/") + 1); 25857 } 25858 function findCurrentScript() { 25859 var scripts = contextWindow.document.getElementsByTagName("script"); 25860 var num = scripts.length - 1; 25861 var currScript; 25862 var src; 25863 while (num >= 0) { 25864 currScript = scripts[num]; 25865 if ((currScript.src || currScript.hasAttribute("src")) && currScript.src.indexOf("Hyphenator") !== -1) { 25866 src = currScript.src; 25867 break; 25868 } 25869 num -= 1; 25870 } 25871 return src; 25872 } 25873 if (!!document.currentScript) { 25874 fullPath = document.currentScript.src; 25875 } else { 25876 fullPath = findCurrentScript(); 25877 } 25878 r.basePath = getBasePath(fullPath); 25879 if (fullPath && fullPath.indexOf("bm=true") !== -1) { 25880 r.isBookmarklet = true; 25881 } 25882 if (window.location.href.indexOf(r.basePath) !== -1) { 25883 r.isLocal = true; 25884 } 25885 return r; 25886 }()); 25887 25888 /** 25889 * @member {string} Hyphenator~basePath
25890 * @desc 25891 * A string storing the basepath from where Hyphenator.js was loaded. 25892 * This is used to load the pattern files. 25893 * The basepath is determined dynamically in getLocality by searching all script-tags for Hyphenator.js 25894 * If the path cannot be determined {@link http://mnater.github.io/Hyphenator/} is used as fallback. 25895 * @access private 25896 * @see {@link Hyphenator~loadPatterns} 25897 */ 25898 var basePath = locality.basePath; 25899 25900 /** 25901 * @member {boolean} Hyphenator~isLocal 25902 * @access private 25903 * @desc 25904 * This is computed by getLocality. 25905 * isLocal is true, if Hyphenator is loaded from the same domain, as the webpage, but false, if 25906 * it"s loaded from an external source (i.e. directly from github) 25907 */ 25908 var isLocal = locality.isLocal; 25909 25910 /** 25911 * @member {boolean} Hyphenator~documentLoaded 25912 * @access private 25913 * @desc 25914 * documentLoaded is true, when the DOM has been loaded. This is set by {@link Hyphenator~runWhenLoaded} 25915 */ 25916 var documentLoaded = false; 25917 25918 /** 25919 * @member {boolean} Hyphenator~persistentConfig 25920 * @access private 25921 * @desc 25922 * if persistentConfig is set to true (defaults to false), config options and the state of the 25923 * toggleBox are stored in DOM-storage (according to the storage-setting). So they haven"t to be 25924 * set for each page. 25925 * @default false 25926 * @see {@link Hyphenator.config} 25927 */ 25928 var persistentConfig = false; 25929 25930 /** 25931 * @member {boolean} Hyphenator~doFrames 25932 * @access private 25933 * @desc 25934 * switch to control if frames/iframes should be hyphenated, too. 25935 * defaults to false (frames are a bag of hurt!) 25936 * @default false 25937 * @see {@link Hyphenator.config} 25938 */ 25939 var doFrames = false; 25940 25941 /** 25942 * @member {Object.<string,boolean>} Hyphenator~dontHyphenate 25943 * @desc 25944 * A key-value object containing all html-tags whose content should not be hyphenated 25945 * @access private 25946 */ 25947 var dontHyphenate = {"video": true, "audio": true, "script": true, "code": true, "pre": true, "img": true, "br": true, "samp": true, "kbd": true, "var": true, "abbr": true, "acronym": true, "sub": true, "sup": true, "button": true, "option": true, "label": true, "textarea": true, "input": true, "math": true, "svg": true, "style": true}; 25948 25949 /** 25950 * @member {boolean} Hyphenator~enableCache 25951 * @desc 25952 * A variable to set if caching is enabled or not 25953 * @default true 25954 * @access private 25955 * @see {@link Hyphenator.config} 25956 */ 25957 var enableCache = true; 25958 25959 /** 25960 * @member {string} Hyphenator~storageType 25961 * @desc 25962 * A variable to define what html5-DOM-Storage-Method is used ("none", "local" or "session") 25963 * @default "local" 25964 * @access private 25965 * @see {@link Hyphenator.config} 25966 */ 25967 var storageType = "local"; 25968 25969 /** 25970 * @member {Object|undefined} Hyphenator~storage 25971 * @desc 25972 * An alias to the storage defined in storageType. This is set by {@link Hyphenator~createStorage}. 25973 * Set by {@link Hyphenator.run} 25974 * @default null 25975 * @access private 25976 * @see {@link Hyphenator~createStorage} 25977 */ 25978 var storage; 25979 25980 /** 25981 * @member {boolean} Hyphenator~enableReducedPatternSet 25982 * @desc 25983 * A variable to set if storing the used patterns is set 25984 * @default false 25985 * @access private 25986 * @see {@link Hyphenator.config} 25987 * @see {@link Hyphenator.getRedPatternSet} 25988 */ 25989 var enableReducedPatternSet = false; 25990 25991 /** 25992 * @member {boolean} Hyphenator~enableRemoteLoading 25993 * @desc 25994 * A variable to set if pattern files should be loaded remotely or not 25995 * @default true 25996 * @access private 25997 * @see {@link Hyphenator.config} 25998 */ 25999 var enableRemoteLoading = true; 26000 26001 /** 26002 * @member {boolean} Hyphenator~displayToggleBox 26003 * @desc 26004 * A variable to set if the togglebox should be displayed or not 26005 * @default false 26006 * @access private 26007 * @see {@link Hyphenator.config} 26008 */ 26009 var displayToggleBox = false; 26010 26011 /** 26012 * @method Hyphenator~onError
26013 * @desc 26014 * A function that can be called upon an error. 26015 * @see {@link Hyphenator.config} 26016 * @access private 26017 */ 26018 var onError = function (e) { 26019 window.alert("Hyphenator.js says:\n\nAn Error occurred:\n" + e.message); 26020 }; 26021 26022 /** 26023 * @method Hyphenator~onWarning 26024 * @desc 26025 * A function that can be called upon a warning. 26026 * @see {@link Hyphenator.config} 26027 * @access private 26028 */ 26029 var onWarning = function (e) { 26030 window.console.log(e.message); 26031 }; 26032 26033 /** 26034 * @method Hyphenator~createElem 26035 * @desc 26036 * A function alias to document.createElementNS or document.createElement 26037 * @access private 26038 */ 26039 function createElem(tagname, context) { 26040 context = context || contextWindow; 26041 var el; 26042 if (window.document.createElementNS) { 26043 el = context.document.createElementNS("http://www.w3.org/1999/xhtml", tagname); 26044 } else if (window.document.createElement) { 26045 el = context.document.createElement(tagname); 26046 } 26047 return el; 26048 } 26049 /** 26050 * @method Hyphenator~forEachKey 26051 * @desc 26052 * Calls the function f on every property of o 26053 * @access private 26054 */ 26055 function forEachKey(o, f) { 26056 var k; 26057 if (Object.hasOwnProperty("keys")) { 26058 Object.keys(o).forEach(f); 26059 } else { 26060 for (k in o) { 26061 if (o.hasOwnProperty(k)) { 26062 f(k); 26063 } 26064 } 26065 } 26066 } 26067 26068 /** 26069 * @member {boolean} Hyphenator~css3 26070 * @desc 26071 * A variable to set if css3 hyphenation should be used 26072 * @default false 26073 * @access private 26074 * @see {@link Hyphenator.config} 26075 */ 26076 var css3 = false; 26077 26078 /** 26079 * @method Hyphenator~css3_gethsupport 26080 * @desc 26081 * This function returns a {@link Hyphenator~css3_hsupport} object for the current UA 26082 * @type function 26083 * @access private 26084 * @see Hyphenator~css3_h9n 26085 */ 26086 function css3_gethsupport() { 26087 var support = false, 26088 supportedBrowserLangs = {}, 26089 property = "", 26090 checkLangSupport, 26091 createLangSupportChecker = function (prefix) { 26092 var testStrings = [ 26093 //latin: 0 26094 "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz", 26095 //cyrillic: 1 26096 "абвгдеÑжзийклмнопÑÑÑÑÑÑ ÑÑÑÑÑÑÑÑÑÑ", 26097 //arabic: 2 26098 "Ø£Ø¨ØªØ«Ø¬ØØ®Ø¯Ø°Ø±Ø²Ø³Ø´ØµØ¶Ø·Ø¸Ø¹ØºÙÙÙÙÙ ÙÙÙÙ", 26099 //armenian: 3 26100 "Õ¡Õ¢Õ£Õ¤Õ¥Õ¦Õ§Õ¨Õ©ÕªÕ«Õ¬ÕÕ®Õ¯Õ°Õ±Õ²Õ³Õ´ÕµÕ¶Õ·Õ¸Õ¹ÕºÕ»Õ¼Õ½Õ¾Õ¿ÖÖÖÖÖÖ Ö", 26101 //bengali: 4 26102 "à¦à¦à¦à¦ à¦à¦à¦à¦à¦à¦à¦à¦à¦à¦à¦à¦à¦à¦à¦à¦à¦à¦à¦à¦à¦à¦à¦ ডঢণতথদধনপফবà¦à¦®à¦¯à¦°à¦²à¦¶à¦·à¦¸à¦¹à¦¼à¦½à¦¾à¦¿à§à§à§à§à§à§à§à§à§à§à§à§à¦¡à¦¼à¦¢à¦¼à¦¯à¦¼à§ ৡৢৣ", 26103 //devangari: 5 26104 "à¤à¤à¤à¤ à¤à¤à¤à¤à¤à¤à¤à¤à¤à¤à¤à¤à¤à¤à¤à¤à¤à¤à¤à¤à¤à¤à¤ डढणतथदधनपफबà¤à¤®à¤¯à¤°à¤²à¤³à¤µà¤¶à¤·à¤¸à¤¹à¤½à¤¾à¤¿à¥à¥à¥à¥à¥à¥à¥à¥à¥à¥à¥à¥à¥ ॡॢॣ", 26105 //greek: 6 26106 "αβγδεζηθικλμνξοÏÏÏÏÏÏ ÏÏÏÏ", 26107 //gujarati: 7 26108 "બહઠàªàªàªàªàªàªà« àªàªàªàªàª¾àª¿à«à«à«à«à«à«¢à«£à«à«à«à«àªàªàªàªàªàªàªàªàªàªàªàª ડઢણતથદધનપફસàªàª®àª¯àª°àª²àª³àªµàª¶àª·", 26109 //kannada: 8 26110 "à²à²à² à²à²à²à²à²à²à²à²à²à²à²à²à²à²à²à²à²à²à²à²à²à²à²à²à² ಡಢಣತಥದಧನಪಫಬà²à²®à²¯à²°à²±à²²à²³à²µà²¶à²·à²¸à²¹à²½à²¾à²¿à³à³à³à³à³à³à³à³à³à³à³à³à³à³à³à³ ೡ", 26111 //lao: 9 26112 "àºàºàºàºàºàºàºàºàºàºàºàºàºàºàºàºàºàºàº¡àº¢àº£àº¥àº§àºªàº«àºàº®àº°àº±àº²àº´àºµàº¶àº·àº¸àº¹àº»àº¼à»à»à»à»à»à»à»à»à»à»à»", 26113 //malayalam: 10 26114 "à´à´à´ à´à´à´à´à´à´à´à´à´à´à´à´à´à´à´à´à´à´à´à´à´à´à´à´à´ ഡഢണതഥദധനപഫബà´à´®à´¯à´°à´±à´²à´³à´´à´µà´¶à´·à´¸à´¹à´¾à´¿àµàµàµàµàµàµàµàµàµàµàµàµàµ ൡൺൻർൽൾൿ", 26115 //oriya: 11 26116 "à¬à¬à¬à¬ à¬à¬à¬à¬à¬à¬à¬à¬à¬à¬à¬à¬à¬à¬à¬à¬à¬à¬à¬à¬à¬à¬à¬ ଡଢଣତଥଦଧନପଫବà¬à¬®à¬¯à¬°à¬²à¬³à¬µà¬¶à¬·à¬¸à¬¹à¬¾à¬¿ààààààààààà à¡", 26117 //persian: 12 26118 "Ø£Ø¨ØªØ«Ø¬ØØ®Ø¯Ø°Ø±Ø²Ø³Ø´ØµØ¶Ø·Ø¸Ø¹ØºÙÙÙÙÙ ÙÙÙÙ", 26119 //punjabi: 13 26120 "à¨à¨à¨à¨ à¨à¨à¨à¨à¨à¨à¨à¨à¨à¨à¨à¨à¨à¨à¨à¨à¨à¨à¨à¨à¨ ਡਢਣਤਥਦਧਨਪਫਬà¨à¨®à¨¯à¨°à¨²à¨²à¨¼à¨µà¨¸à¨¼à¨¸à¨¹à¨¾à¨¿
26120à©à©à©à©à©à©à©à©à©°à©±", 26121 //tamil: 14 26122 "à®à® à®à®à®à®à®à®à®à®à®à®à®à®à®à®à®à®à®à®£à®¤à®¨à®©à®ªà®®à®¯à®°à®±à®²à®³à®´à®µà®·à®¸à®¹à®¾à®¿à¯à¯à¯à¯à¯à¯à¯à¯à¯à¯à¯", 26123 //telugu: 15 26124 "à°à°à°à° à°à°à°à°à°à°à°à°à°à°à°à°à°à°à°à°à°à°à°à°à°à°à°à°à° డఢణతథదధనపఫబà°à°®à°¯à°°à°±à°²à°³à°µà°¶à°·à°¸à°¹à°¾à°¿à±à±à±à±à±à±à±à±à±à±à±à±à±à±à± ౡ", 26125 //georgian: 16 26126 "áááá áá®á¢á£á¤ááááááá¬á¡áááá¥á§á¨á©áªá«áá¯áá¦ááá°" 26127 ], 26128 f = function (lang) { 26129 var shadow, 26130 computedHeight, 26131 bdy, 26132 r = false; 26133 26134 //check if lang has already been tested 26135 if (supportedBrowserLangs.hasOwnProperty(lang)) { 26136 r = supportedBrowserLangs[lang]; 26137 } else if (supportedLangs.hasOwnProperty(lang)) { 26138 //create and append shadow-test-element 26139 bdy = window.document.getElementsByTagName("body")[0]; 26140 shadow = createElem("div", window); 26141 shadow.id = "Hyphenator_LanguageChecker"; 26142 shadow.style.width = "5em"; 26143 shadow.style.padding = "0"; 26144 shadow.style.border = "none"; 26145 shadow.style[prefix] = "auto"; 26146 shadow.style.hyphens = "auto"; 26147 shadow.style.fontSize = "12px"; 26148 shadow.style.lineHeight = "12px"; 26149 shadow.style.wordWrap = "normal"; 26150 shadow.style.wordBreak = "normal"; 26151 shadow.style.visibility = "hidden"; 26152 shadow.lang = lang; 26153 shadow.style["-webkit-locale"] = "\"" + lang + "\""; 26154 shadow.innerHTML = testStrings[supportedLangs[lang].script]; 26155 bdy.appendChild(shadow); 26156 //measure its height 26157 computedHeight = shadow.offsetHeight; 26158 //remove shadow element 26159 bdy.removeChild(shadow); 26160 r = !!(computedHeight > 12); 26161 supportedBrowserLangs[lang] = r; 26162 } else { 26163 r = false; 26164 } 26165 return r; 26166 }; 26167 return f; 26168 }, 26169 s; 26170 26171 if (window.getComputedStyle) { 26172 s = window.getComputedStyle(window.document.getElementsByTagName("body")[0], null); 26173 if (s.hyphens !== undefined) { 26174 support = true; 26175 property = "hyphens"; 26176 checkLangSupport = createLangSupportChecker("hyphens"); 26177 } else if (s["-webkit-hyphens"] !== undefined) { 26178 support = true; 26179 property = "-webkit-hyphens"; 26180 checkLangSupport = createLangSupportChecker("-webkit-hyphens"); 26181 } else if (s.MozHyphens !== undefined) { 26182 support = true; 26183 property = "-moz-hyphens"; 26184 checkLangSupport = createLangSupportChecker("MozHyphens"); 26185 } else if (s["-ms-hyphens"] !== undefined) { 26186 support = true; 26187 property = "-ms-hyphens"; 26188 checkLangSupport = createLangSupportChecker("-ms-hyphens"); 26189 } 26190 } //else we just return the initial values because ancient browsers don"t support css3 anyway 26191 26192 26193 return { 26194 support: support, 26195 property: property, 26196 supportedBrowserLangs: supportedBrowserLangs, 26197 checkLangSupport: checkLangSupport 26198 }; 26199 } 26200 26201 /** 26202 * @typedef {Object} Hyphenator~css3_hsupport 26203 * @property {boolean} support - if css3-hyphenation is supported 26204 * @property {string} property - the css property name to access hyphen-settings (e.g. -webkit-hyphens) 26205 * @property {Object.<string, boolean>} supportedBrowserLangs - an object caching tested languages 26206 * @property {function} checkLangSupport - a method that checks if the browser supports a requested language 26207 */ 26208 26209 /** 26210 * @member {Hyphenator~css3_h9n} Hyphenator~css3_h9n
26211 * @desc 26212 * A generated object containing information for CSS3-hyphenation support 26213 * This is set by {@link Hyphenator~css3_gethsupport} 26214 * @default undefined 26215 * @access private 26216 * @see {@link Hyphenator~css3_gethsupport} 26217 * @example 26218 * //Check if browser supports a language 26219 * css3_h9n.checkLangSupport(<lang>) 26220 */ 26221 var css3_h9n; 26222 26223 /** 26224 * @member {string} Hyphenator~hyphenateClass 26225 * @desc 26226 * A string containing the css-class-name for the hyphenate class 26227 * @default "hyphenate" 26228 * @access private 26229 * @example 26230 * <p class = "hyphenate">Text</p> 26231 * @see {@link Hyphenator.config} 26232 */ 26233 var hyphenateClass = "hyphenate"; 26234 26235 /** 26236 * @member {string} Hyphenator~urlHyphenateClass 26237 * @desc 26238 * A string containing the css-class-name for the urlhyphenate class 26239 * @default "urlhyphenate" 26240 * @access private 26241 * @example 26242 * <p class = "urlhyphenate">Text</p> 26243 * @see {@link Hyphenator.config} 26244 */ 26245 var urlHyphenateClass = "urlhyphenate"; 26246 26247 /** 26248 * @member {string} Hyphenator~classPrefix 26249 * @desc 26250 * A string containing a unique className prefix to be used 26251 * whenever Hyphenator sets a CSS-class 26252 * @access private 26253 */ 26254 var classPrefix = "Hyphenator" + Math.round(Math.random() * 1000); 26255 26256 /** 26257 * @member {string} Hyphenator~hideClass 26258 * @desc 26259 * The name of the class that hides elements 26260 * @access private 26261 */ 26262 var hideClass = classPrefix + "hide"; 26263 26264 /** 26265 * @member {RegExp} Hyphenator~hideClassRegExp 26266 * @desc 26267 * RegExp to remove hideClass from a list of classes 26268 * @access private 26269 */ 26270 var hideClassRegExp = new RegExp("\\s?\\b" + hideClass + "\\b", "g"); 26271 26272 /** 26273 * @member {string} Hyphenator~hideClass 26274 * @desc 26275 * The name of the class that unhides elements 26276 * @access private 26277 */ 26278 var unhideClass = classPrefix + "unhide"; 26279 26280 /** 26281 * @member {RegExp} Hyphenator~hideClassRegExp 26282 * @desc 26283 * RegExp to remove unhideClass from a list of classes 26284 * @access private 26285 */ 26286 var unhideClassRegExp = new RegExp("\\s?\\b" + unhideClass + "\\b", "g"); 26287 26288 /** 26289 * @member {string} Hyphenator~css3hyphenateClass 26290 * @desc 26291 * The name of the class that hyphenates elements with css3 26292 * @access private 26293 */ 26294 var css3hyphenateClass = classPrefix + "css3hyphenate"; 26295 26296 /** 26297 * @member {CSSEdit} Hyphenator~css3hyphenateClass 26298 * @desc 26299 * The var where CSSEdit class is stored 26300 * @access private 26301 */ 26302 var css3hyphenateClassHandle; 26303 26304 /** 26305 * @member {string} Hyphenator~dontHyphenateClass 26306 * @desc 26307 * A string containing the css-class-name for elements that should not be hyphenated 26308 * @default "donthyphenate" 26309 * @access private 26310 * @example 26311 * <p class = "donthyphenate">Text</p> 26312 * @see {@link Hyphenator.config} 26313 */ 26314 var dontHyphenateClass = "donthyphenate"; 26315 26316 /** 26317 * @member {number} Hyphenator~min 26318 * @desc 26319 * A number wich indicates the minimal length of words to hyphenate. 26320 * @default 6 26321 * @access private 26322 * @see {@link Hyphenator.config} 26323 */ 26324 var min = 6; 26325 26326 /** 26327 * @member {number} Hyphenator~leftmin 26328 * @desc 26329 * A number wich indicates the minimal length of characters before the first hyphenation. 26330 * This value is only used if it is greater than the value in the pattern file. 26331 * @default given by pattern file 26332 * @access private 26333 * @see {@link Hyphenator.config} 26334 */ 26335 var leftmin = 0; 26336 26337 /** 26338 * @member {number} Hyphenator~rightmin 26339 * @desc 26340 * A number wich indicates the minimal length of characters after the last hyphenation. 26341 * This value is only used if it is greater than the value in the pattern file. 26342 * @default given by pattern file 26343 * @access private 26344 * @see {@link Hyphenator.config} 26345 */ 26346 var rightmin = 0; 26347 26348 /** 26349 * @member {number} Hyphenator~rightmin 26350 * @desc 26351 * Control how compound words are hyphenated. 26352 * "auto": factory-made -> fac-tory-made ("old" behaviour of Hyphenator.js) 26353 * "all": factory-made -> fac-tory-[ZWSP]made ("made".length < minWordLength) 26354 * "hyphen": factory-made -> factory-[ZWSP]made (Zero Width Space inserted after "-" to provide line breaking opportunity) 26355 * @default "auto" 26356 * @access private 26357 * @see {@link Hyphenator.config} 26358 */ 26359 var compound = "auto"; 26360 26361 /** 26362 * @member {number} Hyphenator~orphanControl
26363 * @desc 26364 * Control how the last words of a line are handled: 26365 * level 1 (default): last word is hyphenated 26366 * level 2: last word is not hyphenated 26367 * level 3: last word is not hyphenated and last space is non breaking 26368 * @default 1 26369 * @access private 26370 */ 26371 var orphanControl = 1; 26372 26373 /** 26374 * @member {boolean} Hyphenator~isBookmarklet 26375 * @desc 26376 * This is computed by getLocality. 26377 * True if Hyphanetor runs as bookmarklet. 26378 * @access private 26379 */ 26380 var isBookmarklet = locality.isBookmarklet; 26381 26382 /** 26383 * @member {string|null} Hyphenator~mainLanguage 26384 * @desc 26385 * The general language of the document. In contrast to {@link Hyphenator~defaultLanguage}, 26386 * mainLanguage is defined by the client (i.e. by the html or by a prompt). 26387 * @access private 26388 * @see {@link Hyphenator~autoSetMainLanguage} 26389 */ 26390 var mainLanguage = null; 26391 26392 /** 26393 * @member {string|null} Hyphenator~defaultLanguage 26394 * @desc 26395 * The language defined by the developper. This language setting is defined by a config option. 26396 * It is overwritten by any html-lang-attribute and only taken in count, when no such attribute can 26397 * be found (i.e. just before the prompt). 26398 * @access private 26399 * @see {@link Hyphenator.config} 26400 * @see {@link Hyphenator~autoSetMainLanguage} 26401 */ 26402 var defaultLanguage = ""; 26403 26404 /** 26405 * @member {ElementCollection} Hyphenator~elements 26406 * @desc 26407 * A class representing all elements (of type Element) that have to be hyphenated. This var is filled by 26408 * {@link Hyphenator~gatherDocumentInfos} 26409 * @access private 26410 */ 26411 var elements = (function () { 26412 /** 26413 * @constructor Hyphenator~elements~ElementCollection~Element 26414 * @desc represents a DOM Element with additional information 26415 * @access private 26416 */ 26417 var makeElement = function (element) { 26418 return { 26419 /** 26420 * @member {Object} Hyphenator~elements~ElementCollection~Element~element 26421 * @desc A DOM Element 26422 * @access protected 26423 */ 26424 element: element, 26425 /** 26426 * @member {boolean} Hyphenator~elements~ElementCollection~Element~hyphenated 26427 * @desc Marks if the element has been hyphenated 26428 * @access protected 26429 */ 26430 hyphenated: false, 26431 /** 26432 * @member {boolean} Hyphenator~elements~ElementCollection~Element~treated 26433 * @desc Marks if information of the element has been collected but not hyphenated (e.g. dohyphenation is off) 26434 * @access protected 26435 */ 26436 treated: false 26437 }; 26438 }, 26439 /** 26440 * @constructor Hyphenator~elements~ElementCollection 26441 * @desc A collection of Elements to be hyphenated 26442 * @access protected 26443 */ 26444 makeElementCollection = function () { 26445 /** 26446 * @member {number} Hyphenator~elements~ElementCollection~counters 26447 * @desc Array of [number of collected elements, number of hyphenated elements] 26448 * @access protected 26449 */ 26450 var counters = [0, 0], 26451 /** 26452 * @member {Object.<string, Array.<Element>>} Hyphenator~elements~ElementCollection~list 26453 * @desc The collection of elements, where the key is a language code and the value is an array of elements 26454 * @access protected 26455 */ 26456 list = {}, 26457 /** 26458 * @method Hyphenator~elements~ElementCollection.prototype~add 26459 * @augments Hyphenator~elements~ElementCollection 26460 * @access protected 26461 * @desc adds a DOM element to the collection 26462 * @param {Object} el - The DOM element 26463 * @param {string} lang - The language of the element 26464 */ 26465 add = function (el, lang) { 26466 var elo = makeElement(el); 26467 if (!list.hasOwnProperty(lang)) {
26468 list[lang] = []; 26469 } 26470 list[lang].push(elo); 26471 counters[0] += 1; 26472 return elo; 26473 }, 26474 /** 26475 * @callback Hyphenator~elements~ElementCollection.prototype~each~callback fn - The callback that is executed for each element 26476 * @param {string} [k] The key (i.e. language) of the collection 26477 * @param {Hyphenator~elements~ElementCollection~Element} element 26478 */ 26479 26480 /** 26481 * @method Hyphenator~elements~ElementCollection.prototype~each 26482 * @augments Hyphenator~elements~ElementCollection 26483 * @access protected 26484 * @desc takes each element of the collection as an argument of fn 26485 * @param {Hyphenator~elements~ElementCollection.prototype~each~callback} fn - A function that takes an element as an argument 26486 */ 26487 each = function (fn) { 26488 forEachKey(list, function (k) { 26489 if (fn.length === 2) { 26490 fn(k, list[k]); 26491 } else { 26492 fn(list[k]); 26493 } 26494 }); 26495 }; 26496 26497 return { 26498 counters: counters, 26499 list: list, 26500 add: add, 26501 each: each 26502 }; 26503 26504 }; 26505 return makeElementCollection(); 26506 }()); 26507 26508 26509 /** 26510 * @member {Object.<sting, string>} Hyphenator~exceptions 26511 * @desc 26512 * An object containing exceptions as comma separated strings for each language. 26513 * When the language-objects are loaded, their exceptions are processed, copied here and then deleted. 26514 * Exceptions can also be set by the user. 26515 * @see {@link Hyphenator~prepareLanguagesObj} 26516 * @access private 26517 */ 26518 var exceptions = {}; 26519 26520 /** 26521 * @member {Object.<string, boolean>} Hyphenator~docLanguages 26522 * @desc 26523 * An object holding all languages used in the document. This is filled by 26524 * {@link Hyphenator~gatherDocumentInfos} 26525 * @access private 26526 */ 26527 var docLanguages = {}; 26528 26529 /** 26530 * @member {string} Hyphenator~url 26531 * @desc 26532 * A string containing a insane RegularExpression to match URL"s 26533 * @access private 26534 */ 26535 var url = "(?:\\w*:\/\/)?(?:(?:\\w*:)?(?:\\w*)@)?(?:(?:(?:[\\d]{1,3}\\.){3}(?:[\\d]{1,3}))|(?:(?:www\\.|[a-zA-Z]\\.)?[a-zA-Z0-9\\-]+(?:\\.[a-z]{2,})+))(?::\\d*)?(?:\/[\\w#!:\\.?\\+=&%@!\\-]*)*"; 26536 // protocoll usr pwd ip or host tld port path 26537 26538 /** 26539 * @member {string} Hyphenator~mail 26540 * @desc 26541 * A string containing a RegularExpression to match mail-adresses 26542 * @access private 26543 */ 26544 var mail = "[\\w-\\.]+@[\\w\\.]+"; 26545 26546 /** 26547 * @member {string} Hyphenator~zeroWidthSpace 26548 * @desc 26549 * A string that holds a char. 26550 * Depending on the browser, this is the zero with space or an empty string. 26551 * zeroWidthSpace is used to break URLs 26552 * @access private 26553 */ 26554 var zeroWidthSpace = (function () { 26555 var zws, ua = window.navigator.userAgent.toLowerCase(); 26556 zws = String.fromCharCode(8203); //Unicode zero width space 26557 if (ua.indexOf("msie 6") !== -1) { 26558 zws = ""; //IE6 doesn"t support zws 26559 } 26560 if (ua.indexOf("opera") !== -1 && ua.indexOf("version/10.00") !== -1) { 26561 zws = ""; //opera 10 on XP doesn"t support zws 26562 } 26563 return zws; 26564 }()); 26565 26566 /** 26567 * @method Hyphenator~onBeforeWordHyphenation 26568 * @desc 26569 * This method is called just before a word is hyphenated. 26570 * It is called with two parameters: the word and its language. 26571 * The method must return a string (aka the word). 26572 * @see {@link Hyphenator.config} 26573 * @access private 26574 * @param {string} word 26575 * @param {string} lang 26576 * @return {string} The word that goes into hyphenation 26577 */ 26578 var onBeforeWordHyphenation = function (word) { 26579 return word; 26580 }; 26581 26582 /** 26583 * @method Hyphenator~onAfterWordHyphenation
26584 * @desc 26585 * This method is called for each word after it is hyphenated. 26586 * Takes the word as a first parameter and its language as a second parameter. 26587 * Returns a string that will replace the word that has been hyphenated. 26588 * @see {@link Hyphenator.config} 26589 * @access private 26590 * @param {string} word 26591 * @param {string} lang 26592 * @return {string} The word that goes into hyphenation 26593 */ 26594 var onAfterWordHyphenation = function (word) { 26595 return word; 26596 }; 26597 26598 /** 26599 * @method Hyphenator~onHyphenationDone 26600 * @desc 26601 * A method to be called, when the last element has been hyphenated. 26602 * If there are frames the method is called for each frame. 26603 * Therefore the location.href of the contextWindow calling this method is given as a parameter 26604 * @see {@link Hyphenator.config} 26605 * @param {string} context 26606 * @access private 26607 */ 26608 var onHyphenationDone = function (context) { 26609 return context; 26610 }; 26611 26612 /** 26613 * @name Hyphenator~selectorFunction 26614 * @desc 26615 * A function set by the user that has to return a HTMLNodeList or array of Elements to be hyphenated. 26616 * By default this is set to false so we can check if a selectorFunction is set⦠26617 * @see {@link Hyphenator.config} 26618 * @see {@link Hyphenator~mySelectorFunction} 26619 * @default false 26620 * @type {function|boolean} 26621 * @access private 26622 */ 26623 var selectorFunction = false; 26624 26625 /** 26626 * @name Hyphenator~flattenNodeList 26627 * @desc 26628 * Takes a nodeList and returns an array with all elements that are not contained by another element in the nodeList 26629 * By using this function the elements returned by selectElements can be "flattened". 26630 * @see {@link Hyphenator~selectElements} 26631 * @param {nodeList} nl 26632 * @return {Array} Array of "parent"-elements 26633 * @access private 26634 */ 26635 function flattenNodeList(nl) { 26636 var parentElements = [], 26637 i = 1, 26638 j = 0, 26639 isParent = true; 26640 26641 parentElements.push(nl[0]); //add the first item, since this is always an parent 26642 26643 while (i < nl.length) { //cycle through nodeList 26644 while (j < parentElements.length) { //cycle through parentElements 26645 if (parentElements[j].contains(nl[i])) { 26646 isParent = false; 26647 break; 26648 } 26649 j += 1; 26650 } 26651 if (isParent) { 26652 parentElements.push(nl[i]); 26653 } 26654 isParent = true; 26655 i += 1; 26656 } 26657 26658 return parentElements; 26659 } 26660 26661 /** 26662 * @method Hyphenator~mySelectorFunction 26663 * @desc 26664 * A function that returns a HTMLNodeList or array of Elements to be hyphenated. 26665 * By default it uses the classname ("hyphenate") to select the elements. 26666 * @access private 26667 */ 26668 function mySelectorFunction(hyphenateClass) { 26669 var tmp, 26670 el = [], 26671 i = 0; 26672 if (window.document.getElementsByClassName) { 26673 el = contextWindow.document.getElementsByClassName(hyphenateClass); 26674 } else if (window.document.querySelectorAll) { 26675 el = contextWindow.document.querySelectorAll("." + hyphenateClass); 26676 } else { 26677 tmp = contextWindow.document.getElementsByTagName("*"); 26678 while (i < tmp.length) {
26679 if (tmp[i].className.indexOf(hyphenateClass) !== -1 && tmp[i].className.indexOf(dontHyphenateClass) === -1) { 26680 el.push(tmp[i]); 26681 } 26682 i += 1; 26683 } 26684 } 26685 return el; 26686 } 26687 26688 /** 26689 * @method Hyphenator~selectElements 26690 * @desc 26691 * A function that uses either selectorFunction set by the user 26692 * or the default mySelectorFunction. 26693 * @access private 26694 */ 26695 function selectElements() { 26696 var elems; 26697 if (selectorFunction) { 26698 elems = selectorFunction(); 26699 } else { 26700 elems = mySelectorFunction(hyphenateClass); 26701 } 26702 if (elems.length !== 0) { 26703 elems = flattenNodeList(elems); 26704 } 26705 return elems; 26706 } 26707 26708 /** 26709 * @member {string} Hyphenator~intermediateState 26710 * @desc 26711 * The visibility of elements while they are hyphenated: 26712 * "visible": unhyphenated text is visible and then redrawn when hyphenated. 26713 * "hidden": unhyphenated text is made invisible as soon as possible and made visible after hyphenation. 26714 * @default "hidden" 26715 * @see {@link Hyphenator.config} 26716 * @access private 26717 */ 26718 var intermediateState = "hidden"; 26719 26720 /** 26721 * @member {string} Hyphenator~unhide 26722 * @desc 26723 * How hidden elements unhide: either simultaneous (default: "wait") or progressively. 26724 * "wait" makes Hyphenator.js to wait until all elements are hyphenated (one redraw) 26725 * With "progressive" Hyphenator.js unhides elements as soon as they are hyphenated. 26726 * @see {@link Hyphenator.config} 26727 * @access private 26728 */ 26729 var unhide = "wait"; 26730 26731 /** 26732 * @member {Array.<Hyphenator~CSSEdit>} Hyphenator~CSSEditors 26733 * @desc A container array that holds CSSEdit classes 26734 * For each window object one CSSEdit class is inserted 26735 * @access private 26736 */ 26737 var CSSEditors = []; 26738 26739 /** 26740 * @constructor Hyphenator~CSSEdit 26741 * @desc 26742 * This class handles access and editing of StyleSheets. 26743 * Thanks to this styles (e.g. hiding and unhiding elements upon hyphenation) 26744 * can be changed in one place instead for each element. 26745 * @access private 26746 */ 26747 function makeCSSEdit(w) { 26748 w = w || window; 26749 var doc = w.document, 26750 /** 26751 * @member {Object} Hyphenator~CSSEdit~sheet 26752 * @desc 26753 * A StyleSheet, where Hyphenator can write to. 26754 * If no StyleSheet can be found, lets create one. 26755 * @access private 26756 */ 26757 sheet = (function () { 26758 var i = 0, 26759 l = doc.styleSheets.length, 26760 s, 26761 element, 26762 r = false; 26763 while (i < l) { 26764 s = doc.styleSheets[i]; 26765 try { 26766 if (!!s.cssRules) { 26767 r = s; 26768 break; 26769 } 26770 } catch (ignore) {} 26771 i += 1; 26772 } 26773 if (r === false) { 26774 element = doc.createElement("style"); 26775 element.type = "text/css"; 26776 doc.getElementsByTagName("head")[0].appendChild(element); 26777 r = doc.styleSheets[doc.styleSheets.length - 1]; 26778 } 26779 return r; 26780 }()), 26781 26782 /** 26783 * @typedef {Object} Hyphenator~CSSEdit~changes 26784 * @property {Object} sheet - The StyleSheet where the change was made 26785 * @property {number} index - The index of the changed rule 26786 */ 26787 26788 /** 26789 * @member {Array.<changes>} Hyphenator~CSSEdit~changes 26790 * @desc 26791 * Sets a CSS rule for a specified selector 26792 * @access private 26793 */ 26794 changes = [], 26795 26796 /** 26797 * @typedef Hyphenator~CSSEdit~rule 26798 * @property {number} index - The index of the rule 26799 * @property {Object} rule - The style rule 26800 */ 26801 /** 26802 * @method Hyphenator~CSSEdit~findRule
26803 * @desc 26804 * Searches the StyleSheets for a given selector and returns an object containing the rule. 26805 * If nothing can be found, false is returned. 26806 * @param {string} sel 26807 * @return {Hyphenator~CSSEdit~rule|false} 26808 * @access private 26809 */ 26810 findRule = function (sel) { 26811 var s, 26812 rule, 26813 sheets = w.document.styleSheets, 26814 rules, 26815 i = 0, 26816 j = 0, 26817 r = false; 26818 while (i < sheets.length) { 26819 s = sheets[i]; 26820 try { //FF has issues here with external CSS (s.o.p) 26821 if (!!s.cssRules) { 26822 rules = s.cssRules; 26823 } else if (!!s.rules) { 26824 // IE < 9 26825 rules = s.rules; 26826 } 26827 } catch (ignore) {} 26828 if (!!rules && !!rules.length) { 26829 while (j < rules.length) { 26830 rule = rules[j]; 26831 if (rule.selectorText === sel) { 26832 r = { 26833 index: j, 26834 rule: rule 26835 }; 26836 } 26837 j += 1; 26838 } 26839 } 26840 i += 1; 26841 } 26842 return r; 26843 }, 26844 /** 26845 * @method Hyphenator~CSSEdit~addRule 26846 * @desc 26847 * Adds a rule to the {@link Hyphenator~CSSEdit~sheet} 26848 * @param {string} sel - The selector to be added 26849 * @param {string} rulesStr - The rules for the specified selector 26850 * @return {number} index of the new rule 26851 * @access private 26852 */ 26853 addRule = function (sel, rulesStr) { 26854 var i, r; 26855 if (!!sheet.insertRule) { 26856 if (!!sheet.cssRules) { 26857 i = sheet.cssRules.length; 26858 } else { 26859 i = 0; 26860 } 26861 r = sheet.insertRule(sel + "{" + rulesStr + "}", i); 26862 } else if (!!sheet.addRule) { 26863 // IE < 9 26864 if (!!sheet.rules) { 26865 i = sheet.rules.length; 26866 } else { 26867 i = 0; 26868 } 26869 sheet.addRule(sel, rulesStr, i); 26870 r = i; 26871 } 26872 return r; 26873 }, 26874 /** 26875 * @method Hyphenator~CSSEdit~removeRule 26876 * @desc 26877 * Removes a rule with the specified index from the specified sheet 26878 * @param {Object} sheet - The style sheet 26879 * @param {number} index - the index of the rule 26880 * @access private 26881 */ 26882 removeRule = function (sheet, index) { 26883 if (sheet.deleteRule) { 26884 sheet.deleteRule(index); 26885 } else { 26886 // IE < 9 26887 sheet.removeRule(index); 26888 } 26889 }; 26890 26891 return { 26892 /** 26893 * @method Hyphenator~CSSEdit.setRule 26894 * @desc 26895 * Sets a CSS rule for a specified selector 26896 * @access public 26897 * @param {string} sel - Selector 26898 * @param {string} rulesString - CSS-Rules 26899 */ 26900 setRule: function (sel, rulesString) { 26901 var i, existingRule, cssText; 26902 existingRule = findRule(sel); 26903 if (!!existingRule) { 26904 if (!!existingRule.rule.cssText) { 26905 cssText = existingRule.rule.cssText; 26906 } else { 26907 // IE < 9 26908 cssText = existingRule.rule.style.cssText.toLowerCase(); 26909 } 26910 if (cssText !== sel + " { " + rulesString + " }") { 26911 //cssText of the found rule is not uniquely selector + rulesString, 26912 if (cssText.indexOf(rulesString) !== -1) { 26913 //maybe there are other rules or IE < 9 26914 //clear existing def 26915 existingRule.rule.style.visibility = ""; 26916 } 26917 //add rule and register for later removal 26918 i = addRule(sel, rulesString); 26919 changes.push({sheet: sheet, index: i}); 26920 } 26921 } else { 26922 i = addRule(sel, rulesString); 26923 changes.push({sheet: sheet, index: i}); 26924 } 26925 }, 26926 /** 26927 * @method Hyphenator~CSSEdit.clearChanges
26928 * @desc 26929 * Removes all changes Hyphenator has made from the StyleSheets 26930 * @access public 26931 */ 26932 clearChanges: function () { 26933 var change = changes.pop(); 26934 while (!!change) { 26935 removeRule(change.sheet, change.index); 26936 change = changes.pop(); 26937 } 26938 } 26939 }; 26940 } 26941 26942 /** 26943 * @member {string} Hyphenator~hyphen 26944 * @desc 26945 * A string containing the character for in-word-hyphenation 26946 * @default the soft hyphen 26947 * @access private 26948 * @see {@link Hyphenator.config} 26949 */ 26950 var hyphen = String.fromCharCode(173); 26951 26952 /** 26953 * @member {string} Hyphenator~urlhyphen 26954 * @desc 26955 * A string containing the character for url/mail-hyphenation 26956 * @default the zero width space 26957 * @access private 26958 * @see {@link Hyphenator.config} 26959 * @see {@link Hyphenator~zeroWidthSpace} 26960 */ 26961 var urlhyphen = zeroWidthSpace; 26962 26963 /** 26964 * @method Hyphenator~hyphenateURL 26965 * @desc 26966 * Puts {@link Hyphenator~urlhyphen} (default: zero width space) after each no-alphanumeric char that my be in a URL. 26967 * @param {string} url to hyphenate 26968 * @returns string the hyphenated URL 26969 * @access public 26970 */ 26971 function hyphenateURL(url) { 26972 var tmp = url.replace(/([:\/.?#&\-_,;!@]+)/gi, "$&" + urlhyphen), 26973 parts = tmp.split(urlhyphen), 26974 i = 0; 26975 while (i < parts.length) { 26976 if (parts[i].length > (2 * min)) { 26977 parts[i] = parts[i].replace(/(\w{3})(\w)/gi, "$1" + urlhyphen + "$2"); 26978 } 26979 i += 1; 26980 } 26981 if (parts[parts.length - 1] === "") { 26982 parts.pop(); 26983 } 26984 return parts.join(urlhyphen); 26985 } 26986 26987 /** 26988 * @member {boolean} Hyphenator~safeCopy 26989 * @desc 26990 * Defines wether work-around for copy issues is active or not 26991 * @default true 26992 * @access private 26993 * @see {@link Hyphenator.config} 26994 * @see {@link Hyphenator~registerOnCopy} 26995 */ 26996 var safeCopy = true; 26997 26998 /** 26999 * @method Hyphenator~zeroTimeOut 27000 * @desc 27001 * defer execution of a function on the call stack 27002 * Analog to window.setTimeout(fn, 0) but without a clamped delay if postMessage is supported 27003 * @access private 27004 * @see {@link http://dbaron.org/log/20100309-faster-timeouts} 27005 */ 27006 var zeroTimeOut = (function () { 27007 if (window.postMessage && window.addEventListener) { 27008 return (function () { 27009 var timeouts = [], 27010 msg = "Hyphenator_zeroTimeOut_message", 27011 setZeroTimeOut = function (fn) { 27012 timeouts.push(fn); 27013 window.postMessage(msg, "*"); 27014 }, 27015 handleMessage = function (event) { 27016 if (event.source === window && event.data === msg) { 27017 event.stopPropagation(); 27018 if (timeouts.length > 0) { 27019 //var efn = timeouts.shift(); 27020 //efn(); 27021 timeouts.shift()(); 27022 } 27023 } 27024 }; 27025 window.addEventListener("message", handleMessage, true); 27026 return setZeroTimeOut; 27027 }()); 27028 } 27029 return function (fn) { 27030 window.setTimeout(fn, 0); 27031 }; 27032 }()); 27033 27034 /** 27035 * @member {Object} Hyphenator~hyphRunFor 27036 * @desc 27037 * stores location.href for documents where run() has been executed 27038 * to warn when Hyphenator.run() executed multiple times 27039 * @access private 27040 * @see {@link Hyphenator~runWhenLoaded} 27041 */ 27042 var hyphRunFor = {}; 27043 27044 /** 27045 * @method Hyphenator~removeHyphenationFromElement 27046 * @desc 27047 * Removes all hyphens from the element. If there are other elements, the function is 27048 * called recursively. 27049 * Removing hyphens is usefull if you like to copy text. Some browsers are buggy when the copy hyphenated texts. 27050 * @param {Object} el The element where to remove hyphenation. 27051 * @access public 27052 */ 27053 function removeHyphenationFromElement(el) { 27054 var h, u, i = 0, n; 27055 //escape hyphen 27056 if (".\\+*?[^]$(){}=!<>|:-".indexOf(hyphen) !== -1) { 27057 h = "\\" + hyphen; 27058 } else { 27059 h = hyphen; 27060 } 27061 //escape hyphen 27062 if (".\\+*?[^]$(){}=!<>|:-".indexOf(urlhyphen) !== -1) { 27063 u = "\\" + urlhyphen; 27064 } else { 27065 u = urlhyphen; 27066 } 27067 n = el.childNodes[i]; 27068 while (!!n) { 27069 if (n.nodeType === 3) { 27070 n.data = n.data.replace(new RegExp(h, "g"), ""); 27071 n.data = n.data.replace(new RegExp(u, "g"), ""); 27072 } else if (n.nodeType === 1) { 27073 removeHyphenationFromElement(n); 27074 } 27075 i += 1; 27076 n = el.childNodes[i]; 27077 } 27078 } 27079 27080 /** 27081 * @member {Object} Hyphenator~hyphRunFor
27082 * @desc 27083 * stores location.href for documents where run() has been executed 27084 * to warn when Hyphenator.run() executed multiple times 27085 * @access private 27086 * @see {@link Hyphenator~runWhenLoaded} 27087 */ 27088 var copy = (function () { 27089 var factory = function () { 27090 var registeredElements = []; 27091 var oncopyHandler = function (e) { 27092 e = e || window.event; 27093 var shadow, 27094 selection, 27095 range, 27096 rangeShadow, 27097 restore, 27098 target = e.target || e.srcElement, 27099 currDoc = target.ownerDocument, 27100 bdy = currDoc.getElementsByTagName("body")[0], 27101 targetWindow = currDoc.defaultView || currDoc.parentWindow; 27102 if (target.tagName && dontHyphenate[target.tagName.toLowerCase()]) { 27103 //Safari needs this 27104 return; 27105 } 27106 //create a hidden shadow element 27107 shadow = currDoc.createElement("div"); 27108 shadow.style.color = window.getComputedStyle 27109 ? targetWindow.getComputedStyle(bdy, null).backgroundColor 27110 : "#FFFFFF"; 27111 shadow.style.fontSize = "0px"; 27112 bdy.appendChild(shadow); 27113 if (!!window.getSelection) { 27114 //FF3, Webkit, IE9 27115 selection = targetWindow.getSelection(); 27116 range = selection.getRangeAt(0); 27117 shadow.appendChild(range.cloneContents()); 27118 removeHyphenationFromElement(shadow); 27119 selection.selectAllChildren(shadow); 27120 restore = function () { 27121 shadow.parentNode.removeChild(shadow); 27122 selection.removeAllRanges(); //IE9 needs that 27123 selection.addRange(range); 27124 }; 27125 } else { 27126 // IE<9 27127 selection = targetWindow.document.selection; 27128 range = selection.createRange(); 27129 shadow.innerHTML = range.htmlText; 27130 removeHyphenationFromElement(shadow); 27131 rangeShadow = bdy.createTextRange(); 27132 rangeShadow.moveToElementText(shadow); 27133 rangeShadow.select(); 27134 restore = function () { 27135 shadow.parentNode.removeChild(shadow); 27136 if (range.text !== "") { 27137 range.select(); 27138 } 27139 }; 27140 } 27141 zeroTimeOut(restore); 27142 }; 27143 var removeOnCopy = function () { 27144 var i = registeredElements.length - 1; 27145 while (i >= 0) { 27146 if (window.removeEventListener) { 27147 registeredElements[i].removeEventListener("copy", oncopyHandler, true); 27148 } else { 27149 registeredElements[i].detachEvent("oncopy", oncopyHandler); 27150 } 27151 i -= 1; 27152 } 27153 }; 27154 var reactivateOnCopy = function () { 27155 var i = registeredElements.length - 1; 27156 while (i >= 0) { 27157 if (window.addEventListener) { 27158 registeredElements[i].addEventListener("copy", oncopyHandler, true); 27159 } else { 27160 registeredElements[i].attachEvent("oncopy", oncopyHandler); 27161 } 27162 i -= 1; 27163 } 27164 }; 27165 var registerOnCopy = function (el) { 27166 registeredElements.push(el); 27167 if (window.addEventListener) { 27168 el.addEventListener("copy", oncopyHandler, true); 27169 } else { 27170 el.attachEvent("oncopy", oncopyHandler); 27171 } 27172 }; 27173 return { 27174 oncopyHandler: oncopyHandler, 27175 removeOnCopy: removeOnCopy, 27176 registerOnCopy: registerOnCopy, 27177 reactivateOnCopy: reactivateOnCopy 27178 }; 27179 }; 27180 return (safeCopy 27181 ? factory() 27182 : false); 27183 }()); 27184 27185 /** 27186 * @method Hyphenator~runWhenLoaded
27187 * @desc 27188 * A crossbrowser solution for the DOMContentLoaded-Event based on 27189 * <a href = "http://jquery.com/">jQuery</a> 27190 * I added some functionality: e.g. support for frames and iframes⦠27191 * @param {Object} w the window-object 27192 * @param {function()} f the function to call when the document is ready 27193 * @access private 27194 */ 27195 function runWhenLoaded(w, f) { 27196 var toplevel, 27197 add = window.document.addEventListener 27198 ? "addEventListener" 27199 : "attachEvent", 27200 rem = window.document.addEventListener 27201 ? "removeEventListener" 27202 : "detachEvent", 27203 pre = window.document.addEventListener 27204 ? "" 27205 : "on"; 27206 27207 function init(context) { 27208 if (hyphRunFor[context.location.href]) { 27209 onWarning(new Error("Warning: multiple execution of Hyphenator.run() â This may slow down the script!")); 27210 } 27211 contextWindow = context || window; 27212 f(); 27213 hyphRunFor[contextWindow.location.href] = true; 27214 } 27215 27216 function doScrollCheck() { 27217 try { 27218 // If IE is used, use the trick by Diego Perini 27219 // http://javascript.nwbox.com/IEContentLoaded/ 27220 w.document.documentElement.doScroll("left"); 27221 } catch (ignore) { 27222 window.setTimeout(doScrollCheck, 1); 27223 return; 27224 } 27225 //maybe modern IE fired DOMContentLoaded 27226 if (!hyphRunFor[w.location.href]) { 27227 documentLoaded = true; 27228 init(w); 27229 } 27230 } 27231 27232 function doOnEvent(e) { 27233 var i = 0, 27234 fl, 27235 haveAccess; 27236 if (!!e && e.type === "readystatechange" && w.document.readyState !== "interactive" && w.document.readyState !== "complete") { 27237 return; 27238 } 27239 27240 //DOM is ready/interactive, but frames may not be loaded yet! 27241 //cleanup events 27242 w.document[rem](pre + "DOMContentLoaded", doOnEvent, false); 27243 w.document[rem](pre + "readystatechange", doOnEvent, false); 27244 27245 //check frames 27246 fl = w.frames.length; 27247 if (fl === 0 || !doFrames) { 27248 //there are no frames! 27249 //cleanup events 27250 w[rem](pre + "load", doOnEvent, false); 27251 documentLoaded = true; 27252 init(w); 27253 } else if (doFrames && fl > 0) { 27254 //we have frames, so wait for onload and then initiate runWhenLoaded recursevly for each frame: 27255 if (!!e && e.type === "load") { 27256 //cleanup events 27257 w[rem](pre + "load", doOnEvent, false); 27258 while (i < fl) { 27259 haveAccess = undefined; 27260 //try catch isn"t enough for webkit 27261 try { 27262 //opera throws only on document.toString-access 27263 haveAccess = w.frames[i].document.toString(); 27264 } catch (ignore) { 27265 haveAccess = undefined; 27266 } 27267 if (!!haveAccess) { 27268 runWhenLoaded(w.frames[i], f); 27269 } 27270 i += 1; 27271 } 27272 init(w); 27273 } 27274 } 27275 } 27276 27277 if (documentLoaded || w.document.readyState === "complete") { 27278 //Hyphenator has run already (documentLoaded is true) or 27279 //it has been loaded after onLoad 27280 documentLoaded = true; 27281 doOnEvent({type: "load"}); 27282 } else { 27283 //register events 27284 w.document[add](pre + "DOMContentLoaded", doOnEvent, false); 27285 w.document[add](pre + "readystatechange", doOnEvent, false); 27286 w[add](pre + "load", doOnEvent, false); 27287 toplevel = false; 27288 try { 27289 toplevel = !window.frameElement; 27290 } catch (ignore) {} 27291 if (toplevel && w.document.documentElement.doScroll) { 27292 doScrollCheck(); //calls init() 27293 } 27294 } 27295 } 27296 27297 /** 27298 * @method Hyphenator~getLang
27299 * @desc 27300 * Gets the language of an element. If no language is set, it may use the {@link Hyphenator~mainLanguage}. 27301 * @param {Object} el The first parameter is an DOM-Element-Object 27302 * @param {boolean} fallback The second parameter is a boolean to tell if the function should return the {@link Hyphenator~mainLanguage} 27303 * if there"s no language found for the element. 27304 * @return {string} The language of the element 27305 * @access private 27306 */ 27307 function getLang(el, fallback) { 27308 try { 27309 return !!el.getAttribute("lang") 27310 ? el.getAttribute("lang").toLowerCase() 27311 : !!el.getAttribute("xml:lang") 27312 ? el.getAttribute("xml:lang").toLowerCase() 27313 : el.tagName.toLowerCase() !== "html" 27314 ? getLang(el.parentNode, fallback) 27315 : fallback 27316 ? mainLanguage 27317 : null; 27318 } catch (ignore) { 27319 return fallback 27320 ? mainLanguage 27321 : null; 27322 } 27323 } 27324 27325 /** 27326 * @method Hyphenator~autoSetMainLanguage 27327 * @desc 27328 * Retrieves the language of the document from the DOM and sets the lang attribute of the html-tag. 27329 * The function looks in the following places: 27330 * <ul> 27331 * <li>lang-attribute in the html-tag</li> 27332 * <li><meta http-equiv = "content-language" content = "xy" /></li> 27333 * <li><meta name = "DC.Language" content = "xy" /></li> 27334 * <li><meta name = "language" content = "xy" /></li> 27335 * </li> 27336 * If nothing can be found a prompt using {@link Hyphenator~languageHint} and a prompt-string is displayed. 27337 * If the retrieved language is in the object {@link Hyphenator~supportedLangs} it is copied to {@link Hyphenator~mainLanguage} 27338 * @access private 27339 */ 27340 function autoSetMainLanguage(w) { 27341 w = w || contextWindow; 27342 var el = w.document.getElementsByTagName("html")[0], 27343 m = w.document.getElementsByTagName("meta"), 27344 i = 0, 27345 getLangFromUser = function () { 27346 var text = ""; 27347 var ul = ""; 27348 var languageHint = (function () { 27349 var r = ""; 27350 forEachKey(supportedLangs, function (k) { 27351 r += k + ", "; 27352 }); 27353 r = r.substring(0, r.length - 2); 27354 return r; 27355 }()); 27356 ul = window.navigator.language || window.navigator.userLanguage; 27357 ul = ul.substring(0, 2); 27358 if (!!supportedLangs[ul] && supportedLangs[ul].prompt !== "") { 27359 text = supportedLangs[ul].prompt; 27360 } else { 27361 text = supportedLangs.en.prompt; 27362 } 27363 text += " (ISO 639-1)\n\n" + languageHint; 27364 return window.prompt(window.unescape(text), ul).toLowerCase(); 27365 }; 27366 mainLanguage = getLang(el, false); 27367 if (!mainLanguage) { 27368 while (i < m.length) { 27369 //<meta http-equiv = "content-language" content="xy"> 27370 if (!!m[i].getAttribute("http-equiv") && (m[i].getAttribute("http-equiv").toLowerCase() === "content-language")) { 27371 mainLanguage = m[i].getAttribute("content").toLowerCase(); 27372 } 27373 //<meta name = "DC.Language" content="xy"> 27374 if (!!m[i].getAttribute("name") && (m[i].getAttribute("name").toLowerCase() === "dc.language")) { 27375 mainLanguage = m[i].getAttribute("content").toLowerCase(); 27376 } 27377 //<meta name = "language" content = "xy"> 27378 if (!!m[i].getAttribute("name") && (m[i].getAttribute("name").toLowerCase() === "language")) { 27379 mainLanguage = m[i].getAttribute("content").toLowerCase(); 27380 } 27381 i += 1; 27382 } 27383 } 27384 //get lang for frame from enclosing document 27385 if (!mainLanguage && doFrames && (!!contextWindow.frameElement)) { 27386 autoSetMainLanguage(window.parent); 27387 } 27388 //fallback to defaultLang if set 27389 if (!mainLanguage && defaultLanguage !== "") { 27390 mainLanguage = defaultLanguage; 27391 } 27392 //ask user for lang 27393 if (!mainLanguage) { 27394 mainLanguage = getLangFromUser(); 27395 } 27396 el.lang = mainLanguage; 27397 } 27398 27399 /** 27400 * @method Hyphenator~gatherDocumentInfos
27401 * @desc 27402 * This method runs through the DOM and executes the process()-function on: 27403 * - every node returned by the {@link Hyphenator~selectorFunction}. 27404 * @access private 27405 */ 27406 function gatherDocumentInfos() { 27407 var elToProcess, 27408 urlhyphenEls, 27409 tmp, 27410 i = 0; 27411 /** 27412 * @method Hyphenator~gatherDocumentInfos 27413 * @desc 27414 * This method copies the element to the elements-variable, sets its visibility 27415 * to intermediateState, retrieves its language and recursivly descends the DOM-tree until 27416 * the child-Nodes aren"t of type 1 27417 * @param {Object} el a DOM element 27418 * @param {string} plang the language of the parent element 27419 * @param {boolean} isChild true, if the parent of el has been processed 27420 */ 27421 function process(el, pLang, isChild) { 27422 var n, 27423 j = 0, 27424 hyphenate = true, 27425 eLang, 27426 useCSS3 = function () { 27427 css3hyphenateClassHandle = makeCSSEdit(contextWindow); 27428 css3hyphenateClassHandle.setRule("." + css3hyphenateClass, css3_h9n.property + ": auto;"); 27429 css3hyphenateClassHandle.setRule("." + dontHyphenateClass, css3_h9n.property + ": manual;"); 27430 if ((eLang !== pLang) && css3_h9n.property.indexOf("webkit") !== -1) { 27431 css3hyphenateClassHandle.setRule("." + css3hyphenateClass, "-webkit-locale : " + eLang + ";"); 27432 } 27433 el.className = el.className + " " + css3hyphenateClass; 27434 }, 27435 useHyphenator = function () { 27436 //quick fix for test111.html 27437 //better: weight elements 27438 if (isBookmarklet && eLang !== mainLanguage) { 27439 return; 27440 } 27441 if (supportedLangs.hasOwnProperty(eLang)) { 27442 docLanguages[eLang] = true; 27443 } else { 27444 if (supportedLangs.hasOwnProperty(eLang.split("-")[0])) { //try subtag 27445 eLang = eLang.split("-")[0]; 27446 docLanguages[eLang] = true; 27447 } else if (!isBookmarklet) { 27448 hyphenate = false; 27449 onError(new Error("Language \"" + eLang + "\" is not yet supported.")); 27450 } 27451 } 27452 if (hyphenate) { 27453 if (intermediateState === "hidden") { 27454 el.className = el.className + " " + hideClass; 27455 } 27456 elements.add(el, eLang); 27457 } 27458 }; 27459 isChild = isChild || false; 27460 if (el.lang && typeof el.lang === "string") { 27461 eLang = el.lang.toLowerCase(); //copy attribute-lang to internal eLang 27462 } else if (!!pLang && pLang !== "") { 27463 eLang = pLang.toLowerCase(); 27464 } else { 27465 eLang = getLang(el, true); 27466 } 27467 27468 if (!isChild) { 27469 if (css3 && css3_h9n.support && !!css3_h9n.checkLangSupport(eLang)) { 27470 useCSS3(); 27471 } else { 27472 if (safeCopy) { 27473 copy.registerOnCopy(el); 27474 } 27475 useHyphenator(); 27476 } 27477 } else { 27478 if (eLang !== pLang) { 27479 if (css3 && css3_h9n.support && !!css3_h9n.checkLangSupport(eLang)) { 27480 useCSS3(); 27481 } else { 27482 useHyphenator(); 27483 } 27484 } else { 27485 if (!css3 || !css3_h9n.support || !css3_h9n.checkLangSupport(eLang)) { 27486 useHyphenator(); 27487 } // else do nothing 27488 } 27489 } 27490 n = el.childNodes[j]; 27491 while (!!n) { 27492 if ( 27493 n.nodeType === 1 && !dontHyphenate[n.nodeName.toLowerCase()] &&
27494 n.className.indexOf(dontHyphenateClass) === -1 && 27495 n.className.indexOf(urlHyphenateClass) === -1 && !elToProcess[n] 27496 ) { 27497 process(n, eLang, true); 27498 } 27499 j += 1; 27500 n = el.childNodes[j]; 27501 } 27502 } 27503 function processUrlStyled(el) { 27504 var n, j = 0; 27505 27506 n = el.childNodes[j]; 27507 while (!!n) { 27508 if ( 27509 n.nodeType === 1 && !dontHyphenate[n.nodeName.toLowerCase()] && 27510 n.className.indexOf(dontHyphenateClass) === -1 && 27511 n.className.indexOf(hyphenateClass) === -1 && !urlhyphenEls[n] 27512 ) { 27513 processUrlStyled(n); 27514 } else if (n.nodeType === 3) { 27515 if (safeCopy) { 27516 copy.registerOnCopy(n.parentNode); 27517 } 27518 //n.data = hyphenateURL(n.data); 27519 elements.add(n.parentNode, "urlstyled"); 27520 } 27521 j += 1; 27522 n = el.childNodes[j]; 27523 } 27524 } 27525 27526 if (css3) { 27527 css3_h9n = css3_gethsupport(); 27528 } 27529 if (isBookmarklet) { 27530 elToProcess = contextWindow.document.getElementsByTagName("body")[0]; 27531 process(elToProcess, mainLanguage, false); 27532 } else { 27533 if (!css3 && intermediateState === "hidden") { 27534 CSSEditors.push(makeCSSEdit(contextWindow)); 27535 CSSEditors[CSSEditors.length - 1].setRule("." + hyphenateClass, "visibility: hidden;"); 27536 CSSEditors[CSSEditors.length - 1].setRule("." + hideClass, "visibility: hidden;"); 27537 CSSEditors[CSSEditors.length - 1].setRule("." + unhideClass, "visibility: visible;"); 27538 } 27539 elToProcess = selectElements(); 27540 tmp = elToProcess[i]; 27541 while (!!tmp) { 27542 process(tmp, "", false); 27543 i += 1; 27544 tmp = elToProcess[i]; 27545 } 27546 27547 urlhyphenEls = mySelectorFunction(urlHyphenateClass); 27548 i = 0; 27549 tmp = urlhyphenEls[i]; 27550 while (!!tmp) { 27551 processUrlStyled(tmp); 27552 i += 1; 27553 tmp = urlhyphenEls[i]; 27554 } 27555 } 27556 if (elements.counters[0] === 0) { 27557 //nothing to hyphenate or all hyphenated by css3 27558 i = 0; 27559 while (i < CSSEditors.length) { 27560 CSSEditors[i].clearChanges(); 27561 i += 1; 27562 } 27563 onHyphenationDone(contextWindow.location.href); 27564 } 27565 } 27566 27567 /** 27568 * @method Hyphenator~createCharMap 27569 * @desc 27570 * reads the charCodes from lo.characters and stores them in a bidi map: 27571 * charMap.int2code = [0: 97, //a 27572 * 1: 98, //b 27573 * 2: 99] //c etc. 27574 * charMap.code2int = {"97": 0, //a 27575 * "98": 1, //b 27576 * "99": 2} //c etc. 27577 * @access private 27578 * @param {Object} language object 27579 */ 27580 function makeCharMap() { 27581 var int2code = [], 27582 code2int = {}, 27583 add = function (newValue) { 27584 if (!code2int[newValue]) { 27585 int2code.push(newValue); 27586 code2int[newValue] = int2code.length - 1; 27587 } 27588 }; 27589 return { 27590 int2code: int2code, 27591 code2int: code2int, 27592 add: add 27593 }; 27594 } 27595 27596 /** 27597 * @constructor Hyphenator~ValueStore 27598 * @desc Storage-Object for storing hyphenation points (aka values) 27599 * @access private 27600 */ 27601 function makeValueStore(len) { 27602 var indexes = (function () { 27603 var arr; 27604 if (Object.prototype.hasOwnProperty.call(window, "Uint32Array")) { //IE<9 doesn"t have window.hasOwnProperty (host object) 27605 arr = new window.Uint32Array(3); 27606 arr[0] = 1; //start position of a value set 27607 arr[1] = 1; //next index 27608 arr[2] = 1; //last index with a significant value 27609 } else { 27610 arr = [1, 1, 1]; 27611 } 27612 return arr; 27613 }()), 27614 keys = (function () { 27615 var i, r; 27616 if (Object.prototype.hasOwnProperty.call(window, "Uint8Array")) { //IE<9 doesn"t have window.hasOwnProperty (host object) 27617 return new window.Uint8Array(len); 27618 } 27619 r = []; 27620 r.length = len; 27621 i = r.length - 1; 27622 while (i >= 0) { 27623 r[i] = 0; 27624 i -= 1; 27625 } 27626 return r; 27627 }()), 27628 add = function (p) { 27629 keys[indexes[1]] = p; 27630 indexes[2] = indexes[1]; 27631 indexes[1] += 1; 27632 }, 27633 add0 = function () { 27634 //just do a step, since array is initialized with zeroe
27634s 27635 indexes[1] += 1; 27636 }, 27637 finalize = function () { 27638 var start = indexes[0]; 27639 keys[indexes[2] + 1] = 255; //mark end of pattern 27640 indexes[0] = indexes[2] + 2; 27641 indexes[1] = indexes[0]; 27642 return start; 27643 }; 27644 return { 27645 keys: keys, 27646 add: add, 27647 add0: add0, 27648 finalize: finalize 27649 }; 27650 } 27651 27652 /** 27653 * @method Hyphenator~convertPatternsToArray 27654 * @desc 27655 * converts the patterns to a (typed, if possible) array as described by Liang: 27656 * 27657 * 1. Create the CharMap: an alphabet of used character codes mapped to an int (e.g. a: "97" -> 0) 27658 * This map is bidirectional: 27659 * charMap.code2int is an object with charCodes as keys and corresponging ints as values 27660 * charMao.int2code is an array of charCodes at int indizes 27661 * the length of charMao.int2code is equal the length of the alphabet 27662 * 27663 * 2. Create a ValueStore: (typed) array that holds "values", i.e. the digits extracted from the patterns 27664 * The first value set starts at index 1 (since the trie is initialized with zeroes, starting at 0 would create errors) 27665 * Each value set ends with a value of 255; trailing 0"s are not stored. So pattern values like e.g. "010200" will become [â¦,0,1,0,2,255,â¦] 27666 * The ValueStore-Object manages handling of indizes automatically. Use ValueStore.add(p) to add a running value. 27667 * Use ValueStore.finalize() when the last value of a pattern is added. It will add the final 255, prepare the valueStore for new values 27668 * and return the starting index of the pattern. 27669 * To prevent doubles we could temporarly store the values in a object {value: startIndex} and only add new values, 27670 * but this object deoptimizes very fast (new hidden map for each entry); here we gain speed and pay memory 27671 * 27672 * 3. Create and zero initialize a (typed) array to store the trie. The trie uses two slots for each entry/node: 27673 * i: a link to another position in the array or -1 if the pattern ends here or more rows have to be added. 27674 * i + 1: a link to a value in the ValueStore or 0 if there"s no value for the path to this node. 27675 * Although the array is one-dimensional it can be described as an array of "rows", 27676 * where each "row" is an array of length trieRowLength (see below). 27677 * The first entry of this "row" represents the first character of the alphabet, the second a possible link to value store, 27678 * the third represents the second character of the alphabet and so on⦠27679 * 27680 * 4. Initialize trieRowLength (length of the alphabet * 2) 27681 * 27682 * 5. Now we apply extract to each pattern collection (patterns of the same length are collected and concatenated to one string) 27683 * extract goes through these pattern collections char by char and adds them either to the ValueStore (if they are digits) or 27684 * to the trie (adding more "rows" if necessary, i.e. if the last link pointed to -1). 27685 * So the first "row" holds all starting characters, where the subsequent rows hold the characters that follow the 27686 * character that link to this row. Therefor the array is dense at the beginning and very sparse at the end. 27687 * 27688 * 27689 * @access private 27690 * @param {Object} language object 27691 */ 27692 function convertPatternsToArray(lo) { 27693 var trieNextEmptyRow = 0, 27694 i, 27695 charMapc2i, 27696 valueStore, 27697 indexedTrie, 27698 trieRowLength, 27699 27700 extract = function (patternSizeInt, patterns) { 27701 var charPos = 0, 27702 charCode = 0, 27703 mappedCharCode = 0, 27704 rowStart = 0, 27705 nextRowStart = 0, 27706 prevWasDigit = false; 27707 while (charPos < patterns.length) { 27708 charCode = patterns.charCodeAt(charPos); 27709 if ((charPos + 1) % patternSizeInt !== 0) { 27710 //more to comeâ¦
27711 if (charCode <= 57 && charCode >= 49) { 27712 //charCode is a digit 27713 valueStore.add(charCode - 48); 27714 prevWasDigit = true; 27715 } else { 27716 //charCode is alphabetical 27717 if (!prevWasDigit) { 27718 valueStore.add0(); 27719 } 27720 prevWasDigit = false; 27721 if (nextRowStart === -1) { 27722 nextRowStart = trieNextEmptyRow + trieRowLength; 27723 trieNextEmptyRow = nextRowStart; 27724 indexedTrie[rowStart + mappedCharCode * 2] = nextRowStart; 27725 } 27726 mappedCharCode = charMapc2i[charCode]; 27727 rowStart = nextRowStart; 27728 nextRowStart = indexedTrie[rowStart + mappedCharCode * 2]; 27729 if (nextRowStart === 0) { 27730 indexedTrie[rowStart + mappedCharCode * 2] = -1; 27731 nextRowStart = -1; 27732 } 27733 } 27734 } else { 27735 //last part of pattern
27736 if (charCode <= 57 && charCode >= 49) { 27737 //the last charCode is a digit 27738 valueStore.add(charCode - 48); 27739 indexedTrie[rowStart + mappedCharCode * 2 + 1] = valueStore.finalize(); 27740 } else { 27741 //the last charCode is alphabetical 27742 if (!prevWasDigit) { 27743 valueStore.add0(); 27744 } 27745 valueStore.add0(); 27746 if (nextRowStart === -1) { 27747 nextRowStart = trieNextEmptyRow + trieRowLength; 27748 trieNextEmptyRow = nextRowStart; 27749 indexedTrie[rowStart + mappedCharCode * 2] = nextRowStart; 27750 } 27751 mappedCharCode = charMapc2i[charCode]; 27752 rowStart = nextRowStart; 27753 if (indexedTrie[rowStart + mappedCharCode * 2] === 0) { 27754 indexedTrie[rowStart + mappedCharCode * 2] = -1; 27755 } 27756 indexedTrie[rowStart + mappedCharCode * 2 + 1] = valueStore.finalize(); 27757 } 27758 rowStart = 0; 27759 nextRowStart = 0; 27760 prevWasDigit = false; 27761 } 27762 charPos += 1; 27763 } 27764 };/*, 27765 prettyPrintIndexedTrie = function (rowLength) { 27766 var s = "0: ", 27767 idx; 27768 for (idx = 0; idx < indexedTrie.length; idx += 1) { 27769 s += indexedTrie[idx]; 27770 s += ","; 27771 if ((idx + 1) % rowLength === 0) { 27772 s += "\n" + (idx + 1) + ": "; 27773 } 27774 } 27775 console.log(s); 27776 };*/ 27777 27778 lo.charMap = makeCharMap(); 27779 i = 0; 27780 while (i < lo.patternChars.length) { 27781 lo.charMap.add(lo.patternChars.charCodeAt(i)); 27782 i += 1; 27783 } 27784 charMapc2i = lo.charMap.code2int; 27785 27786 valueStore = makeValueStore(lo.valueStoreLength); 27787 lo.valueStore = valueStore; 27788 27789 if (Object.prototype.hasOwnProperty.call(window, "Int32Array")) { //IE<9 doesn"t have window.hasOwnProperty (host object) 27790 lo.indexedTrie = new window.Int32Array(lo.patternArrayLength * 2); 27791 } else { 27792 lo.indexedTrie = []; 27793 lo.indexedTrie.length = lo.patternArrayLength * 2; 27794 i = lo.indexedTrie.length - 1; 27795 while (i >= 0) { 27796 lo.indexedTrie[i] = 0; 27797 i -= 1; 27798 } 27799 } 27800 indexedTrie = lo.indexedTrie; 27801 trieRowLength = lo.charMap.int2code.length * 2; 27802 27803 forEachKey(lo.patterns, function (i) { 27804 extract(parseInt(i, 10), lo.patterns[i]); 27805 }); 27806 //prettyPrintIndexedTrie(lo.charMap.int2code.length * 2); 27807 } 27808 27809 /** 27810 * @method Hyphenator~recreatePattern 27811 * @desc 27812 * Recreates the pattern for the reducedPatternSet 27813 * @param {string} pattern The pattern (chars) 27814 * @param {string} nodePoints The nodePoints (integers) 27815 * @access private 27816 * @return {string} The pattern (chars and numbers) 27817 */ 27818 function recreatePattern(pattern, nodePoints) { 27819 var r = [], 27820 c = pattern.split(""), 27821 i = 0; 27822 while (i <= c.length) { 27823 if (nodePoints[i] && nodePoints[i] !== 0) { 27824 r.push(nodePoints[i]); 27825 } 27826 if (c[i]) { 27827 r.push(c[i]); 27828 } 27829 i += 1; 27830 } 27831 return r.join(""); 27832 } 27833 27834 /** 27835 * @method Hyphenator~convertExceptionsToObject 27836 * @desc 27837 * Converts a list of comma seprated exceptions to an object: 27838 * "Fortran,Hy-phen-a-tion" -> {"Fortran":"Fortran","Hyphenation":"Hy-phen-a-tion"} 27839 * @access private 27840 * @param {string} exc a comma separated string of exceptions (without spaces) 27841 * @return {Object.<string, string>} 27842 */ 27843 function convertExceptionsToObject(exc) { 27844 var w = exc.split(", "), 27845 r = {}, 27846 i = 0, 27847 l = w.length, 27848 key; 27849 while (i < l) { 27850 key = w[i].replace(/-/g, ""); 27851 if (!r.hasOwnProperty(key)) { 27852 r[key] = w[i]; 27853 } 27854 i += 1; 27855 } 27856 return r; 27857 } 27858 27859 /** 27860 * @method Hyphenator~loadPatterns
27861 * @desc 27862 * Checks if the requested file is available in the network. 27863 * Adds a <script>-Tag to the DOM to load an externeal .js-file containing patterns and settings for the given language. 27864 * If the given language is not in the {@link Hyphenator~supportedLangs}-Object it returns. 27865 * One may ask why we are not using AJAX to load the patterns. The XMLHttpRequest-Object 27866 * has a same-origin-policy. This makes the Bookmarklet impossible. 27867 * @param {string} lang The language to load the patterns for 27868 * @access private 27869 * @see {@link Hyphenator~basePath} 27870 */ 27871 function loadPatterns(lang, cb) { 27872 var location, xhr, head, script, done = false; 27873 function getXHRforIElt6() { 27874 try { 27875 //IE>=5 27876 xhr = new window.ActiveXObject("Msxml2.XMLHTTP"); 27877 } catch (ignore) { 27878 xhr = null; 27879 } 27880 } 27881 function getXHRforIElt10() { 27882 try { 27883 //IE>=6 27884 xhr = new window.ActiveXObject("Microsoft.XMLHTTP"); 27885 } catch (ignore) { 27886 getXHRforIElt6(); 27887 } 27888 } 27889 if (supportedLangs.hasOwnProperty(lang) && !Hyphenator.languages[lang]) { 27890 location = basePath + "patterns/" + supportedLangs[lang].file; 27891 } else { 27892 return; 27893 } 27894 if (isLocal && !isBookmarklet) { 27895 //check if "location" is available: 27896 xhr = null; 27897 try { 27898 // Mozilla, Opera, Safari and Internet Explorer (ab v7) 27899 xhr = new window.XMLHttpRequest(); 27900 } catch (ignore) { 27901 getXHRforIElt10(); 27902 } 27903 27904 if (xhr) { 27905 xhr.open("HEAD", location, true); 27906 xhr.setRequestHeader("Cache-Control", "no-cache"); 27907 xhr.onreadystatechange = function () { 27908 if (xhr.readyState === 2) { 27909 if (xhr.status >= 400) { 27910 onError(new Error("Could not load\n" + location)); 27911 delete docLanguages[lang]; 27912 return; 27913 } 27914 xhr.abort(); 27915 } 27916 }; 27917 xhr.send(null); 27918 } 27919 } 27920 if (createElem) { 27921 head = window.document.getElementsByTagName("head").item(0); 27922 script = createElem("script", window); 27923 script.src = location; 27924 script.type = "text/javascript"; 27925 script.charset = "utf8"; 27926 script.onreadystatechange = function () { 27927 if (!done && (!script.readyState || script.readyState === "loaded" || script.readyState === "complete")) { 27928 done = true; 27929 27930 cb(); 27931 27932 // Handle memory leak in IE 27933 script.onreadystatechange = null; 27934 script.onload = null; 27935 if (head && script.parentNode) { 27936 head.removeChild(script); 27937 } 27938 } 27939 }; 27940 script.onload = script.onreadystatechange; 27941 head.appendChild(script); 27942 } 27943 } 27944 27945 /** 27946 * @method Hyphenator~createWordRegExp 27947 * @desc 27948 * build a regexp string for finding a word of a given languate 27949 * @access private 27950 * @param {string} lang The language 27951 * @return {string} 27952 */ 27953 function createWordRegExp(lang) { 27954 var lo = Hyphenator.languages[lang], 27955 wrd = ""; 27956 if (String.prototype.normalize) { 27957 wrd = "[\\w" + lo.specialChars + lo.specialChars.normalize("NFD") + hyphen + String.fromCharCode(8204) + "-]{" + min + ",}(?!:\\/\\/)"; 27958 } else { 27959 wrd = "[\\w" + lo.specialChars + hyphen + String.fromCharCode(8204) + "-]{" + min + ",}(?!:\\/\\/)"; 27960 } 27961 return wrd; 27962 } 27963 27964 /** 27965 * @method Hyphenator~prepareLanguagesObj 27966 * @desc 27967 * Adds some feature to the language object: 27968 * - cache 27969 * - exceptions 27970 * Converts the patterns to a trie using {@link Hyphenator~convertPatterns}
27970 27971 * @access private 27972 * @param {string} lang The language of the language object 27973 */ 27974 function prepareLanguagesObj(lang) { 27975 var lo = Hyphenator.languages[lang]; 27976 27977 if (!lo.prepared) { 27978 if (enableCache) { 27979 lo.cache = {}; 27980 //Export 27981 //lo["cache"] = lo.cache; 27982 } 27983 if (enableReducedPatternSet) { 27984 lo.redPatSet = {}; 27985 } 27986 if (leftmin > lo.leftmin) { 27987 lo.leftmin = leftmin; 27988 } 27989 if (rightmin > lo.rightmin) { 27990 lo.rightmin = rightmin; 27991 } 27992 //add exceptions from the pattern file to the local "exceptions"-obj 27993 if (lo.hasOwnProperty("exceptions")) { 27994 Hyphenator.addExceptions(lang, lo.exceptions); 27995 delete lo.exceptions; 27996 } 27997 //copy global exceptions to the language specific exceptions 27998 if (exceptions.hasOwnProperty("global")) { 27999 if (exceptions.hasOwnProperty(lang)) { 28000 exceptions[lang] += ", " + exceptions.global; 28001 } else { 28002 exceptions[lang] = exceptions.global; 28003 } 28004 } 28005 //move exceptions from the the local "exceptions"-obj to the "language"-object 28006 if (exceptions.hasOwnProperty(lang)) { 28007 lo.exceptions = convertExceptionsToObject(exceptions[lang]); 28008 delete exceptions[lang]; 28009 } else { 28010 lo.exceptions = {}; 28011 } 28012 convertPatternsToArray(lo); 28013 lo.genRegExp = new RegExp("(" + createWordRegExp(lang) + ")|(" + url + ")|(" + mail + ")", "gi"); 28014 lo.prepared = true; 28015 } 28016 } 28017 28018 /**** 28019 * @method Hyphenator~prepare 28020 * @desc 28021 * This funtion prepares the Hyphenator~Object: If RemoteLoading is turned off, it assumes 28022 * that the patternfiles are loaded, all conversions are made and the callback is called. 28023 * If storage is active the object is retrieved there. 28024 * If RemoteLoading is on (default), it loads the pattern files and repeatedly checks Hyphenator.languages. 28025 * If a patternfile is loaded the patterns are stored in storage (if enabled), 28026 * converted to their object style and the lang-object extended. 28027 * Finally the callback is called. 28028 * @access private 28029 */ 28030 function prepare(callback) { 28031 var tmp1; 28032 28033 function languagesLoaded() { 28034 forEachKey(docLanguages, function (l) { 28035 if (Hyphenator.languages.hasOwnProperty(l)) { 28036 delete docLanguages[l]; 28037 if (!!storage) { 28038 storage.setItem(l, window.JSON.stringify(Hyphenator.languages[l])); 28039 } 28040 prepareLanguagesObj(l); 28041 callback(l); 28042 } 28043 }); 28044 } 28045 28046 if (!enableRemoteLoading) { 28047 forEachKey(Hyphenator.languages, function (lang) { 28048 prepareLanguagesObj(lang); 28049 }); 28050 callback("*"); 28051 return; 28052 } 28053 callback("urlstyled"); 28054 // get all languages that are used and preload the patterns 28055 forEachKey(docLanguages, function (lang) { 28056 if (!!storage && storage.test(lang)) { 28057 Hyphenator.languages[lang] = window.JSON.parse(storage.getItem(lang)); 28058 prepareLanguagesObj(lang); 28059 if (exceptions.hasOwnProperty("global")) { 28060 tmp1 = convertExceptionsToObject(exceptions.global); 28061 forEachKey(tmp1, function (tmp2) { 28062 Hyphenator.languages[lang].exceptions[tmp2] = tmp1[tmp2]; 28063 }); 28064 } 28065 //Replace exceptions since they may have been changed: 28066 if (exceptions.hasOwnProperty(lang)) { 28067 tmp1 = convertExceptionsToObject(exceptions[lang]); 28068 forEachKey(tmp1, function (tmp2) { 28069 Hyphenator.languages[lang].exceptions[tmp2] = tmp1[tmp2]; 28070 }); 28071 delete exceptions[lang]; 28072 } 28073 //Replace genRegExp since it may have been changed: 28074 Hyphenator.languages[lang].genRegExp = new RegExp("(" + createWordRegExp(lang) + ")|(" + url + ")|(" + mail + ")", "gi"); 28075 if (enableCache) { 28076 if (!Hyphenator.languages[lang].cache) { 28077 Hyphenator.languages[lang].cache = {}; 28078 } 28079 } 28080 delete docLanguages[lang]; 28081 callback(lang); 28082 } else { 28083 loadPatterns(lang, languagesLoaded); 28084 } 28085 }); 28086 //call languagesLoaded in case language has been loaded manually 28087 //and remoteLoading is on (onload won"t fire) 28088 languagesLoaded(); 28089 } 28090 28091 /** 28092 * @method Hyphenator~toggleBox
28093 * @desc 28094 * Creates the toggleBox: a small button to turn off/on hyphenation on a page. 28095 * @see {@link Hyphenator.config} 28096 * @access private 28097 */ 28098 var toggleBox = function () { 28099 var bdy, 28100 myTextNode, 28101 text = (Hyphenator.doHyphenation 28102 ? "Hy-phen-a-tion" 28103 : "Hyphenation"), 28104 myBox = contextWindow.document.getElementById("HyphenatorToggleBox"); 28105 if (!!myBox) { 28106 myBox.firstChild.data = text; 28107 } else { 28108 bdy = contextWindow.document.getElementsByTagName("body")[0]; 28109 myBox = createElem("div", contextWindow); 28110 myBox.setAttribute("id", "HyphenatorToggleBox"); 28111 myBox.setAttribute("class", dontHyphenateClass); 28112 myTextNode = contextWindow.document.createTextNode(text); 28113 myBox.appendChild(myTextNode); 28114 myBox.onclick = Hyphenator.toggleHyphenation; 28115 myBox.style.position = "absolute"; 28116 myBox.style.top = "0px"; 28117 myBox.style.right = "0px"; 28118 myBox.style.zIndex = "1000"; 28119 myBox.style.margin = "0"; 28120 myBox.style.backgroundColor = "#AAAAAA"; 28121 myBox.style.color = "#FFFFFF"; 28122 myBox.style.font = "6pt Arial"; 28123 myBox.style.letterSpacing = "0.2em"; 28124 myBox.style.padding = "3px"; 28125 myBox.style.cursor = "pointer"; 28126 myBox.style.WebkitBorderBottomLeftRadius = "4px"; 28127 myBox.style.MozBorderRadiusBottomleft = "4px"; 28128 myBox.style.borderBottomLeftRadius = "4px"; 28129 bdy.appendChild(myBox); 28130 } 28131 }; 28132 28133 /** 28134 * @method Hyphenator~doCharSubst
28135 * @desc 28136 * Replace chars in a word 28137 * 28138 * @param {Object} loCharSubst Map of substitutions ({"ä": "a", "ü": "u", â¦}) 28139 * @param {string} w the word 28140 * @returns string The word with substituted characers 28141 * @access private 28142 */ 28143 function doCharSubst(loCharSubst, w) { 28144 var r = w; 28145 forEachKey(loCharSubst, function (subst) { 28146 r = r.replace(new RegExp(subst, "g"), loCharSubst[subst]); 28147 }); 28148 return r; 28149 } 28150 28151 /** 28152 * @member {Array} Hyphenator~wwAsMappedCharCodeStore 28153 * @desc 28154 * Array (typed if supported) container for charCodes 28155 * @access private 28156 * @see {@link Hyphenator~hyphenateWord} 28157 */ 28158 var wwAsMappedCharCodeStore = (function () { 28159 if (Object.prototype.hasOwnProperty.call(window, "Int32Array")) { 28160 return new window.Int32Array(64); 28161 } 28162 return []; 28163 }()); 28164 28165 /** 28166 * @member {Array} Hyphenator~wwhpStore 28167 * @desc 28168 * Array (typed if supported) container for hyphenation points 28169 * @access private 28170 * @see {@link Hyphenator~hyphenateWord} 28171 */ 28172 var wwhpStore = (function () { 28173 var r; 28174 if (Object.prototype.hasOwnProperty.call(window, "Uint8Array")) { 28175 r = new window.Uint8Array(64); 28176 } else { 28177 r = []; 28178 } 28179 return r; 28180 }()); 28181 28182 /** 28183 * @method Hyphenator~hyphenateCompound 28184 * @desc 28185 * Treats compound words accordingly to the "compound" setting 28186 * 28187 * @param {Object} lo A language object (containing the patterns) 28188 * @param {string} lang The language of the word 28189 * @param {string} word The word 28190 * @returns string The (hyphenated) compound word 28191 * @access private 28192 */ 28193 function hyphenateCompound(lo, lang, word) { 28194 var hw, parts, i = 0; 28195 switch (compound) { 28196 case "auto": 28197 parts = word.split("-"); 28198 while (i < parts.length) { 28199 if (parts[i].length >= min) { 28200 parts[i] = hyphenateWord(lo, lang, parts[i]); 28201 } 28202 i += 1; 28203 } 28204 hw = parts.join("-"); 28205 break; 28206 case "all": 28207 parts = word.split("-"); 28208 while (i < parts.length) { 28209 if (parts[i].length >= min) { 28210 parts[i] = hyphenateWord(lo, lang, parts[i]); 28211 } 28212 i += 1; 28213 } 28214 hw = parts.join("-" + zeroWidthSpace); 28215 break; 28216 case "hyphen": 28217 hw = word.replace("-", "-" + zeroWidthSpace); 28218 break; 28219 default: 28220 onError(new Error("Hyphenator.settings: compound setting \"" + compound + "\" not known.")); 28221 } 28222 return hw; 28223 } 28224 28225 /** 28226 * @method Hyphenator~hyphenateWord 28227 * @desc 28228 * This function is the heart of Hyphenator.js. It returns a hyphenated word. 28229 * 28230 * If there"s already a {@link Hyphenator~hypen} in the word, the word is returned as it is. 28231 * If the word is in the exceptions list or in the cache, it is retrieved from it. 28232 * If there"s a "-" it calls Hyphenator~hyphenateCompound 28233 * The hyphenated word is returned and (if acivated) cached. 28234 * Both special Events onBeforeWordHyphenation and onAfterWordHyphenation are called for the word. 28235 * @param {Object} lo A language object (containing the patterns) 28236 * @param {string} lang The language of the word 28237 * @param {string} word The word 28238 * @returns string The hyphenated word 28239 * @access private 28240 */ 28241 function hyphenateWord(lo, lang, word) { 28242 var pattern = "", 28243 ww, 28244 wwlen, 28245 wwhp = wwhpStore, 28246 pstart = 0, 28247 plen, 28248 hp, 28249 hpc, 28250 wordLength = word.length, 28251 hw = "", 28252 charMap = lo.charMap.code2int, 28253 charCode, 28254 mappedCharCode, 28255 row = 0, 28256 link = 0, 28257 value = 0, 28258 values, 28259 indexedTrie = lo.indexedTrie, 28260 valueStore = lo.valueStore.keys, 28261 wwAsMappedCharCode = wwAsMappedCharCodeStore; 28262 word = onBeforeWordHyphenation(word, lang); 28263 if (word === "") { 28264 hw = ""; 28265 } else if (enableCache && lo.cache && lo.cache.hasOwnProperty(word)) { //the word is in the cache 28266 hw = lo.cache[word]; 28267 } else if (word.indexOf(hyphen) !== -1) { 28268 //word already contains shy; -> leave at it is! 28269 hw = word; 28270 } else if (lo.exceptions.hasOwnProperty(word)) { //the word is in the exceptions list 28271 hw = lo.exceptions[word].replace(/-/g, hyphen); 28272 } else if (word.indexOf("-") !== -1) {
28273 hw = hyphenateCompound(lo, lang, word); 28274 } else { 28275 ww = word.toLowerCase(); 28276 if (String.prototype.normalize) { 28277 ww = ww.normalize("NFC"); 28278 } 28279 if (lo.hasOwnProperty("charSubstitution")) { 28280 ww = doCharSubst(lo.charSubstitution, ww); 28281 } 28282 if (word.indexOf("'") !== -1) { 28283 ww = ww.replace(/'/g, "â"); //replace APOSTROPHE with RIGHT SINGLE QUOTATION MARK (since the latter is used in the patterns) 28284 } 28285 ww = "_" + ww + "_"; 28286 wwlen = ww.length; 28287 //prepare wwhp and wwAsMappedCharCode 28288 while (pstart < wwlen) { 28289 wwhp[pstart] = 0; 28290 charCode = ww.charCodeAt(pstart); 28291 wwAsMappedCharCode[pstart] = charMap.hasOwnProperty(charCode) 28292 ? charMap[charCode] 28293 : -1; 28294 pstart += 1; 28295 } 28296 //get hyphenation points for all substrings 28297 pstart = 0; 28298 while (pstart < wwlen) { 28299 row = 0; 28300 pattern = ""; 28301 plen = pstart; 28302 while (plen < wwlen) { 28303 mappedCharCode = wwAsMappedCharCode[plen]; 28304 if (mappedCharCode === -1) { 28305 break; 28306 } 28307 if (enableReducedPatternSet) { 28308 pattern += ww.charAt(plen); 28309 } 28310 link = indexedTrie[row + mappedCharCode * 2]; 28311 value = indexedTrie[row + mappedCharCode * 2 + 1]; 28312 if (value > 0) { 28313 hpc = 0; 28314 hp = valueStore[value + hpc]; 28315 while (hp !== 255) { 28316 if (hp > wwhp[pstart + hpc]) { 28317 wwhp[pstart + hpc] = hp; 28318 } 28319 hpc += 1; 28320 hp = valueStore[value + hpc]; 28321 } 28322 if (enableReducedPatternSet) { 28323 if (!lo.redPatSet) { 28324 lo.redPatSet = {}; 28325 } 28326 if (valueStore.subarray) { 28327 values = valueStore.subarray(value, value + hpc); 28328 } else { 28329 values = valueStore.slice(value, value + hpc); 28330 } 28331 lo.redPatSet[pattern] = recreatePattern(pattern, values); 28332 } 28333 } 28334 if (link > 0) { 28335 row = link; 28336 } else { 28337 break; 28338 } 28339 plen += 1; 28340 } 28341 pstart += 1; 28342 } 28343 //create hyphenated word 28344 hp = 0; 28345 while (hp < wordLength) { 28346 if (hp >= lo.leftmin && hp <= (wordLength - lo.rightmin) && (wwhp[hp + 1] % 2) !== 0) { 28347 hw += hyphen + word.charAt(hp); 28348 } else { 28349 hw += word.charAt(hp); 28350 } 28351 hp += 1; 28352 } 28353 } 28354 hw = onAfterWordHyphenation(hw, lang); 28355 if (enableCache) { //put the word in the cache 28356 lo.cache[word] = hw; 28357 } 28358 return hw; 28359 } 28360 28361 28362 /** 28363 * @method Hyphenator~checkIfAllDone 28364 * @desc 28365 * Checks if all elements in {@link Hyphenator~elements} are hyphenated, unhides them and fires onHyphenationDone() 28366 * @access private 28367 */ 28368 function checkIfAllDone() { 28369 var allDone = true, 28370 i = 0, 28371 doclist = {}; 28372 elements.each(function (ellist) { 28373 var j = 0, 28374 l = ellist.length; 28375 while (j < l) { 28376 allDone = allDone && ellist[j].hyphenated; 28377 if (!doclist.hasOwnProperty(ellist[j].element.baseURI)) { 28378 doclist[ellist[j].element.ownerDocument.location.href] = true; 28379 } 28380 doclist[ellist[j].element.ownerDocument.location.href] = doclist[ellist[j].element.ownerDocument.location.href] && ellist[j].hyphenated; 28381 j += 1; 28382 } 28383 }); 28384 if (allDone) { 28385 if (intermediateState === "hidden" && unhide === "progressive") { 28386 elements.each(function (ellist) { 28387 var j = 0, 28388 l = ellist.length, 28389 el; 28390 while (j < l) { 28391 el = ellist[j].element; 28392 el.className = el.className.replace(unhideClassRegExp, ""); 28393 if (el.className === "") { 28394 el.removeAttribute("class"); 28395 } 28396 j += 1; 28397 } 28398 }); 28399 } 28400 while (i < CSSEditors.length) { 28401 CSSEditors[i].clearChanges(); 28402 i += 1; 28403 }
28404 forEachKey(doclist, function (doc) { 28405 onHyphenationDone(doc); 28406 }); 28407 if (!!storage && storage.deferred.length > 0) { 28408 i = 0; 28409 while (i < storage.deferred.length) { 28410 storage.deferred[i].call(); 28411 i += 1; 28412 } 28413 storage.deferred = []; 28414 } 28415 } 28416 } 28417 28418 /** 28419 * @method Hyphenator~controlOrphans 28420 * @desc 28421 * removes orphans depending on the "orphanControl"-setting: 28422 * orphanControl === 1: do nothing 28423 * orphanControl === 2: prevent last word to be hyphenated 28424 * orphanControl === 3: prevent one word on a last line (inserts a nobreaking space) 28425 * @param {string} part - The sring where orphans have to be removed 28426 * @access private 28427 */ 28428 function controlOrphans(ignore, leadingWhiteSpace, lastWord, trailingWhiteSpace) { 28429 var h = hyphen; 28430 //escape hyphen 28431 if (".\\+*?[^]$(){}=!<>|:-".indexOf(hyphen) !== -1) { 28432 h = "\\" + hyphen; 28433 } else { 28434 h = hyphen; 28435 } 28436 if (orphanControl === 3 && leadingWhiteSpace === " ") { 28437 leadingWhiteSpace = String.fromCharCode(160); 28438 } 28439 return leadingWhiteSpace + lastWord.replace(new RegExp(h + "|" + zeroWidthSpace, "g"), "") + trailingWhiteSpace; 28440 } 28441 28442 /** 28443 * @method Hyphenator~hyphenateElement 28444 * @desc 28445 * Takes the content of the given element and - if there"s text - replaces the words 28446 * by hyphenated words. If there"s another element, the function is called recursively. 28447 * When all words are hyphenated, the visibility of the element is set to "visible". 28448 * @param {string} lang - The language-code of the element 28449 * @param {Element} elo - The element to hyphenate {@link Hyphenator~elements~ElementCollection~Element} 28450 * @access private 28451 */ 28452 function hyphenateElement(lang, elo) { 28453 var el = elo.element, 28454 hyphenate, 28455 n, 28456 i, 28457 lo; 28458 if (lang === "urlstyled" && Hyphenator.doHyphenation) { 28459 i = 0; 28460 n = el.childNodes[i]; 28461 while (!!n) { 28462 if ( 28463 n.nodeType === 3 //type 3 = #text 28464 && (/\S/).test(n.data) 28465 ) { //not just white space 28466 n.data = hyphenateURL(n.data); 28467 } 28468 i += 1; 28469 n = el.childNodes[i]; 28470 } 28471 } else if (Hyphenator.languages.hasOwnProperty(lang) && Hyphenator.doHyphenation) { 28472 lo = Hyphenator.languages[lang]; 28473 hyphenate = function (match, word, url, mail) { 28474 var r; 28475 if (!!url || !!mail) { 28476 r = hyphenateURL(match); 28477 } else { 28478 r = hyphenateWord(lo, lang, word); 28479 } 28480 return r; 28481 }; 28482 i = 0; 28483 n = el.childNodes[i]; 28484 while (!!n) { 28485 if ( 28486 n.nodeType === 3 //type 3 = #text 28487 && (/\S/).test(n.data) //not just white space 28488 && n.data.length >= min 28489 ) { //longer then min 28490 n.data = n.data.replace(lo.genRegExp, hyphenate); 28491 if (orphanControl !== 1) { 28492 //prevent last word from being hyphenated 28493 n.data = n.data.replace(/(\u0020*)(\S+)(\s*)$/, controlOrphans); 28494 } 28495 } 28496 i += 1; 28497 n = el.childNodes[i]; 28498 } 28499 } 28500 if (intermediateState === "hidden" && unhide === "wait") { 28501 el.className = el.className.replace(hideClassRegExp, ""); 28502 if (el.className === "") { 28503 el.removeAttribute("class"); 28504 } 28505 } 28506 if (intermediateState === "hidden" && unhide === "progressive") { 28507 el.className = el.className.replace(hideClassRegExp, " " + unhideClass); 28508 } 28509 elo.hyphenated = true; 28510 elements.counters[1] += 1; 28511 if (elements.counters[0] <= elements.counters[1]) { 28512 checkIfAllDone(); 28513 } 28514 } 28515 28516 /** 28517 * @method Hyphenator~hyphenateLanguageElements
28518 * @desc 28519 * Calls hyphenateElement() for all elements of the specified language. 28520 * If the language is "*" then all elements are hyphenated. 28521 * This is done with a setTimout 28522 * to prevent a "long running Script"-alert when hyphenating large pages. 28523 * Therefore a tricky bind()-function was necessary. 28524 * @param {string} lang The language of the elements to hyphenate 28525 * @access private 28526 */ 28527 28528 function hyphenateLanguageElements(lang) { 28529 /*function bind(fun, arg1, arg2) { 28530 return function () { 28531 return fun(arg1, arg2); 28532 }; 28533 }*/ 28534 var i = 0, 28535 l; 28536 if (lang === "*") { 28537 elements.each(function (lang, ellist) { 28538 var j = 0, 28539 le = ellist.length; 28540 while (j < le) { 28541 //zeroTimeOut(bind(hyphenateElement, lang, ellist[j])); 28542 hyphenateElement(lang, ellist[j]); 28543 j += 1; 28544 } 28545 }); 28546 } else { 28547 if (elements.list.hasOwnProperty(lang)) { 28548 l = elements.list[lang].length; 28549 while (i < l) { 28550 //zeroTimeOut(bind(hyphenateElement, lang, elements.list[lang][i])); 28551 hyphenateElement(lang, elements.list[lang][i]); 28552 i += 1; 28553 } 28554 } 28555 } 28556 } 28557 28558 /** 28559 * @method Hyphenator~removeHyphenationFromDocument 28560 * @desc 28561 * Does what it says and unregisters the onCopyEvent from the elements 28562 * @access private 28563 */ 28564 function removeHyphenationFromDocument() { 28565 elements.each(function (ellist) { 28566 var i = 0, 28567 l = ellist.length; 28568 while (i < l) { 28569 removeHyphenationFromElement(ellist[i].element); 28570 ellist[i].hyphenated = false; 28571 i += 1; 28572 } 28573 }); 28574 } 28575 28576 /** 28577 * @method Hyphenator~createStorage 28578 * @desc 28579 * inits the private var {@link Hyphenator~storage) depending of the setting in {@link Hyphenator~storageType} 28580 * and the supported features of the system. 28581 * @access private 28582 */ 28583 function createStorage() { 28584 var s; 28585 function makeStorage(s) { 28586 var store = s, 28587 prefix = "Hyphenator_" + Hyphenator.version + "_", 28588 deferred = [], 28589 test = function (name) { 28590 var val = store.getItem(prefix + name); 28591 return !!val; 28592 }, 28593 getItem = function (name) { 28594 return store.getItem(prefix + name); 28595 }, 28596 setItem = function (name, value) { 28597 try { 28598 store.setItem(prefix + name, value); 28599 } catch (e) { 28600 onError(e); 28601 } 28602 }; 28603 return { 28604 deferred: deferred, 28605 test: test, 28606 getItem: getItem, 28607 setItem: setItem 28608 }; 28609 } 28610 try { 28611 if ( 28612 storageType !== "none" && 28613 window.JSON !== undefined && 28614 window.localStorage !== undefined && 28615 window.sessionStorage !== undefined && 28616 window.JSON.stringify !== undefined && 28617 window.JSON.parse !== undefined 28618 ) { 28619 switch (storageType) { 28620 case "session": 28621 s = window.sessionStorage; 28622 break; 28623 case "local": 28624 s = window.localStorage; 28625 break; 28626 default: 28627 s = undefined; 28628 } 28629 //check for private mode 28630 s.setItem("storageTest", "1"); 28631 s.removeItem("storageTest"); 28632 } 28633 } catch (ignore) { 28634 //FF throws an error if DOM.storage.enabled is set to false 28635 s = undefined; 28636 } 28637 if (s) { 28638 storage = makeStorage(s); 28639 } else { 28640 storage = undefined; 28641 } 28642 } 28643 28644 /** 28645 * @method Hyphenator~storeConfiguration
28646 * @desc 28647 * Stores the current config-options in DOM-Storage 28648 * @access private 28649 */ 28650 function storeConfiguration() { 28651 if (!storage) { 28652 return; 28653 } 28654 var settings = { 28655 "STORED": true, 28656 "classname": hyphenateClass, 28657 "urlclassname": urlHyphenateClass, 28658 "donthyphenateclassname": dontHyphenateClass, 28659 "minwordlength": min, 28660 "hyphenchar": hyphen, 28661 "urlhyphenchar": urlhyphen, 28662 "togglebox": toggleBox, 28663 "displaytogglebox": displayToggleBox, 28664 "remoteloading": enableRemoteLoading, 28665 "enablecache": enableCache, 28666 "enablereducedpatternset": enableReducedPatternSet, 28667 "onhyphenationdonecallback": onHyphenationDone, 28668 "onerrorhandler": onError, 28669 "onwarninghandler": onWarning, 28670 "intermediatestate": intermediateState, 28671 "selectorfunction": selectorFunction || mySelectorFunction, 28672 "safecopy": safeCopy, 28673 "doframes": doFrames, 28674 "storagetype": storageType, 28675 "orphancontrol": orphanControl, 28676 "dohyphenation": Hyphenator.doHyphenation, 28677 "persistentconfig": persistentConfig, 28678 "defaultlanguage": defaultLanguage, 28679 "useCSS3hyphenation": css3, 28680 "unhide": unhide, 28681 "onbeforewordhyphenation": onBeforeWordHyphenation, 28682 "onafterwordhyphenation": onAfterWordHyphenation, 28683 "leftmin": leftmin, 28684 "rightmin": rightmin, 28685 "compound": compound 28686 }; 28687 storage.setItem("config", window.JSON.stringify(settings)); 28688 } 28689 28690 /** 28691 * @method Hyphenator~restoreConfiguration 28692 * @desc 28693 * Retrieves config-options from DOM-Storage and does configuration accordingly 28694 * @access private 28695 */ 28696 function restoreConfiguration() { 28697 var settings; 28698 if (storage.test("config")) { 28699 settings = window.JSON.parse(storage.getItem("config")); 28700 Hyphenator.config(settings); 28701 } 28702 } 28703 28704 /**EXPORTED VALUES**/ 28705 28706 /** 28707 * @member {string} Hyphenator.version 28708 * @desc 28709 * String containing the actual version of Hyphenator.js 28710 * [major release].[minor releas].[bugfix release] 28711 * major release: new API, new Features, big changes 28712 * minor release: new languages, improvements 28713 * @access public 28714 */ 28715 var version = '5.3.0'; 28716 28717 /** 28718 * @member {boolean} Hyphenator.doHyphenation 28719 * @desc 28720 * If doHyphenation is set to false, hyphenateDocument() isn"t called. 28721 * All other actions are performed. 28722 * @default true 28723 */ 28724 var doHyphenation = true; 28725 28726 /** 28727 * @typedef {Object} Hyphenator.languages.language 28728 * @property {Number} leftmin - The minimum of chars to remain on the old line 28729 * @property {Number} rightmin - The minimum of chars to go on the new line 28730 * @property {string} specialChars - Non-ASCII chars in the alphabet. 28731 * @property {Object.<number, string>} patterns - the patterns in a compressed format. The key is the length of the patterns in the value string. 28732 * @property {Object.<string, string>} charSubstitution - optional: a hash table with chars that are replaced during hyphenation 28733 * @property {string | Object.<string, string>} exceptions - optional: a csv string containing exceptions 28734 */ 28735 28736 /** 28737 * @member {Object.<string, Hyphenator.languages.language>} Hyphenator.languages 28738 * @desc 28739 * Objects that holds key-value pairs, where key is the language and the value is the 28740 * language-object loaded from (and set by) the pattern file. 28741 * @namespace Hyphenator.languages 28742 * @access public 28743 */ 28744 var languages = {}; 28745 28746 /** 28747 * @method Hyphenator.config 28748 * @desc 28749 * The Hyphenator.config() function that takes an object as an argument. The object contains key-value-pairs 28750 * containig Hyphenator-settings. 28751 * @param {Hyphenator.config} obj 28752 * @access public 28753 * @example 28754 * <script src = "Hyphenator.js" type = "text/javascript"></script> 28755 Â * <script type = "text/javascript"> 28756 Â * Hyphenator.config({"minwordlength":4,"hyphenchar":"|"}); 28757 * Hyphenator.run(); 28758 Â * </script> 28759 */ 28760 function config(obj) { 28761 var assert = function (name, type) { 28762 var r, 28763 t; 28764 t = typeof obj[name]; 28765 if (t === type) { 28766 r = true; 28767 } else { 28768 onError(new Error("Config onError: " + name + " must be of type " + type)); 28769 r = false;
28770 } 28771 return r; 28772 }; 28773 28774 if (obj.hasOwnProperty("storagetype")) { 28775 if (assert("storagetype", "string")) { 28776 storageType = obj.storagetype; 28777 } 28778 if (!storage) { 28779 createStorage(); 28780 } 28781 } 28782 if (!obj.hasOwnProperty("STORED") && storage && obj.hasOwnProperty("persistentconfig") && obj.persistentconfig === true) { 28783 restoreConfiguration(); 28784 } 28785 28786 forEachKey(obj, function (key) { 28787 switch (key) { 28788 case "STORED": 28789 break; 28790 case "classname": 28791 if (assert("classname", "string")) { 28792 hyphenateClass = obj[key]; 28793 } 28794 break; 28795 case "urlclassname": 28796 if (assert("urlclassname", "string")) { 28797 urlHyphenateClass = obj[key]; 28798 } 28799 break; 28800 case "donthyphenateclassname": 28801 if (assert("donthyphenateclassname", "string")) { 28802 dontHyphenateClass = obj[key]; 28803 } 28804 break; 28805 case "minwordlength": 28806 if (assert("minwordlength", "number")) { 28807 min = obj[key]; 28808 } 28809 break; 28810 case "hyphenchar": 28811 if (assert("hyphenchar", "string")) { 28812 if (obj.hyphenchar === "­") { 28813 obj.hyphenchar = String.fromCharCode(173); 28814 } 28815 hyphen = obj[key]; 28816 } 28817 break; 28818 case "urlhyphenchar": 28819 if (obj.hasOwnProperty("urlhyphenchar")) { 28820 if (assert("urlhyphenchar", "string")) { 28821 urlhyphen = obj[key]; 28822 } 28823 } 28824 break; 28825 case "togglebox": 28826 if (assert("togglebox", "function")) { 28827 toggleBox = obj[key]; 28828 } 28829 break; 28830 case "displaytogglebox": 28831 if (assert("displaytogglebox", "boolean")) { 28832 displayToggleBox = obj[key]; 28833 } 28834 break; 28835 case "remoteloading": 28836 if (assert("remoteloading", "boolean")) { 28837 enableRemoteLoading = obj[key]; 28838 } 28839 break; 28840 case "enablecache": 28841 if (assert("enablecache", "boolean")) { 28842 enableCache = obj[key]; 28843 } 28844 break; 28845 case "enablereducedpatternset": 28846 if (assert("enablereducedpatternset", "boolean")) { 28847 enableReducedPatternSet = obj[key]; 28848 } 28849 break; 28850 case "onhyphenationdonecallback": 28851 if (assert("onhyphenationdonecallback", "function")) { 28852 onHyphenationDone = obj[key]; 28853 } 28854 break; 28855 case "onerrorhandler": 28856 if (assert("onerrorhandler", "function")) { 28857 onError = obj[key]; 28858 } 28859 break; 28860 case "onwarninghandler": 28861 if (assert("onwarninghandler", "function")) { 28862 onWarning = obj[key]; 28863 } 28864 break; 28865 case "intermediatestate": 28866 if (assert("intermediatestate", "string")) { 28867 intermediateState = obj[key]; 28868 } 28869 break; 28870 case "selectorfunction": 28871 if (assert("selectorfunction", "function")) { 28872 selectorFunction = obj[key]; 28873 } 28874 break; 28875 case "safecopy": 28876 if (assert("safecopy", "boolean")) { 28877 safeCopy = obj[key]; 28878 } 28879 break; 28880 case "doframes": 28881 if (assert("doframes", "boolean")) { 28882 doFrames = obj[key]; 28883 } 28884 break; 28885 case "storagetype": 28886 if (assert("storagetype", "string")) { 28887 storageType = obj[key]; 28888 } 28889 break; 28890 case "orphancontrol": 28891 if (assert("orphancontrol", "number")) { 28892 orphanControl = obj[key]; 28893 } 28894 break; 28895 case "dohyphenation": 28896 if (assert("dohyphenation", "boolean")) { 28897 Hyphenator.doHyphenation = obj[key]; 28898 } 28899 break; 28900 case "persistentconfig": 28901 if (assert("persistentconfig", "boolean")) { 28902 persistentConfig = obj[key]; 28903 } 28904 break; 28905 case "defaultlanguage": 28906 if (assert("defaultlanguage", "string")) { 28907 defaultLanguage = obj[key]; 28908 } 28909 break; 28910 case "useCSS3hyphenation": 28911 if (assert("useCSS3hyphenation", "boolean")) { 28912 css3 = obj[key]; 28913 } 28914 break; 28915 case "unhide": 28916 if (assert("unhide", "string")) { 28917 unhide = obj[key]; 28918 } 28919 break; 28920 case "onbeforewordhyphenation": 28921 if (assert("onbeforewordhyphenation", "function")) { 28922 onBeforeWordHyphenation = obj[key]; 28923 } 28924 break; 28925 case "onafterwordhyphenation": 28926 if (assert("onafterwordhyphenation", "function")) { 28927 onAfterWordHyphenation = obj[key]; 28928 } 28929 break; 28930 case "leftmin": 28931 if (assert("leftmin", "number")) { 28932 leftmin = obj[key]; 28933 } 28934 break; 28935 case "rightmin": 28936 if (assert("rightmin", "number")) { 28937 rightmin = obj[key]; 28938 } 28939 break; 28940 case "compound": 28941 if (assert("compound", "string")) { 28942 compound = obj[key]; 28943 } 28944 break; 28945 default: 28946 onError(new Error("Hyphenator.config: property " + key + " not known.")); 28947 } 28948 }); 28949 if (storage && persistentConfig) { 28950 storeConfiguration(); 28951 } 28952 } 28953 28954 /** 28955 * @method Hyphenator.run
28956 * @desc 28957 * Bootstrap function that starts all hyphenation processes when called: 28958 * Tries to create storage if required and calls {@link Hyphenator~runWhenLoaded} on "window" handing over the callback "process" 28959 * @access public 28960 * @example 28961 * <script src = "Hyphenator.js" type = "text/javascript"></script> 28962 Â * <script type = "text/javascript"> 28963 Â * Â Hyphenator.run(); 28964 Â * </script> 28965 */ 28966 function run() { 28967 /** 28968 *@callback Hyphenator.run~process process - The function is called when the DOM has loaded (or called for each frame) 28969 */ 28970 var process = function () { 28971 try { 28972 if (contextWindow.document.getElementsByTagName("frameset").length > 0) { 28973 return; //we are in a frameset 28974 } 28975 autoSetMainLanguage(undefined); 28976 gatherDocumentInfos(); 28977 if (displayToggleBox) { 28978 toggleBox(); 28979 } 28980 prepare(hyphenateLanguageElements); 28981 } catch (e) { 28982 onError(e); 28983 } 28984 }; 28985 28986 if (!storage) { 28987 createStorage(); 28988 } 28989 runWhenLoaded(window, process); 28990 } 28991 28992 /** 28993 * @method Hyphenator.addExceptions 28994 * @desc 28995 * Adds the exceptions from the string to the appropriate language in the 28996 * {@link Hyphenator~languages}-object 28997 * @param {string} lang The language 28998 * @param {string} words A comma separated string of hyphenated words WITH spaces. 28999 * @access public 29000 * @example <script src = "Hyphenator.js" type = "text/javascript"></script> 29001 Â * <script type = "text/javascript"> 29002 Â * Â Hyphenator.addExceptions("de","ziem-lich, Wach-stube"); 29003 * Hyphenator.run(); 29004 Â * </script> 29005 */ 29006 function addExceptions(lang, words) { 29007 if (lang === "") { 29008 lang = "global"; 29009 } 29010 if (exceptions.hasOwnProperty(lang)) { 29011 exceptions[lang] += ", " + words; 29012 } else { 29013 exceptions[lang] = words; 29014 } 29015 } 29016 29017 /** 29018 * @method Hyphenator.hyphenate 29019 * @access public 29020 * @desc 29021 * Hyphenates the target. The language patterns must be loaded. 29022 * If the target is a string, the hyphenated string is returned, 29023 * if it"s an object, the values are hyphenated directly and undefined (aka nothing) is returned 29024 * @param {string|Object} target the target to be hyphenated 29025 * @param {string} lang the language of the target 29026 * @returns {string|undefined} 29027 * @example <script src = "Hyphenator.js" type = "text/javascript"></script> 29028 * <script src = "patterns/en.js" type = "text/javascript"></script> 29029 Â * <script type = "text/javascript"> 29030 * var t = Hyphenator.hyphenate("Hyphenation", "en"); //Hy|phen|ation 29031 * </script> 29032 */ 29033 function hyphenate(target, lang) { 29034 var turnout, n, i, lo; 29035 lo = Hyphenator.languages[lang]; 29036 if (Hyphenator.languages.hasOwnProperty(lang)) { 29037 if (!lo.prepared) { 29038 prepareLanguagesObj(lang); 29039 } 29040 turnout = function (match, word, url, mail) { 29041 var r; 29042 if (!!url || !!mail) { 29043 r = hyphenateURL(match); 29044 } else { 29045 r = hyphenateWord(lo, lang, word); 29046 } 29047 return r; 29048 }; 29049 if (typeof target === "object" && !(typeof target === "string" || target.constructor === String)) { 29050 i = 0; 29051 n = target.childNodes[i]; 29052 while (!!n) { 29053 if ( 29054 n.nodeType === 3 //type 3 = #text 29055 && (/\S/).test(n.data) //not just white space 29056 && n.data.length >= min 29057 ) { //longer then min 29058 n.data = n.data.replace(lo.genRegExp, turnout); 29059 } else if (n.nodeType === 1) { 29060 if (n.lang !== "") { 29061 Hyphenator.hyphenate(n, n.lang); 29062 } else { 29063 Hyphenator.hyphenate(n, lang); 29064 } 29065 } 29066 i += 1; 29067 n = target.childNodes[i]; 29068 } 29069 } else if (typeof target === "string" || target.constructor === String) { 29070 return target.replace(lo.genRegExp, turnout); 29071 } 29072 } else { 29073 onError(new Error("Language \"" + lang + "\" is not loaded.")); 29074 } 29075 } 29076 29077 /** 29078 * @method Hyphenator.getRedPatternSet
29079 * @desc 29080 * Returns the reduced pattern set: an object looking like: {"patk": pat} 29081 * @param {string} lang the language patterns are stored for 29082 * @returns {Object.<string, string>} 29083 * @access public 29084 */ 29085 function getRedPatternSet(lang) { 29086 return Hyphenator.languages[lang].redPatSet; 29087 } 29088 29089 /** 29090 * @method Hyphenator.getConfigFromURI 29091 * @desc 29092 * reads and sets configurations from GET parameters in the URI 29093 * @access public 29094 */ 29095 function getConfigFromURI() { 29096 var loc = null, 29097 re = {}, 29098 jsArray = contextWindow.document.getElementsByTagName("script"), 29099 i = 0, 29100 j = 0, 29101 l = jsArray.length, 29102 s, 29103 gp, 29104 option; 29105 while (i < l) { 29106 if (!!jsArray[i].getAttribute("src")) { 29107 loc = jsArray[i].getAttribute("src"); 29108 } 29109 if (loc && (loc.indexOf("Hyphenator.js?") !== -1)) { 29110 s = loc.indexOf("Hyphenator.js?"); 29111 gp = loc.substring(s + 14).split("&"); 29112 while (j < gp.length) { 29113 option = gp[j].split("="); 29114 if (option[0] !== "bm") { 29115 if (option[1] === "true") { 29116 option[1] = true; 29117 } else if (option[1] === "false") { 29118 option[1] = false; 29119 } else if (isFinite(option[1])) { 29120 option[1] = parseInt(option[1], 10); 29121 } 29122 if ( 29123 option[0] === "togglebox" || 29124 option[0] === "onhyphenationdonecallback" || 29125 option[0] === "onerrorhandler" || 29126 option[0] === "selectorfunction" || 29127 option[0] === "onbeforewordhyphenation" || 29128 option[0] === "onafterwordhyphenation" 29129 ) { 29130 option[1] = new Function("", option[1]); 29131 } 29132 re[option[0]] = option[1]; 29133 } 29134 j += 1; 29135 } 29136 break; 29137 } 29138 i += 1; 29139 } 29140 return re; 29141 } 29142 29143 /** 29144 * @method Hyphenator.toggleHyphenation 29145 * @desc 29146 * Checks the current state of Hyphenator.doHyphenation and removes or does hyphenation. 29147 * @access public 29148 */ 29149 function toggleHyphenation() { 29150 if (Hyphenator.doHyphenation) { 29151 if (!!css3hyphenateClassHandle) { 29152 css3hyphenateClassHandle.setRule("." + css3hyphenateClass, css3_h9n.property + ": none;"); 29153 } 29154 removeHyphenationFromDocument(); 29155 if (safeCopy) { 29156 copy.removeOnCopy(); 29157 } 29158 Hyphenator.doHyphenation = false; 29159 storeConfiguration(); 29160 if (displayToggleBox) { 29161 toggleBox(); 29162 } 29163 } else { 29164 if (!!css3hyphenateClassHandle) { 29165 css3hyphenateClassHandle.setRule("." + css3hyphenateClass, css3_h9n.property + ": auto;"); 29166 } 29167 Hyphenator.doHyphenation = true; 29168 hyphenateLanguageElements("*"); 29169 if (safeCopy) { 29170 copy.reactivateOnCopy(); 29171 } 29172 storeConfiguration(); 29173 if (displayToggleBox) { 29174 toggleBox(); 29175 } 29176 } 29177 } 29178 29179 return { 29180 version: version, 29181 doHyphenation: doHyphenation, 29182 languages: languages, 29183 config: config, 29184 run: run, 29185 addExceptions: addExceptions, 29186 hyphenate: hyphenate, 29187 getRedPatternSet: getRedPatternSet, 29188 isBookmarklet: isBookmarklet, 29189 getConfigFromURI: getConfigFromURI, 29190 toggleHyphenation: toggleHyphenation 29191 }; 29192 29193}(window)); 29194 29195//Export properties/methods (for google closure compiler) 29196/**** to be moved to external file 29197 Hyphenator["languages"] = Hyphenator.languages; 29198 Hyphenator["config"] = Hyphenator.config; 29199 Hyphenator["run"] = Hyphenator.run;
29200 Hyphenator["addExceptions"] = Hyphenator.addExceptions; 29201 Hyphenator["hyphenate"] = Hyphenator.hyphenate; 29202 Hyphenator["getRedPatternSet"] = Hyphenator.getRedPatternSet; 29203 Hyphenator["isBookmarklet"] = Hyphenator.isBookmarklet; 29204 Hyphenator["getConfigFromURI"] = Hyphenator.getConfigFromURI; 29205 Hyphenator["toggleHyphenation"] = Hyphenator.toggleHyphenation; 29206 window["Hyphenator"] = Hyphenator; 29207 */ 29208 29209/* 29210 * call Hyphenator if it is a Bookmarklet 29211 */ 29212if (Hyphenator.isBookmarklet) { 29213 Hyphenator.config({displaytogglebox: true, intermediatestate: "visible", storagetype: "local", doframes: true, useCSS3hyphenation: true}); 29214 Hyphenator.config(Hyphenator.getConfigFromURI()); 29215 Hyphenator.run(); 29216} 29217 29218 29219// The en-US hyphenation patterns are retrieved from 29220// http://tug.org/svn/texhyphen/trunk/collaboration/repository/hyphenator/ 29221/*global Hyphenator*/ 29222Hyphenator.languages['en-us'] = Hyphenator.languages['en'] = { 29223 leftmin: 2, 29224 rightmin: 3, 29225 specialChars: "", 29226 patterns: { 29227 3: "x1qei2e1je1f1to2tlou2w3c1tue1q4tvtw41tyo1q4tz4tcd2yd1wd1v1du1ta4eu1pas4y1droo2d1psw24sv1dod1m1fad1j1su4fdo2n4fh1fi4fm4fn1fopd42ft3fu1fy1ga2sss1ru5jd5cd1bg3bgd44uk2ok1cyo5jgl2g1m4pf4pg1gog3p1gr1soc1qgs2oi2g3w1gysk21coc5nh1bck1h1fh1h4hk1zo1ci4zms2hh1w2ch5zl2idc3c2us2igi3hi3j4ik1cab1vsa22btr1w4bp2io2ipu3u4irbk4b1j1va2ze2bf4oar1p4nz4zbi1u2iv4iy5ja1jeza1y1wk1bk3fkh4k1ikk4k1lk1mk5tk1w2ldr1mn1t2lfr1lr3j4ljl1l2lm2lp4ltn1rrh4v4yn1q1ly1maw1brg2r1fwi24ao2mhw4kr1cw5p4mkm1m1mo4wtwy4x1ar1ba2nn5mx1ex1h4mtx3i1muqu2p3wx3o4mwa1jx3p1naai2x1ua2fxx4y1ba2dn1jy1cn3fpr2y1dy1i", 29228 4: "4dryn2itni4on1inn1im_up3nik4ni4dy5giye4tyes4_ye44ab_nhe4nha4abe2n2gyn1guy1ery5eep2pe4abry3lay3lone4wne4v1nesy3chn1erne2q3neo1nenp2seps4hy2cey5lu2nedne2cyme44nk2y5at2adine2b2ne_y5ac2p1tp2ten1den1cun1cryn5dp2th4adup4twpub3ae4rxu3ayn5gaff4pue4n2au4p1ppuf4n2atag1ipu4mag1na2gon4asx3tix1t2pu2na4gya3haa3heah4la3ho_ti2a5ian2an5puspu2tnak4_th2n1kl_te4_ta4mu4u4mupmun23mum2alex4ob_sy25ynxal1i_st4y1o4xi5cxi5a4alm_si2_sh2m5sixhu4m4sh4m3r4amam2py2rabm2pixhi2yo5dr2ai4m1pmo2vmos2x2edmo2r4n1la2mor2asx3c2xas5yom4x4apxam3nme44mokrbi2nne44andy4osp4ot3noemn4omn4a4m1n4nog4m1l2angws4l1posw3shwri4wra4yp3iwom11wo2m2izrb4ow4nopo4pr2cem2isrd2iano4mig4y3pomi3awiz55mi_no4n4m1fme4v2re_wir42mes1menme2mme2gre1o2med4me_4nop4m5c4m1bwil21noureu2whi4w3ev4maprev2w1era2plpo4crfu4r4fyy5pu2maha3pu2mab2a2rn1p4npi44lyb4lya2p3nwam42l1w1lut4luplu3or1glluf4lu5a2wacltu2y3rol1tr4vv4r3guyr4rl1te4rh_nru4ar1il2sel4sc4l1rl5prl4plys4c4lovri3ar4ib4lof3lo_ar2par3q_os3ll4oll2i4as_ri1o3vokl2levoi44p1mlka35vo_ns4cas4ll1izr4iqr2is3vivl1it3lika2tan2sen2slrle42l3hlgo3l5gal5frns3mvi4p3ley_od2r2meles24athr4myle2al3drv1inldi4l2de2vilnt2il3civik4lce42l1b4lavv3ifrno4r3nua1trr2ocnt4sy4sok4syks4la2tuk4sck3ouko5ryss4a2tyau4b4klyys1tnu1akis4au3rki4pro4ek4ima2va5ki_nu4dn4umn3uokes4k1erav1irok2ke4g1keek2ed_me2aw3ikal4aws4k5agk3ab3ka_aye4ays4veg3jo4p5ba_4vedjew3n1v24ve_ja4pzar23vatizi4n1w41batba4z2b1bb2beix4o4i5w4b1d4be_rox5nym4nyp4n3za4ittr3por1r4i1ti1bel2ith2itei2su4rs2r1sars4cr2seis1p3betvag4i2sor1shbe3wr1sioad34b3hbi2bbi4d3bie3isf4ise2is_1bilr1sp5va_r5sw_le2uz4eir1ibi2tuxu3r1tiu1v2i1raze4nze4pb2l2uu4mo1biip3iz1eripe4b4louts44b1m4b3no3br3bodi4osbo4eru3aio4mi1ol4io_3booo1ce4inyin1u2insru2n2inn4inl4inkrv4e2inioch42iner3vo4indpi2np4idbt4lb4tob3trry4cry3t2in_o4elbu4ni2muim1i5saiil3v4ilnil1iil5fs1apo3er4b5w5by_bys4_in1sau4i1lazet4u2suo3ev2z1ii2go4igius1p5saw4s5bo2fi4ifti3fl4if_i3etsch2usc22ie4i2dui4dri2diid5dpi3au3ruz4ils1cuz4is4s5d4se_se4a2ce_2ici4ich3ceii1bri5bo1ceni1blse2g5seiibe43cepi2aniam4ur2li2al2i1acet4hy2scew41phy4ch_5phuhu4thu4gche2h4tyh4shur1durc44hr44h5p5sev5sexu1ra4s3fup3p2s3gph3t2sh_ho4g2h1n_he23ciau3pl4h1mci5ch2lozo4m4ciihi2vhi4p2cim2cin4phsu1peu1ouo1geu5osheu4sho4he4th1es4shwun5zun5ysi1bunu45cizo4glck3ihep5he2nh4ed1sioph2l5hazsi2rcly4zte4_ge21siscoe22cog5siu1siv5siz_ga24skes1l2s2leha4m2s1ms3ma1ogyo1h2u1ni3gus3gun2guegu4acov1gth3_eu3g4ros1n4_es3u2nez4zyum2pu1mi3som_ev2oig4cri2gov15goos4opgon2ul5v5goeu3lugob53go_2c1t4ph_g1nog1nic2te4sov4ulsgn4ag4myc4twcud5c4ufc4uipe2t3glo1gleul2igla4_eg23giz3cun5givgi4u3gir5gio1cusul4e2spagil4g1ic5gi__eb4cze41d2a5da_u1laggo44daf2dagg2gege4v1geo1gen2ged3dato1la2ge_ol2dol2i5daypek4p4eed1d42de_4gazol2tuiv3ol2vo2lys1sa2gamgaf4o2meui4n2ui2pe2cd4em4fugi4jku3fl3ufaf2tyf4to1denu4du4pe_2f3sfri2de1ps1si4f5pfos5d3eqs4sls4snfo2rss2tdes25fon4p1b_ci23payss5w2st_de1tf4l2de1v2fin4dey4d1fd4gast2idg1id2gyd1h25di_ud5dfi3au4cy_ch4pav43didu3cud1iff2fyu3crd1inst4r4f1ffev4fer11dio2fedfe4bdir2s2ty4fe_dis1on1au3
29228ca4f5bon1c2ondd5k25far4fagpa1peys45eyc1exps4ul2dlyp4ale3whon3s3do_e1wa5doee5vud4oge1visu2msu2nub4euav4su2rp4ai6rk_d4or3dosu1atdo4v3doxp4adoo4k4swoo2padre4eus4e3upe5un2ophet5z4syc3syl4y3hoy1ads4pd4swd4syd2tho4wo3ta_du2c4etn2tabta2luac4es4wdu4g2ess4uabdu4n4duptav4st5bow1io1pr5dyn2tawe1sp2t1bop1uead1tz4et4chopy5ea4l4t1d4te_2tyle1si4esh1tee4tyat1cr4twoteg4es2c4eru1teoer1s2eroea2tte4po1rat1wh3tusea2v3teu3texer1i2e1ber1h4tey2t1f4t1ge3br2th_th2e4thle1ce3tumec2i2ths2erb1tia4tueer1aou5vtud2tif22tige1potu1aou4lttu41timt5toos4le1cre2pat4swe5owe1cue4ottsh4eos4e1ort4sce3ol4edieo2ge5of1tio4eno4enn5tiq4edoti4u1tive3my1tiz4othee2ct5laee2ft5lo4t1mee2mtme4e1meem5bcoi4to3be5exo1ry2tof1effel2iel2ftos24t1pe1la1traos2ceig2ei5de5ico2soe1h45egyeg5n", 29229 5: "_ach4e4go_e4goseg1ule5gurtre5feg4iceher4eg5ibeger44egaltre4mei5gle3imbe3infe1ingtra3beir4deit3eei3the5ity5triae4jud3efiteki4nek4la2trime4la_e4lactri4v4toute4law5toure3leaefil45elece4ledto2rae5len4tonye1lestro3ve4fic4tonoto3mytom4bto2mato5ice5limto2gre3lioe2listru5i4todo4ellaee4tyello4e5locel5ogeest4el2shel4tae5ludel5uge4mace4mage5man2t1n2ee2s4ee4p1e2mele4metee4naemi4eee4lyeel3i3tled3tle_e4mistlan4eed3iem3iztrus4emo4gti3zaem3pie4mule4dulemu3ne4dritiv4aedon2e4dolti3tle5neae5neeen3emtis4pti5sotis4m3tisee3newti3sae5niee5nile3nioedi5zen3ite5niu5enized1ited3imeno4ge4nosen3oven4swti5oc4t1s2en3uaen5ufe3ny_4en3zed3ibe3diae4oi4ede4s3tini4ed3deo3ret2ina2e2dae4culeo4toe5outec4te4t3t2t4tes2t1ine5pel4timpe2corephe4e4plie2col5tigutu3arti5fytu4bie3pro3tienep4sh5tidie4putt4icoeci4t4tick2ti2bec3imera4bti4aber3ar4tuf45tu3ier4bler3che4cib2ere_4thooecca54thil3thet4thea3turethan4e4cade4bitere4qe4ben5turieret4tur5oeav5oeav5itu5ry4tess4tes_ter5ve1rio4eriter4iueri4v1terier3m4ter3cte5pe4t1waer3noeast3er5obe5rocero4rer1oue3assea5sp1tent4ertler3twtwis4eru4t3tende1s4a3tenc5telsear2te2scateli4e3scres5cue1s2ee2sec3tel_te5giear5kear4cte5diear3ae3sha2t1ede5ande2sice2sid5tecttece44teattype3ty5phesi4uea4gees4mie2sole3acte2sone1a4bdys5pdy4sedu4petaun4d3uleta5sytas4e4tare4tarctar4ata5pl2estrta5mo4talke2surtal3idu5eleta4bta5lae3teoua5naet1ic4taf4etin4ta5doe5tir4taciuan4id1ucad1u1ae3trae3tre2d1s2syn5ouar2d4drowet3uaet5ymdro4pdril4dri4b5dreneu3rouar3ieute44draieu5truar3te2vasdop4pe5veadoo3ddoni4u4belsum3iev1erdoli4do4laev3idevi4le4vinevi4ve5voc2d5ofdo5dee4wage5wee4d1n4ewil54d5lue3wit2d3lou3ber5eye_u1b4i3dledfa3blfab3rfa4ce3dle_fain4suit3su5issu2g34d5lasu4b3fa3tasu1al4fato1di1vd2iti5disiuci4bfeas4di1redi4pl4feca5fectdio5gfe3life4mofen2d4st3wuc4it5ferr5diniucle3f4fesf4fie4stry1dinaf4flydi3ge3dictd4icedia5bs4tops1tle5stirs3tifs4ties1ticfic4is5tias4ti_4ficsfi3cuud3ers3thefil5iste2w4filyudev45finas4tedfi2nes2talfin4ns2tagde2tode4suflin4u1dicf2ly5ud5isu5ditde1scd2es_der5sfon4tu4don5dermss4lid4erhfor4is4siede2pudepi4fra4tf5reade3pade3nufril4frol5ud4side3nou4eneuens4ug5infu5el5dem_s5setfu5nefu3rifusi4fus4s4futade5lode5if4dee_5gal_3galiga3lo2d1eds3selg5amos2s5cssas3u1ing4ganouir4mgass4gath3uita4deaf5dav5e5dav44dato4darygeez44spotspor4s4pon4gelydark5s4ply4spio4geno4genydard5ge3omg4ery5gesigeth54getoge4tydan3g4g1g2da2m2g3gergglu5dach4gh3inspil4gh4to4cutr1gi4agia5rula5bspho5g4icogien5s2pheulch42sperspa4n5spai3c4utu1lenul4gigir4lg3islcu5pycu3picu4mic3umecu2maso5vi5glasu5liagli4bg3lig5culiglo3r4ul3mctu4ru1l4og4na_c3terul1tig2ning4nio4ultug4noncta4b4c3s2cru4dul5ulsor5dgo3isum5absor5ccris4go3nic4rinson4gsona45gos_cri5fcre4vum4bi5credg4raigran25solvsoft3so4ceunat44graygre4nco5zi4gritcoz5egruf4cow5ag5stecove4cos4es5menun4ersmel44corbco4pl4gu4tco3pacon5tsman3gy5racon3ghach4hae4mhae4th5aguha3lac4onecon4aun4ims3latu2ninhan4gs3ket5colocol5ihan4kuni3vhap3lhap5ttras4co4grhar2dco5agsir5aclim45sionhas5shaun44clichaz3acle4m1head3hearun3s4s3ingun4sws2ina2s1in4silysil4eh5elohem4p4clarhena45sidiheo5r1c4l4h4eras5icc2c1itu4orsh3ernshor4h3eryci3phshon34cipecion45cinoc1ingc4inahi5anhi4cohigh5h4il2shiv5h4ina3ship3cilihir4lhi3rohir4phir4rsh3iohis4ssh1inci4lau5pia4h1l4hlan44cier5shevcia5rhmet4ch4tish1erh5ods3cho2hoge4chi2z3chitho4mahome3hon4aho5ny3hoodhoon45chiouptu44ura_ho5ruhos4esew4ihos1p1housu4ragses5tu4rasur4behree5se5shs1e4s4h1s24chedh4tarht1enht5esur4fru3rifser4os4erlhun4tsen5gur1inu3riosen4dhy3pehy3phu1ritces5tur3iz4cesa4sencur4no4iancian3i4semeia5peiass45selv5selfi4atu3centse1le4ceniib5iaib3inseg3ruros43cencib3li3cell5cel_s5edli5bun4icam5icap4icar4s4ed3secticas5i4cayiccu44iceour4pe4ced_i5cidsea5wi2cipseas4i4clyur4pi4i1cr5icrai4cryic4teictu2ccon4urti4ic4umic5uoi3curcci4ai4daicch
29229a5ca4thscof4ide4s4casys4cliscle5i5dieid3ios4choid1itid5iui3dlei4domid3owu5sadu5sanid5uous4apied4ecany4ield3s4cesien4ei5enn4sceii1er_i3esci1estus3ciuse5as4cedscav5if4frsca4pi3fieu5siau3siccan4eiga5bcan5d4calous5sli3gibig3ilig3inig3iti4g4lus1trig3orig5oti5greigu5iig1ur2c5ah4i5i44cag4cach4ca1blusur4sat3usa5tab5utoi3legil1erilev4uta4b4butail3iail2ibil3io3sanc2ilitil2izsal4t5bustil3oqil4tyil5uru3tati4magsa5losal4m4ute_4imetbu3res3act5sack2s1ab4imitim4nii3mon4utelbumi4bu3libu4ga4inav4utenbsor42b5s2u4tis4briti3neervi4vr3vic4inga4inger3vey4ingir3ven4ingo4inguu4t1li5ni_i4niain3ioin1isbo4tor5uscrunk5both5b5ota5bos42i1no5boriino4si4not5borein3seru3in2int_ru4glbor5di5nusut5of5bor_uto5gioge4io2grbon4au5tonru3enu4touion3iio5phior3ibod3iio5thi5otiio4toi4ourbne5gb3lisrt4shblen4ip4icr3triip3uli3quar4tivr3tigrti4db4le_b5itzira4bi4racird5ert5ibi4refbi3tri4resir5gibi5ourte5oir4isr3tebr4tagbin4diro4gvac3uir5ul2b3ifis5agis3arisas52is1cis3chbi4eris3erbi5enrson3be5yor5shais3ibisi4di5sisbe3tw4is4krs3es4ismsbe5trr3secva4geis2piis4py4is1sbe3sp4bes4be5nuval5ois1teis1tirrys4rros44be5mis5us4ita_rron4i4tagrri4vi3tani3tatbe3lorri4or4reoit4esbe1libe5gu4itiarre4frre4cbe3giit3igbe3dii2tim2itio4itisrp4h4r3pet4itonr4peait5rybe3debe3dai5tudit3ul4itz_4be2dbeat3beak4ro4varo4tyros4sro5roiv5ioiv1itror3i5root1roomval1ub3berva5mo4izarva5piron4eban3ijac4qban4ebal1ajer5srom4prom4iba4geazz5i5judgay5alax4idax4ickais4aw4ly3awaya1vorav5ocav3igke5liv3el_ve4lov4elyro1feke4tyv4erdv4e2sa5vanav3ag5k2ick4illkilo5au1thk4in_4ves_ro3crkin4gve4teaun5dk5ishau4l2au3gu4kleyaugh3ve4tyk5nes1k2noat3ulkosh4at5uekro5n4k1s2at5uaat4that5te5vianat4sk5vidil4abolaci4l4adela3dylag4nlam3o3landrob3la4tosr4noular4glar3ilas4ea4topr3nivr3nita2tomr5nica4toglbin44l1c2vi5gnat3ifat1ica5tiar3neyr5net4ati_ld5isat4hol4driv2incle4bileft55leg_5leggr4nerr3nel4len_3lencr4nar1lentle3phle4prvin5dler4e3lergr3mitl4eroat5evr4mio5lesq3lessr3menl3eva4vingrma5cvio3lvi1ou4leyevi5rovi3so4l1g4vi3sulgar3l4gesate5cat5apli4agli2amr3lo4li4asr4lisli5bir4ligr2led4lics4vitil4icul3icyl3idaat5ac3lidirk4lel4iffli4flr3ket3lighvit3r4vityriv3iri2tulim3ili4moris4pl4inar3ishris4clin3ir4is_li5og4l4iqlis4pas1trl2it_as4shas5phri2pla4socask3ia3sicl3kallka4ta3sibl4lawashi4l5leal3lecl3legl3lel5riphas4abar2shrin4grin4ear4
29229sarin4dr2inal5lowarre4l5met3rimol4modlmon42l1n2a3roorim5ilo4civo4la5rigil5ogo3loguri5et5longlon4iri1erlood5r4icolop3il3opmlora44ricir4icerib3a5los_v5oleri4agria4blos4tlo4taar2mi2loutar2izar3iolpa5bl3phal5phi4rhall3pit5voltar4im3volv2l1s2vom5ivori4l4siear4fllt5agar4fivo4rylten4vo4talth3ia3reeltis4ar4drw5ablrgo4naraw4lu3brluch4lu3cilu3enwag5olu5idlu4ma5lumia5raur5gitwait5luo3rw5al_luss4r5gisar4atl5venrgi4nara3pwar4tar3alwas4tly5mely3no2lys4l5ysewa1teaque5ma2car3gicma4clr3get5magnwed4nmaid54maldrg3erweet3wee5vwel4lapoc5re4whwest3ap3in4aphires2tr4es_mar3vre5rumas4emas1t5matemath3rero4r4eriap5atr1er4m5bilre1pumbi4vapar4a5nuran3ul4med_an3uare5lure1lian4twre5itmel4tan2trre4fy4antomen4are3fire2fe4menemen4imens4re1de3ment2r2edme5onre4awwin4g5reavme4tare3anme1tere1alm4etr3wiserdin4rdi4aan4stwith3an2span4snan2samid4amid4gan5otwl4esr4dalm4illmin4a3mindrcum3rc4itr3charcen4min4tm4inumiot4wl3ina3niumis5lan3ita3nip4mithan3ioan1gla3neuws4per2bina3nena5neem4ninw5s4tan1dl4mocrrbi4fmo2d1mo4gomois2xac5ex4agor4bagmo3mer4baba3narrau4ta5monrare4rar5cra5nor4aniam1inr2amiam5ifra4lomo3spmoth3m5ouf3mousam3icxer4ixe5roraf4tr5aclm3petra3bixhil5mpi4aam3ag3quetm5pirmp5is3quer2que_qua5vmpov5mp4tram5ab3alyz4m1s25alyt4alysa4ly_ali4exi5di5multx4ime4aldia4laral3adal5abak1enain5opu3trn4abu4nac_na4can5act5putexpe3dna4lia4i4n4naltai5lya3ic_pur4rag5ulnank4nar3c4narenar3inar4ln5arm3agognas4c4ag4l4ageupul3cage4oaga4na4gab3nautnav4e4n1b4ncar5ad5umn3chaa3ducptu4rpti3mnc1innc4itad4suad3owad4len4dain5dana5diua3ditndi4ba3dion1ditn3dizn5ducndu4rnd2we3yar4n3eara3dianeb3uac4um5neckac3ulp4siba3cio5negene4laac1inne5mine4moa3cie4nene4a2cine4poyc5erac1er2p1s2pro1tn2erepro3lner4rych4e2nes_4nesp2nest4neswpri4sycom4n5evea4carab3uln4gabn3gelpre3vpre3rycot4ng5han3gibng1inn5gitn4glangov4ng5shabi5an4gumy4erf4n1h4a5bannhab3a5bal3n4iani3anni4apni3bani4bl_us5ani5dini4erni2fip3petn5igr_ure3_un3up3per_un5op3pennin4g_un5k5nis_p5pel_un1en4ithp4ped_un1ani3tr_to4pympa3_til4n3ketnk3inyn5ic_se2ny4o5gy4onsnmet44n1n2_ru4d5pounnni4vnob4lpo4tan5ocly4ped_ro4qyper5noge4pos1s_ri4gpo4ry1p4or_res2no4mono3my_ree2po4ninon5ipoin2y4poc5po4gpo5em5pod_4noscnos4enos5tno5tayp2ta3noun_ra4cnowl3_pi2tyra5m_pi4eyr5ia_out3_oth32n1s2ns5ab_or3t_or1d_or3cplu4mnsid1nsig4y3s2eys3ion4socns4pen5spiploi4_odd5nta4bpli4n_ni4cn5tib4plignti2fpli3a3plannti4p1p2l23ysis2p3k2ys3ta_mis1nu5enpi2tun3uinp3ithysur4nu1men5umi3nu4nyt3icnu3trz5a2b_li4t_li3o_li2n_li4g_lev1_lep5_len4pion4oard3oas4e3pi1ooat5ip4inoo5barobe4l_la4mo2binpind4_ju3rob3ul_is4i_ir5rp4in_ocif3o4cil_in3so4codpi3lopi3enocre33piec5pidipi3dep5ida_in2kod3icodi3oo2do4odor3pi4cypian4_ine2o5engze3rooe4ta_im3m_id4l_hov5_hi3b_het3_hes3_go4r_gi4bpho4ro5geoo4gero3gie3phobog3it_gi5azo5ol3phizo4groogu5i4z1z22ogyn_fes3ohab5_eye55phieph1icoiff4_en3sph4ero3ing_en3go5ism_to2qans3v_el5d_eer4bbi4to3kenok5iebio5mo4lanper1v4chs_old1eol3erpe5ruo3letol4fi_du4co3liaper3op4ernp4erio5lilpe5ono5liop4encpe4la_do4tpee4do5livcin2q3pediolo4rol5pld3tabol3ub3pedeol3uno5lusedg1le1loaom5ahoma5l2p2edom2beom4bl_de3o3fich3pe4ao4met_co4ro3mia_co3ek3shao5midom1inll1fll3teapa2teo4monom3pi3pare_ca4tlue1pon4aco3nanm2an_pa4pum2en_on5doo3nenng1hoon4guon1ico3nioon1iso5niupa3nypan4ao3nou_bri2pain4ra1oronsu4rk1hopac4tpa4ceon5umonva5_ber4ood5eood5i6rks_oop3io3ordoost5rz1scope5dop1erpa4ca_ba4g_awn4_av4i_au1down5io3pito5pon1sync_as1s_as1p_as3ctch1c_ar5so5ra_ow3elo3visov4enore5auea1mor3eioun2d_ant4orew4or4guou5etou3blo5rilor1ino1rio_ang4o3riuor2miorn2eo5rofoto5sor5pe3orrhor4seo3tisorst4o3tif_an5cor4tyo5rum_al3tos3al_af1tos4ceo4teso4tano5scros2taos4poos4paz2z3wosi4ue3pai", 29230 6: "os3ityos3itoz3ian_os4i4ey1stroos5tilos5titxquis3_am5atot3er_ot5erso3scopor3thyweek1noth3i4ot3ic_ot5icao3ticeor3thiors5enor3ougor3ityor3icaouch5i4o5ria_ani5mv1ativore5sho5realus2er__an3teover3sov4erttot3icoviti4o5v4olow3dero4r3agow5esto4posiop3ingo5phero5phanthy3sc3operaontif5on3t4ionten45paganp3agattele2gonspi4on3omyon4odipan3elpan4tyon3keyon5est3oncil_ar4tyswimm6par5diompro5par5elp4a4ripar4isomo4gepa5terst5scrpa5thy_atom5sta1tio5miniom3icaom3ic_ss3hatsky1scpear4lom3ena_ba5naol3umer1veilpedia4ped4icolli4er1treuo5liteol3ishpeli4epe4nano5lis_pen4thol3ingp4era_r1thoup4erago3li4f_bas4er1krauperme5ol5id_o3liceper3tio3lescolass4oi3terpe5tenpe5tiz_be5raoi
292305son_be3smphar5iphe3nooi5letph4es_oi3deroic3esph5ingr3ial_3ognizo5g2ly1o1gis3phone5phonio5geneo4gatora3mour2amenofit4tof5itera3chupi4ciepoly1eod5dedo5cureoc3ula1pole_5ocritpee2v1param4oc3raco4clamo3chetob5ingob3a3boast5eoke1st3nu3itpi5thanuf4fentu3meoerst2o3chasplas5tn3tinepli5ernti4ernter3sntre1pn4s3esplum4bnsati4npre4cns4moonon1eqnor5abpo3et5n5lessn5oniz5pointpoly5tnon4agnk3rup3nomicng1sprno5l4inois5i4n3o2dno3blenni3aln5keroppa5ran3itor3nitionis4ta5nine_ni3miznd3thrmu2dron3geripray4e5precipre5copre3emm3ma1bpre4lan5gerep3rese3press_can5cmedi2c5pri4e_ce4la3neticpris3op3rocal3chain4er5ipros3en4erarnera5bnel5iz_cit5rne4gatn5d2ifpt5a4bjanu3aign4itn3chisn5chiln5cheon4ces_nau3seid4iosna3talnas5tinan4itnanci4na5mitna5liahnau3zput3er2n1a2bhex2a3hatch1multi3hair1sm4pousg1utanmpo3rim4p1inmp5iesmphas4rach4empar5iraf5figriev1mpara5mo5seyram3et4mora_rane5oran4gemo3ny_monol4rap3er3raphymo3nizgno5morar5ef4raril1g2nacg1leadmoni3ara5vairav3elra5ziemon5gemon5etght1wemoi5sege3o1dmma5ryr5bine3fluoren1dixmis4ti_de3ra_de3rie3chasrch4err4ci4bm4inglm5ineedu2al_3miliame3tryrdi4er_des4crd3ingdi2rerme5thimet3alre5arr3mestim5ersadi2rende2ticdes3icre4cremen4temensu5re3disred5itre4facmen4dede2mosmen5acmem1o3reg3ismel5onm5e5dyme3died2d5ibren4te5mediare5pindd5a5bdata1bmba4t5cle4arma3tisma5scemar4lyre4spichs3huma5riz_dumb5re3strre4terbrus4qre3tribio1rhre5utiman3izre4valrev3elbi1orbbe2vie_eas3ire5vilba1thyman5is5maniamal4tymal4lima5linma3ligmag5inav3ioul5vet4rg3inglus3teanti1dl5umn_ltur3a_el3emltera4ltane5lp5ingloun5dans5gra2cabllos5etlor5ouric5aslo5rie_enam35ricidri4cie5lope_rid5erri3encri3ent_semi5lom3errig5an3logicril3iz5rimanlob5allm3ingrim4pell5out5rina__er4ril5linal2lin4l3le4tl3le4nriph5eliv3er_ge5og_han5k_hi3er_hon3olin3ea1l4inel4im4p_idol3_in3ci_la4cy_lath5rit3iclim4blrit5urriv5elriv3et4l4i4lli4gra_leg5elif3errk4linlid5er4lict_li4cor5licioli4atorl5ish_lig5a_mal5o_man5a_mer3c5less_rm5ersrm3ingy3thinle5sco3l4erilera5b5lene__mon3ele4matld4erild4erela4v4ar1nis44lativ_mo3rola5tanlan4telan5etlan4dllab3ic_mu5takin4dek3est_ro5filk3en4dro5ker5role__of5te4jestyys3icaron4al5izont_os4tlron4tai4v3ot_pe5tero3pelrop3ici5voreiv5il__pio5n_pre3mro4the_ran4tiv3en_rov5eliv3ellit3uati4tramr5pentrp5er__rit5ui4tismrp3ingit5ill_ros5tit3ica4i2tici5terirre4stit3era4ita5mita4bi_row5dist4lyis4ta_is4sesrsa5tiissen4is4sal_sci3erse4crrs5er_islan4rse5v2yo5netish5opis3honr4si4bis5han5iron_ir4minrtach4_self5iri3turten4diri5dei4rel4ire4de_sell5r4tieriq3uidrtil3irtil4lr4tilyr4tistiq5uefip4re4_sing4_ting4yn3chrru3e4lion3at2in4th_tin5krum3pli4no4cin3ityrun4ty_ton4aruti5nymbol5rvel4i_top5irv5er_r5vestin5geni5ness_tou5s_un3cein3cerincel45ryngei4n3auim3ulai5miniimi5lesac3riim5ida_ve5rasalar4ima5ryim3ageill5abil4istsan4deila5rai2l5am_wil5ii4ladeil3a4bsa5voright3iig3eraab5erd4ific_iff5enif5eroi3entiien5a45ie5gaidi5ou3s4cieab5latidi4arid5ianide3al4scopyab5rogid5ancic3ulaac5ardi2c5ocic3ipaic5inase2c3oi4carai4car_se4d4ei2b5riib5iteib5it_ib5ertib3eraac5aroi4ativ4ian4tse4molsen5ata5ceouh4warts5enedhus3t4s5enin4sentd4sentlsep3a34s1er_hun5kehu4min4servohro3poa5chethov5el5se5umhouse3sev3enho5senhort3eho5rishor5at3hol4ehol5arh5odizhlo3riac5robhis3elhion4ehimer4het4edsh5oldhe2s5ph5eroushort5here5aher4bahera3p3side_5sideshen5atsi5diz4signahel4lyact5ifhe3l4ihe5do55sine_h5ecathe4canad4dinsion5aad5er_har4lehard3e3sitioha5rasha3ranhan4tead3icahang5oadi4ersk5inesk5ing5hand_han4cyhan4cislith5hala3mh3ab4lsmall32g5y3n5gui5t3guard5smithad5ranaeri4eag5ellag3onia5guerso4labsol3d2so3licain5in4grada3s4on_gor5ougo5rizgondo5xpan4dait5ens5ophyal3end3g4o4ggnet4tglad5i5g4insgin5ge3g4in_spen4d2s5peog3imen5gies_3spher5giciagh5outsp5ingge5nizge4natge5lizge5lisgel4inxi5miz4gativgar5n4a5le5oga3nizgan5isga5mets5sengs4ses_fu4minfres5cfort5assi4erss5ilyfore5tfor5ayfo5ratal4ia_fon4dessur5aflo3ref5lessfis4tif1in3gstam4i5stands4ta4p5stat_fin2d5al5levs5tero4allicstew5afight5fi5del5ficie5ficiafi3cer5stickf3icena5log_st3ingf3icanama5ra5stockstom3a5stone2f3ic_3storef2f5iss4tradam5ascs4trays4tridf5fin_fend5efeath3fault5fa3thefar5thfam5is4fa4mafall5eew3inge5verbeven4ie5vengevel3oev3ellev5asteva2p5euti5let5roset3roget5rifsy5rinet3ricet5onaam5eraam5ilyami4noamor5ieti4noe5tidetai5loethod3eten4dtal5enes5urramp5enan3ageta5loge5strotan4detanta3ta5pere3ston4es2toes5times3tigta3rizestan43analy4taticta4tures4prean3arces3pertax4ises5onaes3olue5skintch5etanar4ies4i4ntead4ie2s5ima3natiande4sesh5enan3disan4dowang5iete5geres5ences5ecres5cana4n1icte2ma2tem3at3tenanwrita45erwau4tenesert3era3nieser3set5erniz4erniter4nis5ter3de4rivaan3i3fter3isan4imewo5vener3ineeri4ere3rient3ess_teth5e5ericke1ria4er3ester5esser3ent4erenea5nimier5enaer3emoth3easthe5atthe3iser5el_th5ic_th5icaere3in5thinkere5coth5odea5ninee3realan3ishan4klier4che5anniz4erandti4atoanoth5equi3lep5utat4ic1uan4scoe4probep3rehe4predans3poe4precan4surantal4e3pe
29230nttim5ulep5anceo5rol3tine_eop3aran4tiewin4deap5eroen3ishen5icsen3etren5esten5esien5eroa3pheren3dicap3itae4nanten5amoem5ulaa3pituti3zen5emnize5missem5ishap5olaem5ine3tles_t5let_em1in2apor5iem3icaem5anael3op_el4labapos3te3liv3el5ishaps5esweath3e3lierel3icaar3actwa5verto3nate3libee4l1erel3egato3rietor5iza5radeelaxa4aran4gto3warelan4dej5udie5insttra5chtraci4ar5av4wa5gere5git5arbal4ar5easeg5ing4voteetrem5iar3enta5ressar5ial4tricsvor5abe3finetro5mitron5i4tronyar3iantro3sp5eficia3rieted5uloed3icae4d1erec3ulaec4tane4cremeco5roec3orae4concar5o5de4comme4cluse4clame5citeec5ifya5ronias3anta5sia_tu4nis2t3up_ecan5ce4belstur3ise4bel_eav3ene4a3tue5atifeath3ieat5eneart3eear4ilear4icear5eseam3ereal3oueal5erea5geread5iedum4be4ducts4duct_duc5eras3tenasur5adrea5rat3abl4d5outdo3natdom5izdo5lor4dlessu4bero3dles_at3alou3ble_d4is3tdirt5idi5niz3dine_at5ech5di3endi4cam1d4i3ad3ge4tud5estdev3ilde3strud3iedud3iesdes3tide2s5oat3egovis3itde4nardemor5at3en_uen4teuer4ilde5milat3eraugh3en3demicater5nuil5izdeli4ede5comde4cildecan4de4bonv3io4rdeb5it4dativ2d3a4bat3estu5laticu4tie5ulcheul3dercuss4icu5riaath5em3cultua5thenul3ingul5ishul4lar4vi4naul4liscu5ityctim3ic4ticuuls5esc5tantultra3ct5angcros4ecrop5ocro4pl5critiath5omum4blycre3at5vilitumor5oat5i5b5crat_cras5tcoro3ncop3iccom5ercol3orun5ishco3inc5clareat3ituunt3abat5ropun4tescit3iz4cisti4cista4cipicc5ing_cin3em3cinatuper5s5videsup3ingci2a5b5chini5videdupt5ib5vide_at4tag4ch1inch3ersch3er_ch5ene3chemiche5loure5atur4fercheap3vi5aliat3uravet3er4ch3abc5e4taau5sib3cessives4tece5ram2cen4e4cedenccou3turs5erur5tesur3theaut5enur4tiecav5al4cativave4nover3thcar5omca5percan4tycan3izcan5iscan4icus4lin3versecal4laver3ieca3latca5dencab3in3butiobuss4ebus5iebunt4iv4eresuten4i4u1t2iv3erenu3tineut3ingv4erelbroth35u5tizbound34b1orabon5at5vere_bom4bibol3icblun4t5blespblath5av3erav5enuebi3ogrbi5netven3om2v1a4bvac5ilbi3lizbet5izbe5strva5liebe5nigbbi4nabas4siva5nizbari4aav5ernbarbi5av5eryvel3liazi4eravi4er", 29231 7: "_dri5v4ban5dagvar5iedbina5r43bi3tio3bit5ua_ad4derution5auti5lizver5encbuf4ferus5terevermi4ncall5incast5ercas5tigccompa5z3o1phros5itiv5chanicuri4fico5stati5chine_y5che3dupport54v3iden5cific_un4ter_at5omiz4oscopiotele4g5craticu4m3ingv3i3liz4c3retaul4li4bcul4tiscur5a4b4c5utiva5ternauiv4er_del5i5qdem5ic_de4monsdenti5fdern5izdi4latou4b5ingdrag5on5drupliuar5ant5a5si4tec5essawo4k1enec5ifiee4compear5inate4f3eretro5phewide5sp5triciatri5cesefor5ese4fuse_oth5esiar5dinear4chantra5ventrac4tetrac4itar5ativa5ratioel5ativor5est_ar5adisel5ebraton4alie4l5ic_wea5rieel5igibe4l3ingto5cratem5igraem3i3niemoni5oench4erwave1g4a4pillavoice1ption5eewill5inent5age4enthesvaude3vtill5inep5recaep5ti5bva6guer4erati_tho5rizthor5it5thodicer5ence5ternitteri5zater5iesten4tage4sage_e4sagese4sert_an5est_e4sertse4servaes5idenes5ignaesis4tees5piraes4si4btal4lisestruc5e5titioounc5erxe4cutota5bleset5itiva4m5atoa4matis5stratu4f3ical5a5lyst4ficatefill5instern5isspend4gani5zasqual4la4lenti4g3o3nas5ophiz5sophicxpecto55graph_or5angeuri4al_4graphy4gress_smol5d4hang5erh5a5nizharp5enhar5terhel4lishith5erhro5niziam5eteia4tricic4t3uascour5au2r1al_5scin4dover4nescan4t55sa3tiou5do3ny_ven4de_under5ty2p5al_anti5sylla5bliner4arturn3ari5nite_5initioinsur5aion4eryiphras4_tim5o5_ten5an_sta5blrtroph4_se5rieiq3ui3t5i5r2izis5itiviso5mer4istral5i5ticki2t5o5mtsch3ie_re5mittro3fiti4v3er_i4vers_ros5per_pe5titiv3o3ro_ped5alro5n4is_or5ato4jestierom5ete_muta5bk5iness4latelitr4ial__mist5i_me5terr4ming_lev4er__mar5tilev4eralev4ers_mag5a5liar5iz5ligaterit5ers_lat5errit5er_r5ited__im5pinri3ta3blink5er_hon5ey5litica_hero5ior5aliz_hand5irip5lic_gen3t4tolo2gylloqui5_con5grt1li2erbad5ger4operag_eu4lertho3donter2ic__ar4tie_ge4ome_ge5ot1_he3mo1_he3p6a_he3roe_in5u2tpara5bl5tar2rht1a1mintalk1a5ta3gon_par5age_aster5_ne6o3f_noe1thstyl1is_poly1s5pathic_pre1ampa4tricl3o3niz_sem4ic_semid6_semip4_semir45ommend_semiv4lea4s1a_spin1oom5etryspher1o_to6poglo4ratospe3cio3s2paceso2lute_we2b1l_re1e4ca5bolicom5erseaf6fishside5swanal6ysano5a2cside5stl5ties_5lumniasid2ed_anti1reshoe1stscy4th1s4chitzsales5wsales3cat6tes_augh4tlau5li5fom5atizol5ogizo5litiorev5olure5vertre5versbi5d2ifbil2lab_earth5pera5blro1tronro3meshblan2d1blin2d1blon2d2bor1no5ro1bot1re4ti4zr5le5quperi5stper4malbut2ed_but4tedcad5e1moist5enre5stalress5ibchie5vocig3a3roint5er4matizariv1o1lcous2ticri3tie5phisti_be5stoog5ativo2g5a5rr3a3digm4b3ingre4posir4en4tade4als_od5uctsquasis6quasir6re5fer_p5trol3rec5olldic1aiddif5fra3pseu2dr5ebrat5metric2d1lead2d1li2epro2g1epre1neuod5uct_octor5apoin3came5triem5i5liepli5narpara3memin5glim5inglypi4grappal6matmis4er_m5istryeo3graporth1riop1ism__but4tio3normaonom1icfeb1ruafermi1o_de4moio5a5lesodit1icodel3lirb5ing_gen2cy_n4t3ingmo5lestration4get2ic_4g1lishobli2g1mon4ismnsta5blmon4istg2n1or_nov3el3ns5ceivno1vembmpa5rabno4rarymula5r4nom1a6lput4tinput4tedn5o5miz_cam4penag5er_nge5nesh2t1eoun1dieck2ne1skiifac1etncour5ane3backmono1s6mono3chmol1e5cpref5ac3militapre5tenith5i2lnge4n4end5est__capa5bje1re1mma1la1ply5styr1kovian_car5olprin4t3lo2ges_l2l3ishprof5it1s2tamp", 29232 8: "lead6er_url5ing_ces5si5bch5a5nis1le1noidlith1o5g_chill5ilar5ce1nym5e5trych5inessation5arload4ed_load6er_la4c3i5elth5i2lyneg5ativ1lunk3erwrit6er_wrap3arotrav5es51ke6linga5rameteman3u1scmar1gin1ap5illar5tisticamedio6c1me3gran3i1tesima3mi3da5bves1titemil2l1agv1er1eigmi6n3is_1verely_e4q3ui3s5tabolizg5rapher5graphicmo5e2lasinfra1s2mon4ey1lim3ped3amo4no1enab5o5liz_cor5nermoth4et2m1ou3sinm5shack2ppo5sitemul2ti5uab5it5abimenta5rignit1ernato5mizhypo1thani5ficatuad1ratu4n5i4an_ho6r1ic_ua3drati5nologishite3sidin5dling_trib5utin5glingnom5e1non1o1mistmpos5itenon1i4so_re5stattro1p2istrof4ic_g2norespgnet1ism5glo5binlem5aticflow2er_fla1g6elntrol5lifit5ted_treach1etra1versl5i5ticso3mecha6_for5mer_de5rivati2n3o1me3spac6i2t3i4an_thy4l1antho1k2er_eq5ui5to4s3phertha4l1amt3ess2es3ter1geiou3ba3dotele1r6ooxi6d1iceli2t1isonspir5apar4a1leed1ulingea4n3iesoc5ratiztch3i1er_kil2n3ipi2c1a3dpli2c1abt6ap6athdrom3e5d_le6icesdrif2t1a_me4ga1l1prema3cdren1a5lpres2plipro2cess_met4ala3do5word1syth3i2_non1e2m_post1ampto3mat4rec5ompepu5bes5cstrib5utqu6a3si31stor1ab_sem
292326is4star3tliqui3v4arr1abolic_sph6in1de5clar12d3aloneradi1o6gs3qui3tosports3wsports3cra5n2hascro5e2cor3bin1gespokes5wspi2c1il_te3legrcroc1o1d_un3at5t_dictio5cat1a1s2buss4ingbus6i2esbus6i2erbo2t1u1lro5e2las1s2pacinb1i3tivema5rine_r3pau5li_un5err5r5ev5er__vi2c3arback2er_ma5chinesi5resid5losophyan3ti1n2sca6p1ersca2t1olar2rangesep3temb1sci2uttse3mes1tar3che5tsem1a1ph", 29233 9: "re4t1ribuuto5maticl3chil6d1a4pe5able1lec3ta6bas5ymptotyes5ter1yl5mo3nell5losophizlo1bot1o1c5laratioba6r1onierse1rad1iro5epide1co6ph1o3nscrap4er_rec5t6angre2c3i1prlai6n3ess1lum5bia_3lyg1a1miec5ificatef5i5nites2s3i4an_1ki5neticjapan1e2smed3i3cinirre6v3ocde2c5linao3les3termil5li5listrat1a1gquain2t1eep5etitiostu1pi4d1v1oir5du1su2per1e6_mi1s4ers3di1methy_mim5i2c1i5nitely_5maph1ro15moc1ra1tmoro6n5isdu1op1o1l_ko6r1te1n3ar4chs_phi2l3ant_ga4s1om1teach4er_parag6ra4o6v3i4an_oth3e1o1sn3ch2es1to5tes3toro5test1eror5tively5nop5o5liha2p3ar5rttrib1ut1_eth1y6l1e2r3i4an_5nop1oly_graph5er_5eu2clid1o1lo3n4omtrai3tor1_ratio5na5mocratiz_rav5en1o", 29234 10: "se1mi6t5ic3tro1le1um5sa3par5iloli3gop1o1am1en3ta5bath3er1o1s3slova1kia3s2og1a1myo3no2t1o3nc2tro3me6c1cu2r1ance5noc3er1osth1o5gen1ih3i5pel1a4nfi6n3ites_ever5si5bs2s1a3chu1d1ri3pleg5_ta5pes1trproc3i3ty_s5sign5a3b3rab1o1loiitin5er5arwaste3w6a2mi1n2ut1erde3fin3itiquin5tes5svi1vip3a3r", 29235 11: "pseu3d6o3f2s2t1ant5shimi1n2ut1estpseu3d6o3d25tab1o1lismpo3lyph1onophi5lat1e3ltravers3a3bschro1ding12g1o4n3i1zat1ro1pol3it3trop1o5lis3trop1o5lesle3g6en2dreeth1y6l1eneor4tho3ni4t", 29236 12: "3ra4m5e1triz1e6p3i3neph1" 29237 }, 29238 patternChars: "_abcdefghijklmnopqrstuvwxyz", 29239 patternArrayLength: 113949, 29240 valueStoreLength: 20195 29241}; 29242 29243// For questions about the spanish hyphenation patterns 29244// ask Luis Pabon (lpabon at metagrama dot es) 29245/*global Hyphenator*/ 29246Hyphenator.languages['es'] = { 29247 leftmin: 2, 29248 rightmin: 2, 29249 specialChars: "áéÃóúñ", 29250 patterns: { 29251 2: "1b1c1d1f1g1j1k1l1m1n1ñ1p1q1r1s1t1v1w1x1y1z", 29252 3: "_a22bb2bc2bd2bf2bg2bj2bkb2l2bm2bn2bp2bqb2r2bs2bt2bv2bw2bx2by2bz2cb2cc2cd2cf2cgc4h2cjc2kc2l2cm2cn2cp2cqc2r2cs2ct2cv2cw2cx2cy2cz2db2dc2dd2df2dg2dj2dk2dl2dm2dn2dp2dqd2r2ds2dt2dv2dw2dx2dy2dz4e_4é_4és2fb2fc2fd2ff2fg2fj2fkf2l2fm2fn2fp2fqf2r2fs2ft2fv2fw2fx2fy2fz2gb2gc2gd2gf2gg2gj2gkg2l2gm2gn2gp2gqg2r2gs2gt2gv2gw2gx2gy2gz2hb2hc2hd2hf2hg2hj2hk2hl2hm2hn2hp2hq2hr2hs2ht2hv2hw2hx2hy2hz4Ã_2jb2jc2jd2jf2jg2jj2jk2jl2jm2jn2jp2jq2jr2js2jt2jv2jw2jx2jy2jz2kb2kc2kd2kf2kg2kj2kkk2l2km2kn2kp2kqk2r2ks2kt2kv2kw2kx2ky2kz2lb2lc2ld2lf2lg2lj2lkl4l2lm2ln2lp2lq2lr2ls2lt2lv2lw2lx2ly2lz2mb2mc2md2mf2mg2mj2mk2ml2mm2mn2mp2mq2mr2ms2mt2mv2mw2mx2my2mz2nb2nc2nd2nf2ng2nj2nk2nl2nm2nn2np2nq2nr2ns2nt2nv2nw2nx2ny2nz2o_2pb2pc2pd2pf2pg2pj2pkp2l2pm2pn2pp2pqp2r2ps2pt2pv2pw2px2py2pz2qb2qc2qd2qf2qg2qj2qk2ql2qm2qn2qp2qq2qr2qs2qt2qv2qw2qx2qy2qz2rb2rc2rd2rf2rg2rj2rk2rl2rm2rn2rp2rqr2r2rs2rt2rv2rw2rx2ry2rz2sb2sc2sd2sf2sg2sj2sk2sl2sm2sn2sp2sq2sr2ss2st2sv2sw2sx2sy2sz2tb2tc2td2tf2tg2tj2tk2tm2tn2tp2tqt2r2ts2tt2tv2twt2x2ty2tz2vb2vc2vd2vf2vg2vj2vkv2l2vm2vn2vp2vqv2r2vs2vt2vv2vw2vx2vy2vz2wb2wc2wd2wf2wg2wj2wkw2l2wm2wn2wp2wqw2r2ws2wt2wv2ww2wx2wy2wz2xb2xc2xd2xf2xg2xj2xk2xl2xm2xn2xp2xq2xr2xs2xt2xv2xw2xx2xy2xz2yb2yc2yd2yf2yg2yj2yk2yl2ym2yn2yp2yq2yr2ys2yt2yv2yw2yx2yy2yz2zb2zc2zd2zf2zg2zj2zk2zl2zm2zn2zp2zq2zr2zs2zt2zv2zw2zx2zy2zz", 29253 4: "4ad_2al_4an_4ar_4as_4ás_2b1h2bl_2br_2ch_2cl_4cn_2cr_4ct_4cz_2d1h2dr_4ed_4en_4er_4es_2f1h2fl_2fr_4ft_2g2h2gl_4gn_2gr_2h1hi2a_4Ãa_i2o_2j1h2k2h2kl_2kr_2l1h2ll_mal22m1h4mn_2n1h2no_4ón_2os_4pc_2p1h2pl_4pn_2pr_4pt_2q1h2r1h2rr_3sa_2s1h2t1h2t2l2tr_4ts_4tz_2v1h2vl_2vr_2w1h2wl_2wr_2x1h2y1h2z1h", 29254 5: "_an3h4áis_4ando4aos_bien2bio1heco1h4éis_4eos_geo1h4Ãan_i2as_4Ãas_i2os_iso1hmal3bmal3cmal3dmal3fmal3gmal3mmal3pmal3qmal3smal3tmal3v4meo_neo1ho2os_2ótic3sas_s3te_", 29255 6: "_an2a2_an2á2_an2e2_an2é2_an2i2_an2Ã2_ani3m_aniña_ani3q_an2o2_an2ó2_an2u2_anu3l_bi1ox_bi1un_co2a2_co2á2_co2e2_co2é2_co2i2_co2Ã2_co3o4_co2ó2_co2u2_co2ú2_en2a2_en2á2_en2e2_en2é2_en1ej_en2i2_en2Ã2_en2o2_en2ó2_en2u2_en2ú2_in2a2_in2á2_in2e2_in2é2_in2i2_in2Ã2_in2o2_in2ó2_in2u2_in2ú2_re2a2_re2á2_re3e4_re2é2_re2i2_re2Ã2_re2o2_re2ó2_re1oc_re1oj_re2u2_re2ú24a3ba_acto1h4a3da_4adle_4adlo_4adme_4a3do_4adte_aero1hafro1haÃ5so_2ales_ana3lÃanfi1hante1h4a3ra_4a3rá_4a3re_4a3ré_a3rio_4a3se_4aste_asu3b24ates_auto1h2b3c2n2b3c2t2b3c2z2b3f2t2b3g2nbien3hbien3mbien3qbien3tbien3vbio1a2bio1á2bio1e2bio1é2bio1i2bio1Ã2bio1o2bio1ó2bio1u2bio1ú22b3m2n2b3p2n2b3p2s2b3p2t2b3t2s2b3t2z4caca44caga44cago42c3c2n2c3c2t2c3c2z2c3f2t2c3g2ncito1h2c3m2nco4artco4ártco4ercco4erzco4optco4ord2c3p2n2c3p2s2c3p2t2c3t2s2c3t2z4culo42d3c2n2d3c2t2d3c2zdeca1hde3seo2d3f2t2d3g2n2d3m2n2d3p2n2d3p2s2d3p2t2d3t2s2d3t2zeco1a2eco1á2eco1e2eco1é2eco1i2eco1Ã2eco1o2eco1ó2eco1u2eco1ú24edle_4edlo_4edme_4edte_emi2o2endo1hento1h4e3rá_4e3ré_4erla_4erle_4erlo_4erme_4erse_4erte_euco1heuro1hfono1hfoto1hgeo1a2geo1á2geo1e2geo1é2geo1i2geo1Ã2geo1o2geo1ó2geo1u2geo1ú2hemi1hhemo1hhexa1hhomo1h4Ãais_2i3ca_2i3co_4Ã3da_4Ã3do_4i4er_4i3ga_4i3go_4Ãsmo_iso1a2iso1á2iso1e2
29255iso1é2iso1i2iso1Ã2iso1o2iso1ó2iso1u2iso1ú24Ãsta_kilo1h2l3c2n2l3c2t2l3c2z2l3f2t2l3g2n2l3m2n2l3p2n2l3p2s2l3p2t2l3t2s2l3t2zma4l3hmaxi1h2m3c2n2m3c2t2m3c2zmega1h2m3f2t2m3g2nmili1hmini1h2m3m2nmono1h2m3p2n2m3p2s2m3p2t2m3t2s2m3t2znamo1h2n3c2n2n3c2t2n3c2zneo1a2neo1á2neo1e2neo1é2neo1i2neo1Ã2neo1o2neo1ó2neo1u2neo1ú2neto1h2n3f2t2n3g2n2n3m2n2n3p2n2n3p2s2n3p2t2n3t2s2n3t2zocta1hocto1homni1h4ones_2o3sa_2o3so_para1h4pedo4poli1h3p2sic3p2siq4puta44puto42r3c2n2r3c2t2r3c2z2r3f2t2r3g2n2r3m2nromo1h2r3p2n2r3p2s2r3p2t2r3t2s2r3t2z2s3c2n2s3c2t2s3c2zsemi1h2s3f2t2s3g2n2s3m2n2s3p2n2s3p2s2s3p2ts3tal_s3tes_s3tor_2s3t2s2s3t2zsup6ra2t3c2n2t3c2t2t3c2ztele1h4teta_2t3f2t2t3g2n2t3m2ntopo1h2t3p2n2t3p2s2t3p2t2t3t2s2t3t2zu4teriwa3s4h2x3c2n2x3c2t2x3c2zxeno1h2x3f2t2x3g2n2x3m2n2x3p2n2x3p2s2x3p2t2x3t2s2x3t2z2y3c2n2y3c2t2y3c2z2y3f2t2y3g2n2y3m2n2y3p2n2y3p2s2y3p2t2y3t2s2y3t2z", 29256 7: "_ana3li_aná3li_ane3xa_ane3xá_ane3xe_ane3xé_ani3ll_ano5ta_ano3tá_anti1h_an2ú2__anua3l_anu3bl_anu3da_bi1aur_bi1ó2x_en1apa_en1arb_en1art_he4mee_hu4mea_hu4meo_mala1e_pre2a2_pre2á2_pre2e2_pre2é2_pre2h2_pre2i2_pre2Ã2_pre2o2_pre2ó2_pre2u2_pre2ú2_pro2a2_pro2á2_pro2e2_pro2é2_pro2h2_pro2i2_pro2Ã2_pro2o2_pro2ó2_pro2u2_pro2ú2_re3abr_re3ábr_re3a2q_re3a2z_re3i2m_re3inc_re3ing_re3ins_re3int_re3o2b_re1unt_so3a4s4a3ban_4a3bas_acante2acto1a2acto1á2acto1e2acto1é2acto1i2acto1Ã2acto1o2acto1ó2acto1u2acto1ú24a3das_4adlas_4adles_4adlos_4adnos_4a3dor_4a3dos_aero1a2aero1á2aero1e2aero1é2aero1i2aero1Ã2aero1o2aero1ó2aero1u2aero1ú2afro1a2afro1á2afro1e2afro1é2afro1i2afro1Ã2afro1o2afro1ó2afro1u2afro1ú2aÃ5sos_4a3mos_anfi1a2anfi1á2anfi1e2anfi1é2anfi1i2anfi1Ã2anfi1o2anfi1ó2anfi1u2anfi1ú2anglo1hante1a2ante1á2ante1e2ante1é2ante1i2ante1Ã2ante1o2ante1ó2ante1u2ante1ú24áosla_4áosle_4áoslo_4a3ran_4a3rán_4a3ras_4a3rás_archi1h4a3ren_4a3res_4a3rés_4a3rÃa_a3rios_4a3rÃs_4a4rme_4a3ron_4a3ros_4a3sen_4a3ses_4astes_auto1a2auto1á2auto1e2auto1é2auto1i2auto1Ã2auto1o2auto1ó2auto1u2auto1ú2bi1u2nÃ4cagas_centi1hciclo1hcito1a2cito1á2cito1e2cito1é2cito1i2cito1Ã2cito1o2cito1ó2cito1u2cito1ú23c2neorcnico1hco4accico4actico4adjuco4adyuco3agenco4e3táco3exisco4imbrco4incico4i3tocon1urbcrono1hdeca1a2deca1á2deca1e2deca1é2deca1i2deca1Ã2deca1o2deca1ó2deca1u2deca1ú2decimo1desa3fidesa3fÃdesa3güde4s3eqde3signde3sollea3cia_ea3cio_4eadla_ecano1hectro1h4edlas_4edles_4edlos_4ednos_4e3dro_4eedla_4emboca4e3mos_endo1a2endo1á2end
29256o1e2endo1é2endo1i2endo1Ã2endo1o2endo1ó2endo1u2endo1ú2ento1a2ento1á2ento1e2ento1é2ento1i2ento1Ã2ento1o2ento1ó2ento1u2ento1ú2entre1h4éosla_4éosle_4éoslo_e5r4ad_e5r4an_4e3rán_e5r4as_4e3rás_4e3rés_4e3rÃa_4e3rÃs_4erlas_4erles_4erlos_4ernos_4e3ros_euco1a2euco1á2euco1e2euco1é2euco1i2euco1Ã2euco1o2euco1ó2euco1u2euco1ú2euro1a2euro1á2euro1e2euro1é2euro1i2euro1Ã2euro1o2euro1ó2euro1u2euro1ú2expoli4extra1hfono1a2fono1á2fono1e2fono1é2fono1i2fono1Ã2fono1o2fono1ó2fono1u2fono1ú2foto1a2foto1á2foto1e2foto1é2foto1i2foto1Ã2foto1o2foto1ó2foto1u2foto1ú2gluco1hhecto1hhelio1hhemi1a2hemi1á2hemi1e2hemi1é2hemi1i2hemi1Ã2hemi1o2hemi1ó2hemi1u2hemi1ú2hemo1a2hemo1á2hemo1e2hemo1é2hemo1i2hemo1Ã2hemo1o2hemo1ó2hemo1u2hemo1ú2hexa1a2hexa1á2hexa1e2hexa1é2hexa1i2hexa1Ã2hexa1o2hexa1ó2hexa1u2hexa1ú2hidro1hhisto1hhomo1a2homo1á2homo1e2homo1é2homo1i2homo1Ã2homo1o2homo1ó2homo1u2homo1ú2ia5res_2i3cas_icono1h2i3cos_4i2dal_4Ã3das_4i3deo_4Ã3dos_4i3gas_4i3gás_4Ã3mos_infra1hintra1h4Ãsmos_4Ãstas_4Ã3tes_kilo1a2kilo1á2kilo1e2kilo1é2kilo1i2kilo1Ã2kilo1o2kilo1ó2kilo1u2kilo1ú2li5áreamacro1hmante4amaxi1a2maxi1á2maxi1e2maxi1é2maxi1i2maxi1Ã2maxi1o2maxi1ó2maxi1u2maxi1ú2mega1a2mega1á2mega1e2mega1é2mega1i2mega1Ã2mega1o2mega1ó2mega1u2mega1ú23mente_micro1hmili1a2mili1á2mili4armili1e2mili1é2mili1i2mili1Ã2mili1o2mili1ó2mili1u2mili1ú2mini1a2mini1á2mini1e2mini1é2mini1i2mini1Ã2mini1o2mini1ó2mini1u2mini1ú2miria1hmono1a2mono1á2mono1e2mono1é2mono1i2mono1Ã2mono1o2mono1ó2mono1u2mono1ú2multi1hnamo1a2namo1á2namo1e2namo1é2namo1i2namo1Ã2namo1o2namo1ó2namo1u2namo1ú2necro1hneto1a2neto1á2neto1e2neto1é2neto1i2neto1Ã2neto1o2neto1ó2neto1u2neto1ú2norte1hocta1a2octa1á2octa1e2octa1é2octa1i2octa1Ã2octa1o2octa1ó2octa1u2octa1ú2octo1a2octo1á2octo1e2octo1é2octo1i2octo1Ã2octo1o2octo1ó2octo1u2octo1ú24o2ica_4o2ico_oligo1homni1a2omni1á2omni1e2omni1é2omni1i2omni1Ã2omni1o2omni1ó2omni1u2omni1ú22o3sas_2o3sos_4ósteo_paleo1hpara1a2para1á2para1e2para1é2para1i2para1Ã2para1o2para1ó2para1u2para1ú2penta1hpiezo1hpluri1hpoi3de_poli1a2poli1á2poli1e2poli1é2poli1i2poli1Ã2poli1o2poli1ó2poli1u2poli1ú2pos3ta_pre3olÃproto1hradio1hranco1hretro1hrmano1hromo1a2romo1á2romo1e2romo1é2romo1i2romo1Ã2romo1o2romo1ó2romo1u2romo1ú2san4c5tsemi1a2semi1á2semi1e2semi1é2semi1i2semi1Ã2semi1o2semi1ó2semi1u2semi1ú2seudo1hsobre1hsocio1hs3tora_supra1htalmo1htele1a2tele1á2tele1e2tele1é2tele1i2tele1Ã2tele1o2tele1ó2tele1u2tele1ú2termo1h4tetas_tetra1hti2o3coti2o3qutopo1a2topo1á2topo1e2topo1é2topo1i2topo1Ã2topo1o2topo1ó2topo1u2topo1ú2tropo1hultra1hxeno1a2xeno1á2xeno1e2xeno1é2xeno1i2xeno1Ã2xeno1o2xeno1ó2xeno1u2xeno1ú2", 29257 8: "_an3aero_ane3xio_ane3xió_ani3dar_ani3mad_ani3mád_an3i2so_an3i2só_ani3vel_ano5che_ano5din_ano5mal_anó5mal_ano5nad_ano5nim_anó3nim_anti1a2_anti1á2_anti1e2_anti1é2_anti1i2_anti1Ã2_anti1o2_anti1ó2_anti1u2_anti1ú2_anua4lm_de2s2a2_de2s2á2_de2s2e2_de2s2é2_de2s2i2_de2s2Ã2_de2s2o2_de2s2ó2_de2s2u2_de2s2ú2_en1aciy_en1anch_en2artr_eno3jar_hepta1e_ina3nic_in3anim_iná3nim_in3apel_iné3dit_in3efic_ini3cia_ini3ciá_ini3cie_ino3cua_ino3cuo_intra1o_intra1u_inú3til_mal1est_mal1int_pos3tin_pos3tÃn_re3a2eg_re3alim_re3anim_re3anÃm_re3orga_retro1a_re3unir_re3unÃr_re3usar_re3usár_su2b2a2_su2b2á2_sub3arr_su2b2e2_su2b2é2_su2b2i2_su2b2Ã2_sub3Ãmi_sub3Ãnd_su2b2o2_su2b2ó2_su2b2u2_su2b2ú2_sur1est_sur1oes_tra2s1a_tra2s1o_tri1ó2x4a3bais_4a3ción_4ádmele_4ádmelo_4a3dora_4ádsela_4ádsele_4ádselo_4ádtele_4ádtelo_4ándola_4ándole_4ándolo_4ándome_4ándoos_4ándose_4ándote_anglo1a2anglo1á2anglo1e2anglo1é2anglo1i2anglo1Ã2anglo1o2anglo1ó2anglo1u2anglo1ú24áoslas_4áosles_4áoslos_4a3rais_archi1a2archi1á2archi1e2archi1é2archi1i2archi1Ã2archi1o2archi1ó2archi1u2archi1ú24a3reis_4a3réis_4a3rÃais4a3rÃan_4a3rÃas_4a4r3la_4a4r3le_4a4r3lo_4árosla_4árosle_4ároslo_4a4r3se_4a4r3te_4a3seis_4asteis_biblio1hcardio1hcefalo1hcenti1a2centi1á2centi1e2centi1é2centi1i2centi1Ã2centi1o2centi1ó2centi1u2centi1ú2ciclo1a2ciclo1á2ciclo1e2ciclo1é2ciclo1i2ciclo1Ã2ciclo1o2ciclo1ó2ciclo1u2ciclo1ú2cnico1a2cnico1á2cnico1e2cnico1é2cnico1i2cnico1Ã2cnico1o2cnico1ó2cnico1u2cnico1ú2co4a3dunco4a3gulco4á3gulco4a3licco4aptacco4e3ficcon1imbrcontra1hco4o3perco4o3pércripto1hcrono1a2crono1á2crono1e2crono1é2crono1i2crono1Ã2crono1o2crono1ó2crono1u2crono1ú2de4s3abrde4s3agudesa3lindesa3livde4s3almdesa3lojde4s3anddesa3pañdesa3pegde4s3armdes4armede4s3asndesa3tindesa3yundesa3zondesa3zónde3semejde4s3endde4s3enjde4s3enmde4s3enrde4s3ensde3s4ertde3s4
29257értde3siderde3sidiade3sidiode3siertde3socupde3solacde3soladde3soncede4s3ovade4s3ovide4s3oxide4s3oyede4s3oyéde3suelldodeca1hea3cias_ea3cios_ecano1a2ecano1á2ecano1e2ecano1é2ecano1i2ecano1Ã2ecano1o2ecano1ó2ecano1u2ecano1ú2ectro1a2ectro1á2ectro1e2ectro1é2ectro1i2ectro1Ã2ectro1o2ectro1ó2ectro1u2ectro1ú24édmele_4édmelo_4e3dros_4édsela_4édsele_4édselo_4édtele_4édtelo_entre1a2entre1á2entre1e2entre1é2entre1i2entre1Ã2entre1o2entre1ó2entre1u2entre1ú24éoslas_4éosles_4éoslos_e5r4áis_4e3réis_4e3rÃan_4e3rÃas_4e3rior_4érmele_4érmelo_4érsela_4érsele_4érselo_4értele_4értelo_extra1a2extra1á2extra1e2extra1é2extra1i2extra1Ã2extra1o2extra1ó2extra1u2extra1ú2gastro1hgluco1a2gluco1á2gluco1e2gluco1é2gluco1i2gluco1Ã2gluco1o2gluco1ó2gluco1u2gluco1ú2hecto1a2hecto1á2hecto1e2hecto1é2hecto1i2hecto1Ã2hecto1o2hecto1ó2hecto1u2hecto1ú2helio1a2helio1á2helio1e2helio1é2helio1i2helio1Ã2helio1o2helio1ó2helio1u2helio1ú2hemato1hhidro1a2hidro1á2hidro1e2hidro1é2hidro1i2hidro1Ã2hidro1o2hidro1ó2hidro1u2hidro1ú2hipe2r3rhisto1a2histo1á2histo1e2histo1é2histo1i2histo1Ã2histo1o2histo1ó2histo1u2histo1ú24Ãa3mos_icono1a2icono1á2icono1e2icono1é2icono1i2icono1Ã2icono1o2icono1ó2icono1u2icono1ú24i3deos_4i3gáis_infra1a2infra1á2infra1e2infra1é2infra1i2infra1Ã2infra1o2infra1ó2infra1u2infra1ú2inter4ésinter4inintra1a2intra1á2intra1e2intra1é2intra1i2intra1Ã2intra1o2intra1ó2intra1u2intra1ú24Ã4s3te_4Ãstica_4Ãstico_macro1a2macro1á2macro1e2macro1é2macro1i2macro1Ã2macro1o2macro1ó2macro1u2macro1ú24meable_megalo1hmelano1hmicro1a2micro1á2micro1e2micro1é2micro1i2micro1Ã2micro1o2micro1ó2micro1u2micro1ú2miria1a2miria1á2miria1e2miria1é2miria1i2miria1Ã2miria1o2miria1ó2miria1u2miria1ú2multi1a2multi1á2multi1e2multi1é2multi1i2multi1Ã2multi1o2multi1ó2multi1u2multi1ú2necro1a2necro1á2necro1e2necro1é2necro1i2necro1Ã2necro1o2necro1ó2necro1u2necro1ú2norte1a2norte1á2norte1e2norte1é2norte1i2norte1Ã2norte1o2norte1ó2norte1u2norte1ú24o2icas_4o2icos_o4i3dal_4o2i3de_o4i3dea_oligo1a2oligo1á2oligo1e2oligo1é2oligo1i2oligo1Ã2oligo1o2oligo1ó2oligo1u2oligo1ú24ó3loga_4ó3logo_4ósteos_paleo1a2paleo1á2paleo1e2paleo1é2paleo1i2paleo1Ã2paleo1o2paleo1ó2paleo1u2paleo1ú2para2is_para4Ãsopenta1a2penta1á2penta1e2penta1é2penta1i2penta1Ã2penta1o2penta1ó2penta1u2penta1ú2piezo1a2piezo1á2piezo1e2piezo1é2piezo1i2piezo1Ã2piezo1o2piezo1ó2piezo1u2piezo1ú2plan4c5tpluri1a2pluri1á2pluri1e2pluri1é2pluri1i2pluri1Ã2pluri1o2pluri1ó2pluri1u2pluri1ú2poi3des_poli4arqpoli4árqpoli4u3rpos3tas_pre3eligpre3elijpre3eminpre3exispreo3cuppreo2cúppre3opinproto1a2proto1á2proto1e2proto1é2proto1i2proto1Ã2proto1o2proto1ó2proto1u2proto1ú2radio1a2radio1á2radio1e2radio1é2radio1i2radio1Ã2radio1o2radio1ó2radio1u2radio1ú2ranco1a2ranco1á2ranco1e2ranco1é2ranco1i2ranco1Ã2ranco1o2ranco1ó2ranco1u2ranco1ú2retro1a2retro1á2retro1e2retro1é2retro1i2retro1Ã2retro1o2retro1ó2retro1u2retro1ú2rmano1a2rmano1á2rmano1e2rmano1é2rmano1i2rmano1Ã2rmano1o2rmano1ó2rmano1u2rmano1ú2seudo1a2seudo1á2seudo1e2seudo1é2seudo1i2seudo1Ã2seudo1o2seudo1ó2seudo1u2seudo1ú2sobre1a2sobre1á2sobre1e2sobre1é2sobre1i2sobre1Ã2sobre1o2sobre1ó2sobre1u2sobre1ú2socio1a2socio1á2socio1e2socio1é2socio1i2socio1Ã2socio1o2socio1ó2socio1u2socio1ú2s3toras_s3tores_su4d3oessupe2r3rsupra1a2supra1á2supra1e2supra1é2supra1i2supra1Ã2supra1o2supra1ó2supra1u2supra1ú2talmo1a2talmo1á2talmo1e2talmo1é2talmo1i2talmo1Ã2talmo1o2talmo1ó2talmo1u2talmo1ú23te3ri3ntermo1a2termo1á2termo1e2termo1é2termo1i2termo1Ã2termo1o2termo1ó2termo1u2termo1ú2tetra1a2tetra1á2tetra1e2tetra1é2tetra1i2tetra1Ã2tetra1o2tetra1ó2tetra1u2tetra1ú2trans4artrans4ittropo1a2tropo1á2tropo1e2tropo1é2tropo1i2tropo1Ã2tropo1o2tropo1ó2tropo1u2tropo1ú2ultra1a2ultra1á2ultra1e2ultra1é2ultra1i2ultra1Ã2ultra1o2ultra1ó2ultra1u2ultra1ú2", 29258 9: "_bi1anual_bien1and_bien1apa_bien1ave_bien1est_bien1int_dieci1o2_en1aceit_en1aguaz_enu3mera_enu3merá_enu3mere_in3abarc_in3abord_in3acent_in3adapt_in3aplic_in3arrug_in3asist_in3efici_in3eludi_ine3narr_ino3cula_ino3culá_ino3cule_inte2r3r_mal1acon_mal1acos_pos2t2a2_pos2t2á2_pos2t2e2_pos2t2é2_pos3terg_pos2t2i2_pos2t2Ã2_post3ind_pos2t2o2_pos2t2ó2_post3ope_post3rev_pos2t2u2_pos2t2ú2_re3afirm_re3afÃrm_re3ajust_rea3júst_rea3lism_rea3list_rea3liza_rea3lizá_rea3lÃza_re3ubica_re3ubÃca_reu3mati_reu3máti_su3b4ien_sub2i3ll_su4b3ray_sub3urba_su2d1est_sur1a2me_tele1imp_tele1obj_tra2s2oñ4á3bamos_4ád3mela_4ádmeles_4ádmelos_4ádnosla_4ádnosle_4ádnoslo_4a3doras_4a3dores_4ádselas_4ádseles_4ádselos_4ád3tela_4ádteles_4ádtelos_4a4i3gan_4ándolas_4ándoles_4ándolos_4ándonos_4á3ramos_4a3remos_4á3remos_4a4r3las_4a4r3les_4a4r3los_4á4rmele_4á4rmelo_4a4r3nos_4ároslas_4árosles_4ároslos_4á3semos_biblio1a2biblio1á2biblio1e2biblio1é2biblio1i2biblio1Ã2biblio1o2biblio1ó2biblio1u2biblio1ú2b4ien3do_cardio1a2cardio1á2cardio1e2cardio1é2cardio1i2cardio1Ã2cardio1o2cardio1ó2cardio1u2cardio1ú2cefalo1a2cefalo1á2
29258cefalo1e2cefalo1é2cefalo1i2cefalo1Ã2cefalo1o2cefalo1ó2cefalo1u2cefalo1ú2contra1a2contra1á2contra1e2contra1é2contra1i2contra1Ã2contra1o2contra1ó2contra1u2contra1ú2cripto1a2cripto1á2cripto1e2cripto1é2cripto1i2cripto1Ã2cripto1o2cripto1ó2cripto1u2cripto1ú2desa3briddesa3certde4s3acotde4s3aficde4s3afilde4s3afinde4s3afordesa3garrde4s3ahijde4s3aliñdesa3marrdesa3moblde4s3anidde4s3animde4s3anÃmde4s3anudde4s3apoyde4s3arende4s3avisde4s3empéde4s3enamde4s3enchde4s3enclde4s3encode4s3encrde4s3encude3senfadde3senfádde4s3enfide4s3enfode4s3enfóde3sengañde3sengáñde4s3enlode4s3entade4s3entode4s3entrde4s3entude3s4ercide4s3espade3sesperde3sigualde3siluside4s3imande3sinencde3sinfecde4s3inflde3sistende4s3odorde4s3ordede4s3órdede4s3orejde3s4osegde3su3dande3su3darde3su3dasde4s3unimde4s3unirdodeca1a2dodeca1á2dodeca1e2dodeca1é2dodeca1i2dodeca1Ã2dodeca1o2dodeca1ó2dodeca1u2dodeca1ú24éd3mela_4édmeles_4édmelos_4édnosla_4édnosle_4édnoslo_4é3drica_4é3drico_4édselas_4édseles_4édselos_4éd3tela_4édteles_4édtelos_e5r4a3ba_e5r4a3da_e5r4a3do_e5r4a3ra_e5r4a3rá_e5r4a3re_e5r4a3ré_e5r4a3se_e5r4aste_e5r4ates_4e3rÃais_4e3riora_4ér3mela_4érmeles_4érmelos_4érnosla_4érnosle_4érnoslo_4é3rosla_4é3rosle_4é3roslo_4érselas_4érseles_4érselos_4ér3tela_4érteles_4értelos_gastro1a2gastro1á2gastro1e2gastro1é2gastro1i2gastro1Ã2gastro1o2gastro1ó2gastro1u2gastro1ú2hemato1a2hemato1á2hemato1e2hemato1é2hemato1i2hemato1Ã2hemato1o2hemato1ó2hemato1u2hemato1ú2hipe2r1a2hipe2r1á2hipe2r1e2hipe2r1é2hipe2r1i2hipe2r1Ã2hipe2r1o2hipe2r1ó2hipe2r1u2hipe2r1ú24i2dales_4i3gamos_inter4inointer4ior4Ãs3teis_4Ã4s3tes_4Ãsticas_4Ãsticos_4meables_megalo1a2megalo1á2megalo1e2megalo1é2megalo1i2megalo1Ã2megalo1o2megalo1ó2megalo1u2megalo1ú2melano1a2melano1á2melano1e2melano1é2melano1i2melano1Ã2melano1o2melano1ó2melano1u2melano1ú2mili4arioo4i3deas_4o2i3des_4ó3logas_4o3logÃa_4ó3logos_pe5r4antepoli4andrpoli4éstes3ta3les_s3ti3lla_supe2r1a2supe2r1á2supe2r1e2supe2r1é2supe2r1i2supe2r1Ã2super4iorsupe2r1o2supe2r1ó2supe2r1u2supe2r1ú2t4eo3nes_tran4sacctrans4ido", 29259 10: "_an3e2pigr_ante2o3je_en1aguach_in3aguant_ina3movib_in3analiz_in3apreci_in3aprens_inte2r1a2_inte2r1á2_inte2r1e2_inte2r1é2_inte2r1i2_inte2r1Ã2_inte2r1o2_inte2r1ó2_inte2r1u2_inte2r1ú2_inu3tiliz_ma4l3e4du_pa4n1afri_pa4n1ópti_post3elec_pos3te3ri_pos3ti3go_pos3ti3la_post3impr_pos3ti3ne_pos3ti3za_pos3ti3zo_pos3tó3ni_pos3tu3la_pos3tu3lá_pos3tu3le_pos3tu3lé_pos3tu3ra_re3a2grup_re3aparec_re3utiliz_re3utilÃz_sub3aflue_sub3enten_sub3estim_sub3estÃm_sub3ofici_su2d1a2fr_su2d1a2me_tran2s1ur4a3ciones_4ád3melas_4ádnoslas_4ádnosles_4ádnoslos_4ád3telas_4ándomela_4ándomele_4ándomelo_4ándosela_4ándosele_4ándoselo_4ándoseme_4ándotela_4ándotele_4ándotelo_4ándoteme_4a3rÃamos_4á4r3mela_4á4r3sela_4á4r3sele_4á4r3selo_4á4r3tela_4á4r3tele_4á4r3telo_b4ien3das_centi5áreaco3n4imbride4s3abastde4s3abollde4s3abotode4s3aceitdesa3ciertde4s3acompde4s3aconsde4s3acoplde4s3acorrde4s3activde4s3adeudde4s3adornde4s3aferrde4s3agradde4s3agregde4s3agrupde4s3aherrde4s3ajustde4s3alentde4s3alfomde4s3alforde4s3aliende4s3alinede4s3almidde4s3alterde4s3amoldde4s3amortde4s3angeldesa3pacibde4s3apadrde4s3aparedesa3parecdesa3paricde4s3aplicde4s3apretde4s3aprobde4s3arbolde4s3arrimdesa3rrollde4s3arropde4s3arrugde4s3asentde4s3asistdesa3sosegde4s3atencde4s3atendde4s3atentde4s3atornde4s3autorde4s3embalde4s3embálde4s3embarde4s3embárde4s3embotde4s3empacde4s3empañde4s3empáñde4s3empatde4s3empegde4s3emplede4s3empozde4s3encabde4s3encadde4s3encajde4s3encájde4s3encamde3sencantde4s3encapde4s3encarde4s3encárde3senfrende4s3enfurde4s3engarde4s3engasde4s3engomde4s3engozde4s3engrade4s3enladde4s3enlazde3sentendde4s3enterde3sentiende3sentiénde4s3estimde4s3imponde4s3inhibde3s4interde4s3intoxde4s3inverde4s3obligde4s3obstrde4s3ub4icde4s3unierde3s4ustane4a3miento4éd3melas_4édnoslas_4édnosles_4édnoslos_4é3dricas_4é3dricos_4éd3telas_e5r4a3ban_e5r4a3bas_4e3ra3ble_e5r4a3das_e5r4a3dor_e5r4a3dos_e5r4a3mos_e5r4a3ran_e5r4a3rán_e5r4a3ras_e5r4a3rás_e5r4a3ren_e5r4a3res_e5r4a3rés_e5r4a3rÃa_e5r4a3rÃs_e5r4a3ron_e5r4a3sen_e5r4a3ses_e5r4astes_4e3re3mos_4e3rÃamos_4e3rioras_4e3riores_4ér3melas_4érnoslas_4érnosles_4érnoslos_4é3roslas_4é3rosles_4é3roslos_4ér3telas_familia3riinter4esarmini4a5turo4i3dales_4o3logÃas_4o3lógica_4o3lógico_para4ulatape3r4e3miaperpon5d6rpoli4anteapoli4o5mies3ti3llas_s3ti3llón_super4ablesupe4r4a3rsupe4r4á3rtrans4ibertrans4igentrans4igirtrans4itabultra4Ãsmo", 29260 11: "_mal1andant_mal1andanz_pa4n1europ_sub2i3mien_tran2s1alp_tran2s1and_tran2s1atl_tran2s1oce4ándomelas_4ándomeles_4ándomelos_4ándoselas_4ándoseles_4ándoselos_4ándosenos_4ándotelas_4ándoteles_4ándotelos_4ándotenos_4á4r3melas_4á4r3meles_4á4r3melos_4á4r3nosla_4á4r3nosle_4á4r3noslo_4á4r3selas_4á4r3seles_4á4r3selos_4á4r3telas_4á4r3teles_4á4r3telos_de4s3abrochde4s3acelerde4s3acobarde4s3acomoddesa3cralizde4s3acuartde4s3aderezde4s3adorarde4s3advertde4s3agracide4s3agravide4s3alagarde4s3alquilde4s3alumbrde4s3amuebldesa3percibde4s3aprenddesa3prenside4s3aprietde4s3apropide4s3arraigde4s3arreglde4s3arrenddesa3sosiegde4s3atiend
29260de4s3atrancde4s3embargde4s3embolsde4s3emborrde4s3emboscde4s3embragde4s3embrágde4s3embrujde4s3embrújde4s3empedrde4s3empeorde4s3empernde4s3empolvde4s3empotrde4s3encallde4s3encállde4s3enfundde4s3enhebrde4s3entierde4s3entiérde4s3envainde3sesperacde4s3imaginde4s3impresde4s3incentde4s3inclinde4s3incorpde4s3inflamde4s3informde4s3insectde4s3instalde3s4integrde4s3obedecde3s4ubstane5r4a3bais_4e3ra3bles_e5r4a3dora_e5r4a3rais_e5r4a3reis_e5r4a3réis_e5r4a3rÃaise5r4a3rÃan_e5r4a3rÃas_e5r4a3seis_e5r4asteis_4i3gá3moos_4o3lógicas_4o3lógicos_2o3samente_super4ación4te4r5i4nsutrans4eúntetrans4icióntrans4istortrans4ubsta", 29261 12: "_in3ter2e3sa_in3ter2e3sá_in3ter2e3se_in3ter2e3sé_in3ter2e3so_in3ter2e3só_in3te3r4rog_pa4n1a4meri4á4r3noslas_4á4r3nosles_4á4r3noslos_deca2i3mientde4s3acostumde4s3acreditde4s3adormecdesa3guisadode4s3apolillde4s3articulde4s3embravede4s3embrávede4s3embrollde4s3embróllde4s3emparejde4s3emparéjde4s3emperezde4s3enganchde3senvolvimde4s3estabilde4s3impresXde4s3incruste5r4á3bamos_e5r4a3doras_e5r4a3dores_e5r4á3ramos_e5r4a3remos_e5r4á3remos_e5r4á3semos_4e3rioridad_4i3gá3monos_4i3gá3mosla_4i3gá3mosle_4i3gá3moslo_4i3gá3mosme_4i3gá3moste_s3ti3llones_trans4itorio", 29262 13: "_in3te3r4rump_in3te3r4rupc_in3te3r4ruptde4s3aprovechde4s3empaquetde4s3empaquétde4s3emparentde4s3esperanze5r4a3rÃamos_4e3riormente_4i3gá3moosla_4i3gá3moosle_4i3gá3mooslo_4i3gá3mosela_4i3gá3mosele_4i3gá3moselo_4i3gá3moslas_4i3gá3mosles_4i3gá3moslos_supe3r4á3vit_", 29263 14: "4e3rioridades_4i3gá3monosla_4i3gá3monosle_4i3gá3monoslo_4i3gá3mooslas_4i3gá3moosles_4i3gá3mooslos_4i3gá3moselas_4i3gá3moseles_4i3gá3moselos_4i3gá3mosmele_4i3gá3mosmelo_4i3gá3mostele_4i3gá3mostelo_supe3r4á3vits_", 29264 15: "4e3ra3blemente_4i3gá3monoslas_4i3gá3monosles_4i3gá3monoslos_4i3gá3mos3mela_4i3gá3mosmeles_4i3gá3mosmelos_4i3gá3mos3tela_4i3gá3mosteles_4i3gá3mostelos_4o3lógicamente_", 29265 16: "4i3gá3mos3melas_4i3gá3mos3telas_", 29266 17: "_de3s4in3ter2e3sa_de3s4in3ter2e3sá_de3s4in3ter2e3se_de3s4in3ter2e3sé_de3s4in3ter2e3so_de3s4in3ter2e3só" 29267 }, 29268 patternChars: "X_abcdefghijklmnopqrstuvwxyzáéÃñóúü", 29269 patternArrayLength: 79623, 29270 valueStoreLength: 15424 29271}; 29272 29273Hyphenator.config({ 29274 classname : 'article-headline', 29275 minwordlength : 10, 29276 rightmin : 5, 29277 intermediatestate : 'visible', 29278 unhide : 'progressive' 29279}); 29280 29281Hyphenator.run(); 29282var topics = {}; 29283 29284jQuery.Topic = function (id) { 29285 var callbacks, method, 29286 topic = id && topics[id]; 29287 29288 if (!topic) { 29289 callbacks = jQuery.Callbacks(); 29290 topic = { 29291 publish: callbacks.fire, 29292 subscribe: callbacks.add, 29293 unsubscribe: callbacks.remove 29294 }; 29295 if (id) { 29296 topics[id] = topic; 29297 } 29298 } 29299 return topic; 29300}; 29301(function ($) { 29302 ns('News').ContentList = { 29303 DYNAMIC: "tag-based-dynamic", 29304 HYBRID: "hybrid", 29305 MANUAL: "manual", 29306 TAG_MANUAL: "tag-based-manual", 29307 LANDING_PAGE_LAYOUT: "content-list-layout--landing-page", 29308 COMMAND_DYNAMIC: "tags", 29309 COMMAND_MANUAL: "path", 29310 SERVICE_DIR: "/services/", 29311 SERVICE_NAME: "articlelist", 29312 LANDING_PAGE_DISPLAY_COUNT: 9, 29313 LANDING_PAGE_AD_DISPLAY_COUNT: 11, 29314 AUTHOR_MODE_CLASS: "content-list-author-mode", 29315 29316 authorMode: false, 29317 ajaxTime: 0, 29318 layoutTypesForInlineVideos: ['hero', '1x1', 'landing-page'], 29319 29320 /** 29321 * Handles different content list loading strategies 29322 */ 29323 loadContentList: function (index, element, callback) { 29324 if ($(element).hasClass("content-list__mode--" + News.ContentList.DYNAMIC)) { 29325 News.ContentList.loadDynamicContentList(index, element, callback) 29326 } else if ($(element).hasClass("content-list__mode--" + News.ContentList.HYBRID)) { 29327 News.ContentList.loadHybridContentList(index, element, callback) 29328 } else { 29329 News.ContentList.loadManualContentList(index, element, callback) 29330 } 29331 }, 29332 29333 /** 29334 * Primary entry point for loading dynamic content lists 29335 * 29336 * @param index - index from jQuery.each 29337 * @param element - the node of the dynamic content list component which stores our data properties 29338 */ 29339 loadDynamicContentList: function (index, element, callback) { 29340 try { 29341 var limit = News.ContentList.getLimit(element) 29342 var requiredTags = News.ContentList.getRequiredTags(element) 29343 var optionalTags = News.ContentList.getOptionalTags(element) 29344 var excludedTags = News.ContentList.getExcludedTags(element) 29345 var daysLimit = News.ContentList.getDaysLimit(element) 29346 var daysLimitTimezone = News.ContentList.getDaysLimitTimezone(element) 29347 var path = News.ContentList.getPagePath(element) 29348 var uri = '/services/ms/articles?reqTags=' + requiredTags + '&optTags=' + optionalTags + '&exTags=' + excludedTags + '&path=' + path + '&daysLimit=' + daysLimit + '&daysLimitTimezone=' + daysLimitTimezone; 29349 var startTime = new Date().getTime(); 29350 $.ajax({
29351 url: uri 29352 }) 29353 .done(function (data, textStatus, jqXHR) { 29354 News.ContentList.ajaxLoadFinished(element, data) 29355 News.App.QuantumAnalytics.quantumApiSuccessOrFailure(uri, jqXHR.status, "All_Generic_API_Call_Success", startTime, "GET", "", "", jqXHR); 29356 if (callback) callback(); 29357 }) 29358 .fail(function (jqXHR, textStatus, errorThrown) { 29359 let responseText = News.App.QuantumAnalytics.extractAjaxErrorMessage(jqXHR); 29360 News.App.QuantumAnalytics.quantumApiSuccessOrFailure(uri, jqXHR.status, "All_Generic_API_Call_Failure", startTime, "GET", "", responseText, jqXHR); 29361 if (callback) callback(); 29362 }) 29363 } catch (ex) { 29364 if (callback) callback(); 29365 } 29366 }, 29367 29368 /** 29369 * Primary entry point for loading Hybrid content lists 29370 * 29371 * @param index - index from jQuery.each 29372 * @param element - the node of the dynamic content list component which stores our data properties 29373 */ 29374 loadHybridContentList: function (index, element, callback) { 29375 try { 29376 var limit = News.ContentList.getLimit(element) 29377 var requiredTags = News.ContentList.getRequiredTags(element) 29378 var optionalTags = News.ContentList.getOptionalTags(element) 29379 var excludedTags = News.ContentList.getExcludedTags(element) 29380 var daysLimit = News.ContentList.getDaysLimit(element) 29381 var daysLimitTimezone = News.ContentList.getDaysLimitTimezone(element) 29382 var path = News.ContentList.getPagePath(element) 29383 var compPath = News.ContentList.getResourcePath(element) 29384 var uri = '/services/ms/articles/hybrid?mode=hybrid&path='+ compPath; 29385 var startTime = new Date().getTime(); 29386 let responseText = ''; 29387 $.ajax({ 29388 url: uri 29389 }) 29390 .done(function (data, textStatus, jqXHR) { 29391 News.ContentList.ajaxLoadFinished(element, data) 29392 News.App.QuantumAnalytics.quantumApiSuccessOrFailure(uri, jqXHR.status, "All_Generic_API_Call_Success", startTime, "GET", "", "", jqXHR); 29393 if (callback) callback(); 29394 }) 29395 .fail(function (jqXHR) { 29396 responseText = News.App.QuantumAnalytics.extractAjaxErrorMessage(jqXHR); 29397 News.App.QuantumAnalytics.quantumApiSuccessOrFailure(uri, jqXHR.status, "All_Generic_API_Call_Failure", startTime, "GET", "", responseText, jqXHR); 29398 if (callback) callback(); 29399 }) 29400 } catch (ex) { 29401 if (callback) callback(); 29402 } 29403 }, 29404 29405 /** 29406 * Primary entry point for loading manual content lists 29407 * 29408 * @param index - index from jQuery.each 29409 * @param element - the node of the manual content list component which stores our data properties 29410 */ 29411 loadManualContentList: function (index, element, callback) { 29412 try { 29413 var path = News.ContentList.getPath(element) 29414 var uri = News.ContentList.manualListUri(path) 29415 var startTime = new Date().getTime(); 29416 let responseText = ''; 29417 $.ajax({ 29418 url: uri 29419 }) 29420 .done(function (data, textStatus, jqXHR) { 29421 News.ContentList.ajaxLoadFinished(element, data) 29422 News.App.QuantumAnalytics.quantumApiSuccessOrFailure(uri, jqXHR.status, "All_Generic_API_Call_Success", startTime, "GET", "", "", jqXHR); 29423 if (callback) callback(); 29424 }) 29425 .fail(function (jqXHR) { 29426 responseText = News.App.QuantumAnalytics.extractAjaxErrorMessage(jqXHR); 29427 News.App.QuantumAnalytics.quantumApiSuccessOrFailure(uri, jqXHR.status, "All_Generic_API_Call_Failure",startTime, "GET", "", responseText, jqXHR); 29428 if (callback) callback(); 29429 }) 29430 } catch (ex) { 29431 if (callback) callback(); 29432 } 29433 }, 29434 29435 /** 29436 * When ajax completes successfully, load articles into the content list 29437 * 29438 * Parameters: 29439 * contentList 29440 * data - a response object with an array of results stored in "articles" 29441 */ 29442 ajaxLoadFinished: function (contentList, data) { 29443 var articles = data["articles"] 29444 29445 // Filter articles to remove the current page from the list 29446 articles = $(articles).filter(News.ContentList.currentArticleExcludeFilter) 29447 29448 // Check if no articles are returned from the API 29449 if (articles.length === 0) { 29450 // Find the closest hero wrapper (may be the contentList itself or its parent) 29451 var contentListWrapper = contentList.closest('.content-list'); 29452 29453 if (contentListWrapper) { 29454 // Get heading and articles container inside the wrapper 29455 var h1 = contentListWrapper.querySelector('.content-list-layout > h1'); 29456 var articlesContainer = contentListWrapper.querySelector('.content-list-layout > .articles-container'); 29457 var viewMoreDiv = contentListWrapper.querySelector('.view-more'); 29458 29459 // Helper function: returns true if a node is missing or only contains whitespace 29460 function isEmptyOrWhitespace(node) { 29461 return !node || !node.textContent.trim(); 29462 } 29463 29464 // If both heading and articles container are empty 29465 if (isEmptyOrWhitespace(h1) && isEmptyOrWhitespace(articlesContainer)) { 29466 if (viewMoreDiv) { 29467 // If view-more div exists, add 'link-noArticle' class 29468 contentListWrapper.classList.add('view-more-no-article'); 29469 } else { 29470 // Otherwise, add 'no-article' class 29471 contentListWrapper.classList.add('no-article'); 29472 } 29473 } 29474 } 29475 29476 // Stop execution early since there's nothing to render 29477 return; 29478 } 29479 29480 // When the current page is not in the list, make sure we don't return more results than we should. 29481 if (articles.length > contentList.dataset.limit) { 29482 var limit = parseInt(contentList.dataset.limit); 29483 articles = articles.slice(0, limit) 29484 } 29485 29486 //When in author swap path to URL in order for links to remain JCR paths 29487 if (News.ContentList.authorMode) { 29488 articles = News.ContentList.modifyProperty(articles, "url", "path") 29489 } 29490 29491 /* Render articles in a landing page content list, with view more and lead article behavior */ 29492 if (News.ContentList.isLandingPageContentList(contentList)) { 29493 News.ContentList.renderLandingPageArticles(contentList, articles) 29494 } 29495 /* Render articles in the hero or regular content list layouts */ 29496 else { 29497 News.ContentList.renderContentListArticles(contentList, articles) 29498 } 29499 29500 }, 29501 29502 /** 29503 * Used to determine whether the current content list is a landing page content list, for styling 29504 */ 29505 isLandingPageContentList: function (contentList) { 29506 return $(contentList).hasClass(News.ContentList.LANDING_PAGE_LAYOUT) 29507 }, 29508 29509 /** 29510 * Returns the path attribute of a manual content list 29511 * 29512 * Usually returns the number of items configured on 'element', but in 29513 * articles we need an extra element since we may filter it out. 29514 */ 29515 getPath: function (element) { 29516 var path = element.dataset.path 29517 29518 return path 29519 }, 29520 29521 /** 29522 * Returns how many articles to show in the content list 29523 * 29524 * Usually returns the number of items configured on 'element', but in 29525 * articles we need an extra element since we may filter it out. 29526 */ 29527 getLimit: function (element) { 29528 var limit = parseInt(element.dataset.limit) 29529 29530 return limit 29531 }, 29532 /** 29533 * Returns boolean 29534 * 29535 * to show canoncialUrl instead of page path when USe Canonical Urls is selected. 29536 */ 29537 getCanonical: function (element) { 29538 var canonical = element.dataset.canonical 29539 return canonical 29540 }, 29541 29542 getLandingPageCanonical: function (element) { 29543 var canonical = element.dataset.canonical 29544 return canonical 29545 }, 29546 29547 /** 29548 * Returns boolean 29549 * 29550 * to show ad unit in landing page content list when Display Ad Unit is selected. 29551 */ 29552 getLandingPageAdDisplay: function (element) { 29553 var displayAd = element.dataset.displayad
29554 return displayAd 29555 }, 29556 29557 /** 29558 * Returns the current page path 29559 */ 29560 getPagePath: function (element) { 29561 return element.dataset.pagepath || "" 29562 }, 29563 29564 getResourcePath: function (element) { 29565 return element.dataset.resourcepath || "" 29566 }, 29567 /** 29568 * Returns the required tags configured on 'element' to use in the query 29569 */ 29570 getRequiredTags: function (element) { 29571 return element.dataset.requiredtags || "" 29572 }, 29573 /** 29574 * Returns the required tags configured on 'element' to use in the query 29575 */ 29576 getOptionalTags: function (element) { 29577 return element.dataset.optionaltags || "" 29578 }, 29579 29580 getExcludedTags: function (element) { 29581 return element.dataset.excludedtags || "" 29582 }, 29583 29584 getDaysLimit: function (element) { 29585 return element.dataset.dayslimit || "" 29586 }, 29587 29588 getDaysLimitTimezone: function (element) { 29589 return element.dataset.dayslimittimezone || "" 29590 }, 29591 29592 /** 29593 * Returns the show inline video on 'element' 29594 */ 29595 getShowInlineVideo: function (element,layout) { 29596 if(layout === '1x1' || layout === 'hero' || layout === 'landing-page'){ 29597 return element.dataset.showinlinevideo || "" 29598 } 29599 return ""; 29600 }, 29601 29602 /** 29603 * Returns the query URI for a dynamic content list with the specified required/optional tags and limited to a certain number of results 29604 */ 29605 dynamicListUri: function (required, optional, excluded, limit) { 29606 29607 // setting up limit to either 10 or 100 to reduce service call 29608 if (limit <= 10) { 29609 limit = 10 29610 } else if (limit > 10) { 29611 limit = 100 29612 } 29613 29614 var length = 0 29615 var serviceName = "" 29616 required = News.ContentList.formatTags(required) 29617 optional = News.ContentList.formatTags(optional) 29618 excluded = News.ContentList.formatTags(excluded) 29619 do { 29620 serviceName = News.ContentList.SERVICE_NAME + '.' + News.ContentList.COMMAND_DYNAMIC + '.' + required + '.' + optional + '.' + excluded + '.' + limit + '.json' 29621 length = serviceName.length 29622 29623 if (length > 255) { 29624 if (optional.length > 2) { 29625 optional = News.ContentList.removeTag(optional) 29626 } else if (required.length > 2) { 29627 required = News.ContentList.removeTag(required) 29628 } else /* istanbul ignore else */ if (excluded.length > 2) { 29629 excluded = News.ContentList.removeTag(excluded) 29630 } 29631 } 29632 } 29633 while (length > 255); 29634 29635 return News.ContentList.SERVICE_DIR + serviceName 29636 }, 29637 /** 29638 * Returns the query URI for a manual content list at a specific path 29639 * 29640 */ 29641 manualListUri: function (path) { 29642 return News.ContentList.SERVICE_DIR + News.ContentList.SERVICE_NAME + '.' + News.ContentList.COMMAND_MANUAL + '.' + path + '.json' 29643 }, 29644 29645 /** Filter which should return false when the article input is the current page. 29646 * 29647 * A duplicate article has the same article date in the path + same article name in the path 29648 */ 29649 currentArticleExcludeFilter: function (index, article) { 29650 // Locate the name end of the article, which looks like /name 29651 var articleNameIdx = article.url.lastIndexOf('/') 29652 29653 // Format: .../YYYY/MM/DD/name 29654 // '/YYYY/MM/DD' is 11 characters, but we should allow for MM and DD to possibly be one character. 29655 // If we compare the last 9 characters of the article date, we would still be checking the century, decade, year, month, and date accurately. 29656 var dateLength = 9 29657 var articleDateName = article.url.substring(articleNameIdx - dateLength) 29658 29659 if (window.location.toString().indexOf(articleDateName) > 0) { 29660 return false;
29661 } 29662 return true; 29663 }, 29664 29665 /** Default implementation of a filter: allow any content list to be retrieved 29666 * 29667 * @param index - the index of the current content list in a loop of results based on selecotrs 29668 * @param contentList - the contentList that may be valid 29669 * 29670 * Returns: 'false' - suppress the current content list 29671 * 'true' - attempt to load the current content list 29672 */ 29673 contentListFilter: function (index, contentList) { 29674 return true 29675 }, 29676 29677 /** formatTags 29678 * 29679 * @param tagIds as a string 29680 * 29681 * Returns: pipe-delimited tagIDs, sorted in alphabetic order, with each tagid surrounded in parentheses 29682 * 29683 * e.g. input: "regions:nyc,regions:All/All-Regions,pageCategories:news" 29684 * output: "(pageCategories:news)(regions:All|All-Regions)(regions:nyc)" 29685 */ 29686 formatTags: function (tags) { 29687 var formatted = tags.replace(/(\/)/g, '|') 29688 formatted = formatted.replace(/pageCategories:/g, 'p:') 29689 formatted = formatted.replace(/regions:/g, 'r:') 29690 29691 // Split the tags up, sort them alphabetically, and rejoin the array back into a string 29692 formatted = formatted.split(',').sort().join(')(') 29693 return '(' + formatted + ')' 29694 }, 29695 29696 /** 29697 * Removes a tag from the list of tags to avoid creating an uncacheable URI 29698 * 29699 * Params: 29700 * tags - String of tags in the format (tagId)(tagId) 29701 * 29702 * TODO: Should it be: Last tag (alphabetic), or longest tag (could be overly specific)? 29703 * 29704 * Last tag is easier to implement... 29705 */ 29706 removeTag: function (tags) { 29707 var lastTagStart = tags.lastIndexOf('(') 29708 tags = tags.substring(0, lastTagStart) 29709 return tags 29710 }, 29711 29712 /** pageIsArticle: 29713 * function to determine if the current page is an article (important for empire) 29714 * 29715 * Returns: true - current page is an article 29716 */ 29717 pageIsArticle: function () { 29718 return $('#analyticsDataLayer').data('content-type') === 'article' 29719 }, 29720 29721 modifyProperty: function (articles, propertyFrom, propertyTo) { 29722 articles.each(function (i, article) { 29723 articles[i][propertyFrom] = articles[i][propertyTo] 29724 }) 29725 return articles; 29726 }, 29727 /** 29728 * renderContentListArticles 29729 * 29730 * function to render hero and plain content lists via AJAX 29731 * 29732 * @param contentList - DOM object, the current content list component 29733 * @param articles - array of JSON objects returned from the service 29734 */ 29735 renderContentListArticles: function (contentList, articles) { 29736 const articleContainer = $(contentList).find('.articles-container') 29737 const canonical = News.ContentList.getCanonical(contentList); 29738 29739 // Determine the layout type from the content list 29740 const layoutType = News.ContentList.getLayoutType(contentList); 29741 29742 // Get the inline video setting from the dialog 29743 let showInlineVideo = News.ContentList.getShowInlineVideo(contentList,layoutType); 29744 29745 // Remove the current articles and add new ones 29746 articleContainer.children().remove(); 29747 29748 // Render articles on the content list 29749 if (articles.length > 0) { 29750 // Render the articles on the page 29751 articles.each(function (i, article) { 29752 News.ContentList.renderArticleInContentList(i, article, articleContainer, canonical, layoutType, showInlineVideo) 29753 }) 29754 } 29755 // Hide the heading when on an article, and in Empire, and no articles to display 29756 else if (News.design.getDesignName() == "empire" && 29757 News.ContentList.pageIsArticle()) { 29758 $(contentList).find('h1').hide() 29759 } 29760 }, 29761 29762 /** 29763 * renderLandingPageArticles 29764 * 29765 * function to render landing page content lists via AJAX 29766 * 29767 * @param contentList - DOM object, the current content list component 29768 * @param articles - array of JSON objects returned from the service 29769 * 29770 * This function is overridden in empire landing content lists 29771 */ 29772 renderLandingPageArticles: function (contentList, articles) { 29773 // Remove the current lead object 29774 var leadItemContainer = $(contentList).find('.lead-item') 29775 leadItemContainer.children().remove() 29776 29777 // Remove the current articles and add new ones 29778 var articleContainer = $(contentList).find('.articles-container') 29779 articleContainer.children().remove(); 29780 29781 var canonical = News.ContentList.getLandingPageCanonical(contentList); 29782 var layoutType = News.ContentList.getLayoutType(contentList); 29783 var showInlineVideo = News.ContentList.getShowInlineVideo(contentList,layoutType); 29784 29785 // Render the articles on the page 29786 articles.each(function (i, article) { 29787 if (i == 0) { 29788 News.ContentList.renderArticleInLandingPageContentList(i, article, leadItemContainer, canonical, layoutType, showInlineVideo) 29789 } else { 29790 News.ContentList.renderArticleInLandingPageContentList(i, article, articleContainer, canonical, layoutType, showInlineVideo) 29791 } 29792 }) 29793 }, 29794 29795 /** 29796 * Get layout type from content list element 29797 */ 29798 getLayoutType: function(contentList) { 29799 const supportedLayoutTypes = ['hero', 'landing-page', '4x1-single-column-mobile', '1x1', 'landing-page'] 29800 let contentListLayoutType = contentList.dataset.contentlistlayouttype || ""; 29801 29802 if (!supportedLayoutTypes.includes(contentListLayoutType)) { 29803 contentListLayoutType = 'default'; 29804 } 29805 29806 return contentListLayoutType 29807 }, 29808 29809 29810 renderLandingPageAdHTML: function (container) { 29811 var html = News.ContentList.getAdHtml() 29812 var adTag = document.createElement("div") 29813 adTag.setAttribute('class', 'google-dfp-ads'); 29814 adTag.innerHTML = html 29815 container.append(adTag) 29816 $(adTag).trigger('article-append') 29817 }, 29818 29819 renderGoogleDFPAd: function () { 29820 googletag.cmd.push(function () { 29821 var adSlot = googletag.defineSlot(News.ContentList.getSitePage(), [300, 250], 'x35') 29822 .setTargeting('pos', ['top']); 29823 adSlot.addService(googletag.pubads()); 29824 }); 29825 googletag.cmd.push(function () { 29826 googletag.pubads().enableSingleRequest(); 29827 googletag.pubads().setCentering(true); 29828 googletag.pubads().enableAsyncRendering(); 29829 googletag.pubads().collapseEmptyDivs(); 29830 googletag.pubads().setTargeting('kvrefd', ['www.spectrumlocalnews.com']); 29831 googletag.enableServices(); 29832 }); 29833 googletag.cmd.push(function () { 29834 googletag.display('x35'); 29835 }); 29836 }, 29837 29838 getSitePage: function () { 29839 let dfpSitePage = ''; 29840 if (typeof dfpSiteId !== 'undefined') { 29841 const regionPlusVertRE = /(\/([^\/]*)){3}/; 29842 const regionRE = /(\/([^\/]*)){2}/; 29843 const articleRE = /(\/([^\/]*)){3}(\/\d{4}\/(\d{1,2})\/(\d{1,2})\/)/; 29844 const path = location.pathname.replace('/content/news', '').replace('.html', ''); 29845 const articleAppender = articleRE.test(path) ? '/article' : ''; 29846 const regionPlusVert = regionPlusVertRE.test(path) ? regionPlusVertRE.exec(path)[0] : null; 29847 const region = regionRE.exec(path)[0]; 29848 const regionWithDash = region.replace(/\//g, '-'); 29849 let adRegionPlusVert = regionPlusVert ? regionPlusVert.replace(region, regionWithDash) : regionWithDash; 29850 dfpSitePage = dfpSiteId + adRegionPlusVert + articleAppender; 29851 } else { 29852 return; 29853 } 29854 return dfpSitePage; 29855 }, 29856 29857 getAdHtml: function () { 29858 return '<div id="x35" class="dfp-ad-tags" data-position="x35"></div><div class="icon-advertisement"></div>' 29859 }, 29860 /** 29861 * renderArticleInContentList 29862 * @param i - index of the current article in the service response list 29863 * @param article - JSON object returned from the article service 29864 * @param articleContainer - DOM object, div where the article will be injected 29865 * Sample Article Object: 29866 * {"date":"1536715020000","headline":"Florence heading our way for now","path":"/content/news/stories/2018/09/12/f/florence-heading-our-way-for-now","url":"/nc/charlotte/news/2018/09/12/florence-heading-our-way-for-now","image":"https://images.spectrumnews1.com/is/image/SpectrumNews/tropical_-_prob_of40windspng","damImage":"https://images.spectrumnews1.com/is/image/SpectrumNews/tropical_-_prob_of40windspng","altText":"Probs","previewText":"Florence heading our way for now","location":"Charlotte","categories":"WEATHER","flairText":"","flairType":"","utcFlareOffTime":0} 29867 */ 29868 renderArticleInContentList: function (i, article, articleContainer, canonical, layoutType, showInlineVideo) { 29869 if (i > 0) { 29870 // don't show inline videos beyond the first item 29871 showInlineVideo = false;
29872 } 29873 29874 // URL with .html in author mode 29875 article.url = News.ContentList.fixStoryLinkInAuthorMode(article.url); 29876 29877 var html = News.ContentList.getArticleHtml(article, layoutType, showInlineVideo) 29878 29879 // Now create an article node and place it into the content list 29880 var articleTag = document.createElement("article") 29881 if (showInlineVideo === 'true' && article.hasVideo && article.hasVideo !== 'videoHide') { 29882 articleTag.classList.add('showing-ivp'); 29883 } 29884 articleTag.innerHTML = html 29885 articleContainer.append(articleTag) 29886 29887 // Add "non-video-article" class to articleContainer and articleTag to avoid showing inline video player styling when IVP is enabled but the article has no video or is set to videoHide 29888 if (showInlineVideo === 'true' && (!article.hasVideo || article.hasVideo === 'videoHide')) { 29889 $(articleTag).addClass('non-video-article'); 29890 $(articleContainer).addClass('non-video-article'); 29891 } 29892 29893 // Handle video player initialization for articles with videos ONLY 29894 if (i === 0 && article.hasVideo && article.hasVideo !== 'videoHide' && this.layoutTypesForInlineVideos.includes(layoutType) && showInlineVideo === 'true') { 29895 News.ContentList.initializeVideoPlayer(articleTag, article.videoDetails) 29896 } 29897 29898 // Regionalize article URLs, Display Scene7 Images, Compute Relative Dates 29899 $(articleTag).trigger('article-append') 29900 if (canonical) { 29901 $(articleTag).find('a').each(function () { 29902 $(this).prop("href", article['canonicalUrl']); 29903 }); 29904 } 29905 }, 29906 29907 /** 29908 * renderArticleInLandingPageContentList 29909 * @param i - index of the current article in the service response list 29910 * @param article - JSON object returned from the article service 29911 * @param container - DOM object, div where the article will be injected 29912 * Sample Article Object: 29913 * {"date":"1536715020000","headline":"Florence heading our way for now","path":"/content/news/stories/2018/09/12/f/florence-heading-our-way-for-now","url":"/nc/charlotte/news/2018/09/12/florence-heading-our-way-for-now","image":"https://images.spectrumnews1.com/is/image/SpectrumNews/tropical_-_prob_of40windspng","damImage":"https://images.spectrumnews1.com/is/image/SpectrumNews/tropical_-_prob_of40windspng","altText":"Probs","previewText":"Florence heading our way for now","location":"Charlotte","categories":"WEATHER","flairText":"","flairType":"","utcFlareOffTime":0} 29914 */ 29915 renderArticleInLandingPageContentList: function (i, article, container, displayAd, canonical, layoutType, showInlineVideo) { 29916 if (i > 0) { 29917 // don't show inline videos beyond the first item 29918 showInlineVideo = false; 29919 } 29920 29921 // URL with .html in author mode 29922 article.url = News.ContentList.fixStoryLinkInAuthorMode(article.url); 29923 var html = News.ContentList.getArticleHtml(article, layoutType, showInlineVideo) 29924 29925 29926 // Now create an article node and place it into the content list 29927 var articleTag = document.createElement("article") 29928 if (showInlineVideo === 'true' && article.hasVideo && article.hasVideo !== 'videoHide') { 29929 articleTag.classList.add('showing-ivp', 'lp-cl'); 29930 } 29931 29932 articleTag.innerHTML = html 29933 var listCount = displayAd ? News.ContentList.LANDING_PAGE_AD_DISPLAY_COUNT : News.ContentList.LANDING_PAGE_DISPLAY_COUNT 29934 if (i > listCount) { 29935 articleTag.className = "hide-landing-article" 29936 } 29937 container.append(articleTag) 29938 29939 // Handle video player initialization for articles with videos ONLY for hero and 1x1 layouts 29940 if (article.hasVideo && article.hasVideo !== 'videoHide' && this.layoutTypesForInlineVideos.includes(layoutType) && showInlineVideo === 'true') { 29941 News.ContentList.initializeVideoPlayer(articleTag, article.videoDetails) 29942 } 29943 29944 // Regionalize article URLs, Display Scene7 Images, Compute Relative Dates 29945 $(articleTag).trigger('article-append') 29946 if (canonical) { 29947 $(articleTag).find('a').each(function () { 29948 $(this).prop("href", article['canonicalUrl']); 29949 }); 29950 } 29951 }, 29952 29953 /** 29954 * Initialize video player for articles with video content 29955 */ 29956 initializeVideoPlayer: function (articleElement, videoDetails) { 29957 try { 29958 // Find the video player container within this article 29959 var videoContainer = $(articleElement).find('.video-player-container') 29960 29961 if (videoContainer.length > 0 && videoDetails.videoPid) { 29962 // Create unique IDs for this video player instance 29963 var uniqueId = 'video-player-' + videoDetails.videoPid 29964 var vodPlayerId = 'vod-player-' + videoDetails.videoPid 29965 29966 // Set the unique IDs 29967 videoContainer.attr('id', uniqueId) 29968 var videoElement = videoContainer.find('video') 29969 videoElement.attr('id', vodPlayerId) 29970 29971 // Set up platform-video-data attributes from article data 29972 var platformVideoData = videoContainer.find('.platform-video-data') 29973 if (platformVideoData.length === 0) { 29974 // Create platform-video-data div if it doesn't exist 29975 platformVideoData = $('<div class="platform-video-data"></div>') 29976 videoContainer.find('.player-wrapper').append(platformVideoData) 29977 } 29978 29979 // Set data attributes that video-player.js expects 29980 platformVideoData.attr({ 29981 'data-pid': videoDetails.videoPid || '',
29982 'data-videothumbnail': videoDetails.videoThumbnail || '', 29983 'data-autoplay': videoDetails.videoAutoPlay || 'false', 29984 'data-logobranding': videoDetails.videoLogoBranding || '', 29985 'data-authenticated': videoDetails.videoAuthentication || '', 29986 'data-authtype': videoDetails.videoAuthType || 'openMode' 29987 }) 29988 29989 if (videoDetails.videoThumbnail) { 29990 videoElement.attr('poster', videoDetails.videoThumbnail); 29991 } 29992 29993 if (typeof News.VideoPlayer !== 'undefined' && News.VideoPlayer.init) { 29994 News.VideoPlayer.init(uniqueId, vodPlayerId, videoDetails); 29995 } else { 29996 console.log('News.VideoPlayer.init is not available'); 29997 } 29998 } 29999 } catch (ex) { 30000 console.log('Error initializing video player:', ex) 30001 } 30002 }, 30003 decodeHtmlEntities: function (str) { 30004 if (!str) { 30005 return ""; 30006 } 30007 var txt = document.createElement("textarea"); 30008 txt.innerHTML = str; 30009 return txt.value; 30010 }, 30011 repairLostAposQ: function (s) { 30012 if (!s || s.indexOf("?") < 0) { 30013 return s || ""; 30014 } 30015 s = s.replace(/^\?([^?]+?)\?(\s|$)/, "'$1'$2"); 30016 s = s.replace(/(\s)\?([^?]+?)\?(\s|$)/g, '$1â$2â$3'); 30017 s = s.replace(/(\w)\?(\w)/g, "$1'$2"); 30018 s = s.replace(/(\d{2})\?s\b/g, "$1's"); 30019 return s; 30020 }, 30021 cleanText: function (s) { 30022 var t = News.ContentList.decodeHtmlEntities(s || ""); 30023 t = News.ContentList.repairLostAposQ(t); 30024 return t; 30025 }, 30026 30027 /** 30028 * Assembles and returns the article tag contents as a string, with placeholders swapped out for variables 30029 * 30030 * @param article - JSON object with variables returned from the article service. 30031 * 30032 * The HTML structure returned includes three sibling divs in one string, intended to be injected in an <article> tag. 30033 */ 30034 getArticleHtml: function (article, layoutType, showInlineVideo) { 30035 article.image = article.image || "" 30036 article.altText = article.altText || "" 30037 article.location = article.location || "" 30038 article.headline = News.ContentList.cleanText(article.headline); 30039 article.previewText = News.ContentList.cleanText(article.previewText); 30040 article.flairText = News.ContentList.cleanText(article.flairText); 30041 30042 let isPodcastArticle = false; 30043 if (article.flairText.includes('PODCAST') || article.podcastDuration) { 30044 isPodcastArticle = true; 30045 } 30046 30047 // Check if article has video and should show video player instead of image 30048 let hasVideo = article.hasVideo && article.hasVideo !== 'videoHide' && this.layoutTypesForInlineVideos.includes(layoutType) && showInlineVideo === 'true'; 30049 30050 // Determine poster image 30051 let posterImage = ''; 30052 if (article.placeholderImage && article.placeholderImage.trim() !== '') { 30053 posterImage = article.placeholderImage; 30054 } else if (article.image) { 30055 posterImage = article.image; 30056 } 30057 30058 // Rules: .flair--single-column-mobile only displays flair in .content-list-layout--4x1-single-column-mobile 30059 let flair1Template = '<div class="flair--single-column-mobile"><a href="{url}"><div data-flair-text="{flairText}" data-flair-off-time="{utcFlareOffTime}" class="flair flair--{flairType}"></div></a></div>' 30060 30061 let articleImageTemplate = '' 30062 30063 // If article has video AND it's hero layout, render video player container instead of image 30064 if (hasVideo) { 30065 articleImageTemplate = News.ContentList.getVideoPlayerHtml(layoutType, posterImage) 30066 } 30067 // If article has image but no video OR not hero layout, render image 30068 else if (article.image != "") { 30069 articleImageTemplate = '<div class="article-image"><a href="{url}"><img alt="{altText}" class="img-responsive" width="1250" height="703" data-src="{image}" src="https://s7d2.scene7.com/is/image/TWCNews/1x1transparent" loading="lazy"><div class="{hasVideo}" data-video-duration="{videoDuration}"><a href="{url}"><div class="triangle"></div><div class="text"><span>{videoDuration}</span></div></a></div></a></div>' 30070 } 30071 // No image and no video 30072 else { 30073 articleImageTemplate = '<div class="article-image-none"></div>' 30074 } 30075 30076 var articleDetailsTemplate = '<div class="article__details list-details"><a class="flair--landing-page" href="{url}"><div data-flair-text="{flairText}" data-flair-off-time="{utcFlareOffTime}" class="flair flair--{flairType}"></div></a><h2 class="headline-only--small"><a href="{url}">{headline}</a></h2><p class="article-preview">{previewText}</p><p><span class="article__location">{location}</span><span class="article__relative-time" data-time="{date}"></span></p><div class="video-length-container"><div class="{hasVideo}" data-video-duration="{videoDuration}"><a href="{url}"><div class="triangle"></div><div class="text"><span>{videoDuration}</span></div></a></div></div></div>' 30077 30078 if(isPodcastArticle && (article.hasVideo === 'videoHide')){ 30079 article.podcastDuration = News.ContentList.formatPodcastDuration(article.podcastDuration) 30080 articleDetailsTemplate = '<div class="article__details list-details"><a class="flair--landing-page" href="{url}"><div data-flair-text="{flairText}" data-flair-off-time="{utcFlareOffTime}" class="flair flair--{flairType}"></div></a><h2 class="headline-only--small"><a href="{url}">{headline}</a></h2><p class="article-preview">{previewText}</p><p><span class="article__location">{location}</span><span class="article__relative-time" data-time="{date}"></span></p><div class="podcast-icon-container"><div class="videoShow" ><a href="{url}"><img src="/etc/designs/news/clientlibs/css/images/icons/icon-microphone.svg" alt="podcast icon" style="width: 16px;height: 16px;flex-grow: 0;object-fit: contain;" /><div class="text"><span>{podcastDuration}</span></div></a></div></div><div class="video-length-container"><div class="{hasVideo}" data-video-duration="{videoDuration}"><a href="{url}"><div class="triangle"></div><div class="text"><span>{videoDuration}</span></div></a></div></div></div>' 30081 } 30082 30083 // Rules: .hide-landing-flair--single-column-mobile doesn't display in .content-list-layout--4x1-single-column-mobile and landing page content list 30084 var flairTemplate = '<a href="{url}"><div data-flair-text="{flairText}" data-flair-off-time="{utcFlareOffTime}" class="flair flair--{flairType} hide-landing-flair--single-column-mobile"></div></a>' 30085 30086 var allDivsTemplate = flair1Template + articleImageTemplate + flairTemplate + articleDetailsTemplate 30087 return News.ContentList.createStringFromTemplate(allDivsTemplate, article) 30088 }, 30089 30090 formatPodcastDuration: function(podcastDuration){ 30091 const time = podcastDuration.split(':').map(Number); 30092 let hr = 0 , min = 0 , sec = 0; 30093 30094 if(time.length === 3){ 30095 [hr, min, sec] = time; 30096 }else if(time.length === 2){ 30097 [min, sec] = time; 30098 }else{ 30099 [sec] = time 30100 } 30101 30102 if(hr > 0){ 30103 return `${hr}:${min.toString().padStart(2,'0')}:${sec.toString().padStart(2,'0')}` 30104 }else if(min > 0){ 30105 return `${min}:${sec.toString().padStart(2,'0')}` 30106 }else{ 30107 return `0:${sec.toString().padStart(2,'0')}` 30108 } 30109 30110 }, 30111 30112 30113 /** 30114 * Generate video player HTML container structure 30115 * Updated to ensure IVP thumbnail loads immediately like non-IVP articles 30116 */ 30117 getVideoPlayerHtml(layoutType, posterImage) { 30118 30119 let playerHtml = ''; 30120 30121 if (layoutType === 'landing-page' || layoutType === 'hero' || layoutType === '1x1') { 30122 playerHtml += '<div class="article-image">'; 30123 } 30124 30125 // Use article image as poster (same as non-IVP logic) 30126 const transparentPixel = 30127 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAA' + 30128 'AAC0lEQVR42mP8/x8AAwMBAAOH1YkAAAAASUVORK5CYII='; 30129 30130 const poster = (posterImage && posterImage.trim() !== '') ? posterImage : transparentPixel; 30131 30132 playerHtml += 30133 '<div class="video-player-container">' + 30134 '<div class="header-player">' + 30135 '<div class="componentWrapper">' + 30136 '<div class="player-wrapper">' + 30137 30138 // preload thumbnail like normal article image 30139 '<link rel="preload" as="image" href="' + poster + '">' + 30140 30141 '<video playsinline webkit-playsinline ' + 30142 'width="1250" height="703" ' + 30143 'poster="' + poster + '" ' + 30144 'preload="metadata" ' + 30145 'style="width:100%;height:auto;" ' +
30146 'data-video-type="vod-inline-content-list">' + 30147 '</video>' + 30148 30149 '</div>' + 30150 '</div>' + 30151 '</div>' + 30152 '</div>'; 30153 30154 if (layoutType === 'landing-page' || layoutType === 'hero' || layoutType === '1x1') { 30155 playerHtml += '</div>'; 30156 } 30157 30158 return playerHtml; 30159 }, 30160 30161 /** 30162 * Helper function to use string templates for rendering HTML 30163 * 30164 * Replaces placeholders of {name} format in template string, by looking for 'name' property in the variables object 30165 */ 30166 createStringFromTemplate: function (template, variables) { 30167 return template.replace(new RegExp("\{([^\{]+)\}", "g"), function (_unused, varName) { 30168 return variables[varName] || ""; 30169 }); 30170 }, 30171 30172 fixStoryLinkInAuthorMode: function (url) { 30173 if (!News.ContentList.authorMode) return url; 30174 if (!/^\/content\/news\/(stories|web-reference-templates)/i.test(location.pathname)) return url; 30175 if (/^\/content\/news\/stories\//i.test(url) && !url.endsWith('.html')) { 30176 return url + '.html'; 30177 } 30178 return url; 30179 }, 30180 30181 /** 30182 * Dynamically loads all content lists that specify using ajax to return results. 30183 * 30184 */ 30185 init: function () { 30186 News.ContentList.authorMode = $("." + News.ContentList.AUTHOR_MODE_CLASS).length > 0; 30187 30188 const contentLists = $('.content-list .ajax--true').filter(News.ContentList.contentListFilter); 30189 let completedCount = 0; 30190 const totalCount = contentLists.length; 30191 let timeoutTriggered = false; 30192 30193 // Track completion of all content lists 30194 const triggerComplete = () => { 30195 if (!timeoutTriggered) { 30196 timeoutTriggered = true; 30197 window.contentListsComplete = true; 30198 $(document).trigger('contentListsComplete'); 30199 } 30200 }; 30201 30202 const checkAllComplete = () => { 30203 completedCount++; 30204 if (completedCount === totalCount) { 30205 triggerComplete(); 30206 } 30207 }; 30208 30209 if (totalCount === 0) { 30210 triggerComplete(); 30211 } else { 30212 // Set 3-second timeout as fallback 30213 setTimeout(triggerComplete, 3000); 30214 30215 contentLists.each(function(index) { 30216 News.ContentList.loadContentList(index, this, checkAllComplete); 30217 }); 30218 } 30219 } // init: function() { 30220 30221 } // ns('News').ContentList 30222 30223// Load all the tag based dynamic content lists 30224 $(News.ContentList.init) 30225 30226})(jQuery); 30227(function ($) { 30228 30229 ns("News.App").Analytics = { 30230 30231 init: function () { 30232 30233 /* 30234 * Core variable for DTM to pull its tracking data 30235 */ 30236 30237 var $adl = $('#analyticsDataLayer'); 30238 30239 window.analyticsDataLayer = { 30240 region : $adl.data('region') != null ? $adl.data('region') : '', 30241 isInternal : $adl.data('is-internal') != null ? String($adl.data('is-internal')) : '', 30242 tags : $adl.data('tags') != null ? $adl.data('tags') : '', 30243 pageCategory : $adl.data('page-category') != null ? $adl.data('page-category') : '', 30244 author : $adl.data('author') != null ? $adl.data('author') : '', 30245 publicationDate : $adl.data('publication-date') != null ? $adl.data('publication-date') : '', 30246 headline : $adl.data('headline') != null ? $adl.data('headline') : '', 30247 hhid : '', 30248 isAuthenticated : window.localStorage.getItem('authenticatedV2')? 'true' : 'false', 30249 contentType : $adl.data('content-type') != null ? $adl.data('content-type') : '', 30250 vodAuthType : $('div.platform-video-data').data('analytics-authtype') ? $('div.platform-video-data').data('analytics-authtype') :'closed', 30251 language : $adl.data('language') != null ? $adl.data('language') : '' 30252 }; 30253 30254 /* 30255 * Added to accommodate the search results app handling its own analytics requests 30256 */ 30257 30258 if (!window.searchapp) { 30259 try { 30260 _satellite.pageBottom(); 30261 } catch (e) { 30262 } 30263 } 30264 30265 this.bindLinkTracking(); 30266 30267 //page view event listener for forward/back 30268 $(window).on("pageShow",function() 30269 { 30270 window.digitalData.event = "pageView"; 30271 }); 30272 }, 30273 30274 bindLinkTracking: function () { 30275 30276 /* 30277 * Header component nav bar TWCNEWS-1329 30278 * 30279 */ 30280 $(".site-header .navbar-nav").on("click", "a", function () { 30281 setWebEvent("navigationLinkTracking", 30282 { 30283 componentName: "header sub nav", 30284 linkText: trim(this.text) 30285 } 30286 ); 30287 }); 30288 30289 /* 30290 * Header component social buttons TWCNEWS-1329 30291 * 30292 */ 30293 $(".site-header .social-icons").on("click", "a", function () { 30294 setWebEvent("postPageLoadAction", 30295 { 30296 componentName: "follow: header", 30297 events: ["siteToolUsed"] 30298 } 30299 ); 30300 }); 30301 30302 /* 30303 * Header component search icon TWCNEWS-1329 30304 * 30305 */ 30306 $(".site-header .icon-SearchButton").on("click", function () { 30307 setWebEvent("postPageLoadAction", 30308 { 30309 componentName: "search: header", 30310 events: ["siteToolUsed"] 30311 } 30312 ); 30313 }); 30314 30315 /* 30316 * Footer component 30317 */ 30318 30319 $("#footerLinks a").on("click", function () { 30320 setWebEvent("navigationLinkTracking", 30321 { 30322 componentName: "footer links", 30323 linkText: trim(this.text) 30324 } 30325 ); 30326 }); 30327 30328 /* 30329 * Footer component social links 30330 */ 30331 30332 $("#footerSocialLinks a").on("click", function () { 30333 setWebEvent("postPageLoadAction", 30334 { 30335 siteTool: "social: follow", 30336 mediaType: trim($(this).data("provider")), 30337 events: ["siteToolUsed", "socialFollow"] 30338 } 30339 ); 30340 }); 30341 30342 /* 30343 * Automated/Manual Weather/Closings alert component 30344 */ 30345 30346 $(".wxAlerts a").on("click", function () { 30347 30348 var componentEle = $(this).closest(".wxAlerts > div") 30349 var componentName = componentEle.data("alertconfigtype") + " " + componentEle.data("alerttype") + " alert"; 30350 30351 setWebEvent("navigationLinkTracking", 30352 { 30353 componentName: componentName, 30354 linkText: trim(this.text), 30355 linkType: "button" 30356 } 30357 ); 30358 }); 30359 30360 /* 30361 * Weather Outlook component "Forecast Button" 30362 */ 30363 30364 $('#wxOutlook').on('click', '#wxOutlookForecastBtn', function () { 30365 setWebEvent("navigationLinkTracking", 30366 { 30367 componentName: "7-day forecast", 30368 linkText: "view 7-day forecast", 30369 linkType: "button" 30370 } 30371 ); 30372 }); 30373 30374 /* 30375 * Weather Outlook component "Radar Button" 30376 */ 30377 30378 $('#wxOutlook').on('click', '#wxOutlookRadarBtn', function () { 30379 setWebEvent("navigationLinkTracking", 30380 { 30381 componentName: "Interactive Radar", 30382 linkText: "Interactive Radar", 30383 linkType: "button" 30384 } 30385 ); 30386 }); 30387 30388 /* 30389 * Quick Links component 30390 */ 30391 30392 $(".quickLinks a").on("click", function () { 30393 setWebEvent("navigationLinkTracking", 30394 { 30395 componentName: "Quick Links Bar", 30396 linkText: trim(this.text) 30397 } 30398 ); 30399 }); 30400 30401 /* 30402 * Section Header component 30403 */ 30404 30405 $(".section-header a").on("click", function () { 30406 setWebEvent("navigationLinkTracking", 30407 { 30408 componentName: "Section Header", 30409 linkText: trim(this.text) 30410 } 30411 ); 30412 }); 30413 30414 /* 30415 * Hero Content List Component article headline link TWCNEWS-1344 30416 */ 30417 $(".hero .article-headline").on("click", "a", function () { 30418 setWebEvent("navigationLinkTracking", 30419 { 30420 componentName: "Hero Content List", 30421 linkText: trim(this.text) 30422 }); 30423 }); 30424 30425 /* 30426 * Hero Content List Component article headline link TWCNEWS-1344 30427 */ 30428 $(".hero .article-image").on("click", "a", function () { 30429 setWebEvent("navigationLinkTracking", 30430 { 30431 componentName: "Hero Content List", 30432 linkText: trim(this.href) 30433 }); 30434 }); 30435 30436 /* 30437 * Hero Content List Component View More button TWCNEWS-1344 30438 */ 30439 $(".hero").on("click", ".btn-view-more", function () { 30440 setWebEvent("navigationLinkTracking", 30441 { 30442 componentName: "Hero Content List", 30443 linkText: "View More" 30444 }); 30445 }); 30446 30447 /* 30448 *Content List component tracking headline TWCNEWS-1345 30449 */ 30450 $("div[class='content-list'] .article-headline").on("click", "a", function () { 30451 30452 var position = $(this).closest(".content-list-item").index(".content-list-item") ; 30453 var text = trim(this.text) + " : " + position ; 30454 30455 setWebEvent("navigationLinkTracking", 30456 { 30457 componentName: "Content List", 30458 linkText: trim(this.text) 30459 }); 30460 }); 30461 30462 /* 30463 *Content List component tracking article image TWCNEWS-1345 30464 */ 30465 $("div[class='content-list'] .article-image").on("click", "a", function () { 30466 30467 var position = $(this).closest(".content-list-item").index(".content-list-item") ; 30468 var text = trim(this.text) + " : " + position ; 30469 30470 setWebEvent("navigationLinkTracking", 30471 { 30472 componentName: "Content List", 30473 linkText: trim(this.href) 30474 }); 30475 }); 30476 30477 /* 30478 * Content List Component View More button tracking TWCNEWS-1345 30479 */ 30480 $("div[class='content-list']").on("click", ".btn-view-more", function () { 30481 setWebEvent("navigationLinkTracking", 30482 { 30483 componentName: "Content List", 30484 linkText: "View More" 30485 }); 30486 }); 30487 30488 /* 30489 *Landing Page Content List component tracking headline TWCNEWS-1352 30490 */ 30491 $(".landing-page .article-headline").on("click", "a", function () { 30492 30493 var position = $(this).closest(".content-list-item").index(".content-list-item") ; 30494 var text = trim(this.text) + " : " + position ; 30495 30496 setWebEvent("navigationLinkTracking", 30497 { 30498 componentName: "Landing Page Content List", 30499 linkText: trim(this.text) 30500 }); 30501 }); 30502 30503 /* 30504 *Landing Page Content List component tracking article image TWCNEWS-1352 30505 */ 30506 $(".landing-page .article-image").on("click", "a", function () { 30507 30508 var position = $(this).closest(".content-list-item").index(".content-list-item") ; 30509 var text = trim(this.text) + " : " + position ; 30510 30511 setWebEvent("navigationLinkTracking", 30512 { 30513 componentName: "Landing Page Content List", 30514 linkText: trim(this.href) 30515 }); 30516 }); 30517 30518 30519 /* 30520 * Calendar component "Sharing" 30521 *
30522 * Using "delegate" to support dynamic calendar content 30523 */ 30524 $("#community-calendar").delegate( "a.shareIcon", "click", function() { 30525 setWebEvent("postPageLoadAction", 30526 { 30527 siteTool: "social: share calendar", 30528 mediaType: trim($(this).data("provider")), 30529 events: ["siteToolUsed", "socialShare"] 30530 } 30531 ); 30532 }); 30533 30534 }, 30535 30536 changeEvents: { 30537 30538 /* 30539 * Weather Outlook component "Slider Change" 30540 * This gets called from function "initSlider" etc/designs/news/clientlibs/js/weather/js/wxOutlook.js 30541 */ 30542 30543 onWxOutLookSlider: function () { 30544 setWebEvent("postPageLoadAction", 30545 { 30546 siteTool: "weather: interactive radar slider used", 30547 events: ["siteToolUsed"] 30548 } 30549 ); 30550 }, 30551 onPlaybackStreamStarted: function(streamAnalytics){ 30552 setWebEvent("postPageLoadAction", 30553 { 30554 channelName : streamAnalytics.analyticsChannel, 30555 videoTitle: streamAnalytics.analyticsTitle, 30556 startTime:"", 30557 products:";;;;event3=0", 30558 events:["liveStreamTimeWatched","videoStart"] 30559 } 30560 ); 30561 }, 30562 30563 continuousPlayback: function(streamAnalytics){ 30564 setWebEvent("postPageLoadAction", 30565 { 30566 channelName: streamAnalytics.analyticsChannel, 30567 videoTitle: streamAnalytics.analyticsTitle, 30568 products:";;;;event3=300", 30569 events:["liveStreamTimeWatched"] 30570 } 30571 ); 30572 }, 30573 30574 onPlaybackStreamStopped: function(streamAnalytics){ 30575 setWebEvent("postPageLoadAction", 30576 { 30577 channelName : streamAnalytics.analyticsChannel, 30578 videoTitle: streamAnalytics.analyticsTitle, 30579 products:";;;;event3=" + streamAnalytics.seconds_remaining, 30580 events:["liveStreamTimeWatched"] 30581 } 30582 ); 30583 }, 30584 30585 onBufferingBegan: function(streamAnalytics){ 30586 setWebEvent("postPageLoadAction", 30587 { 30588 channelName : streamAnalytics.analyticsChannel, 30589 videoTitle: streamAnalytics.analyticsTitle, 30590 streamEventObject:"Buffering", 30591 events:["streamEventObject"] 30592 } 30593 ); 30594 } 30595 30596 } 30597 30598 }; 30599 30600 News.App.Analytics.init(); 30601 30602})(jQuery); 30603 30604(function ($) { 30605 ns("News.App").QuantumAnalytics = { 30606 30607 APPLICATION_NAME: "application", 30608 APPLICATION_USER: "user", 30609 isPlayBackSelected: false, 30610 isPlayBackStarted: false, 30611 isPlaybackStartedAfterRetry: false, 30612 isPlayBackPause: false, 30613 isBufferStarted: false, 30614 isUriAcquired: false, 30615 isUriAcquiredFailed: false, 30616 isPlayBackStopped: false, 30617 isPlayBackExitedBeforeStartByUser: false, 30618 isPlayBackExitedBeforeStartByApp: false, 30619 isPlayBackFailed: false, 30620 isPlaybackFailedBeforeRetry: false, 30621 isPlaybackFailedAfterRetry: false, 30622 isPlaybackAttemptRestart: false, 30623 isPlaybackExitBeforeStartRetryByUser: false, 30624 isPlaybackStartRetrySuccess: false, 30625 isplayerUnmutedBefore: false, 30626 userConfigPostMVPFired: false, 30627 mediaDuration: "", 30628 streamType: "", 30629 videoCodec: "", 30630 pid: "", 30631 tmsId: "", 30632 csid: "", 30633 streamUrl: "", 30634 scrubbingCapability: "", 30635 callSign: "", 30636 detailsTitle: "", 30637 sourceMarket: "", 30638 pageRegion: "", 30639 networkStatus: "", 30640 connType: "", 30641 contentListPageMap: {'politics': 'politicsMain', 'public-safety': 'publicSafety', 'health': 'latestNews'}, 30642 ourjournalists: ["staff-profiles", "bios", "ourteam"], 30643 browserSupportsBitrateTracking: undefined, 30644 30645 doSet: function (netStat) { 30646 var _timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone; 30647 if (window && window.Helix && window.Helix.track) { 30648 window.Helix.set("deviceLocation", {connectionDeviceLocation: "inHome"}); 30649 window.Helix.set("entitlements", {entitlements: "canWatchLive, canWatchVod"}); 30650 window.Helix.set("timeZone", {timeZone: _timeZone}); 30651 window.Helix.set("networkStatus", {networkStatus: netStat}); 30652 window.Helix.set("accountFeatures", {accessibility: true, cDvr: false, boxless: true}); 30653 } 30654 }, 30655 30656 showUnInitializedHelixMsg: function (eid, adhoc) { 30657 var msie = navigator.userAgent; 30658 if (msie.indexOf("MSIE") > -1 || msie.indexOf("Trident/") > -1) { 30659 // IE does not do console.error 30660 } else { 30661 console.warn("Helix wasn't initialized before **EID** was triggered " + eid + ", " + adhoc); 30662 } 30663 }, 30664 30665 setPageRegion: function () { 30666 var str = ""; 30667 if (typeof window.digitalData !== "undefined" && window.digitalData) { 30668 if ((window.digitalData.page.pageRegionParent && window.digitalData.page.pageRegionParent.length !== 0) 30669 && (window.digitalData.page.pageRegion && window.digitalData.page.pageRegion.length !== 0)) { 30670 this.pageRegion = window.digitalData.page.pageRegionParent + "/" + window.digitalData.page.pageRegion 30671 } else { 30672 str = window.digitalData.page.pageID 30673 var res = str.split("/"); 30674 if (str.toLowerCase().indexOf('/content/news'.toLowerCase()) !== -1 && res.length > 4) { 30675 this.pageRegion = res[3] + "/" + res[4] 30676 } 30677 } 30678 } 30679 }, 30680 30681 30682 firesQuantumLoginStart: function (hhid) { 30683 var eventCaseId = 'SpectrumLocal_loginStart_manualAuth'; 30684 if (window && window.Helix && window.Helix.track) { 30685 window.Helix.track(eventCaseId, { 30686 opUserText: hhid, 30687 opType: 'manualAuth', 30688 msgTriggeredBy: 'user', 30689 }); 30690 } else { 30691 this.showUnInitializedHelixMsg(eventCaseId, ""); 30692 } 30693 }, 30694 30695 /** 30696 * this called from method: firesQuantumLoginStopSuccess 30697 */ 30698 firesQuantumLoginStopFailure: function () { 30699 var eventCaseId = 'SpectrumLocal_loginStop_failure_manualAuth'; 30700 if (window && window.Helix && window.Helix.track) { 30701 window.Helix.track(eventCaseId, { 30702 opSuccess: false 30703 }); 30704 } else { 30705 this.showUnInitializedHelixMsg(eventCaseId, ""); 30706 } 30707 }, 30708 30709 firesQuantumLoginStartResumeAuth: function () { 30710 var eventCaseId = 'SpectrumLocal_loginStart_resumeAuth'; 30711 if (window && window.Helix && window.Helix.track) { 30712 window.Helix.track(eventCaseId, { 30713 opType: 'resumeAuth' 30714 }); 30715 } else { 30716 this.showUnInitializedHelixMsg(eventCaseId, ""); 30717 } 30718 }, 30719 30720 firesQuantumLoginStopSuccessResumeAuth: function () { 30721 var eventCaseId = 'SpectrumLocal_loginStop_success_resumeAuth'; 30722 const authState = News.App.Pinxt.AuthState; 30723 let hhid = authState.hhid || Cookies.get('player-hhid'); 30724 let mvpd = authState.mvpd || (authState.tempPass.isActive ? authState.tempPass.mvpd : null) 30725 if (window && window.Helix && window.Helix.track) { 30726 if (window.Helix.get('currentState') !== "initiating") { 30727 this.firesQuantumLoginStartResumeAuth(); 30728 window.Helix.track(eventCaseId, { 30729 accountGUID: hhid, 30730 opSuccess: true, 30731 tvProvider: mvpd, 30732 opType: 'resumeAuth', 30733 accountOauthToken: Cookies.get('login-token') 30734 }); 30735 } 30736 News.App.QuantumAnalytics.getNetworkStatus().then(netStat => { 30737 this.networkStatus = netStat; 30738 this.doSet(netStat); 30739 this.firesQuantumUserConfigSetGuidTvProvider(hhid, mvpd); 30740 this.firesQuantumUserConfigPostMVP(hhid, mvpd); 30741 }) 30742 } else { 30743 this.showUnInitializedHelixMsg(eventCaseId, ""); 30744 } 30745 }, 30746 30747 firesQuantumLoginStopFailureResumeAuth: function () { 30748 var eventCaseId = "SpectrumLocal_loginStop_failure_resumeAuth"; 30749 if (window && window.Helix && window.Helix.track) { 30750 window.Helix.track(eventCaseId, { 30751 opSuccess: false, 30752 appErrorType: 'authentication' 30753 }); 30754 } else { 30755 this.showUnInitializedHelixMsg(eventCaseId, ""); 30756 } 30757 }, 30758 30759 /* 30760 * NEWS-826 30761 * This method will run when a user 30762 * click one of the mvpd icons to go to the login 30763 * page and login is successful 30764 */ 30765 firesQuantumUserConfigSetGuidTvProvider: function (hhid, mvpd, identityGUID, bypassPageGuard) { 30766 var eventCaseId = 'SpectrumLocal_userConfigSet_guid_tvProvider'; 30767 // Historically this event is page-guarded to the watch-live/login pages (a scope from 30768 // the manual-login flow). Auto auth (NEWS-9891) typically completes on the home page, 30769 // so the auto path passes bypassPageGuard=true to fire regardless of page and capture 30770 // visit.account.identityGUID. Manual/resume callers omit the flag and stay page-guarded. 30771 var isAllowedPage = window.digitalData.page && (window.digitalData.page.pageName === "watch_spectrum_news_live" || 30772 window.digitalData.page.pageName === 'login'); 30773 if (bypassPageGuard || isAllowedPage) { 30774 30775 if (window && window.Helix && window.Helix.track) { 30776 var payload = { 30777 accountGUID: hhid, 30778 tvProvider: mvpd, 30779 appName: 'SpectrumLocal', // Example string 30780 };
30781 // COX analytics (NEWS-9891): legacy MVPD identity for auto auth. Only added 30782 // when present; manual/resume-auth callers do not pass it and are unchanged. 30783 // Quantum backend encrypts identityGUID and stores it as encIdentityGUID. 30784 if (identityGUID) { 30785 payload.identityGUID = identityGUID; 30786 } 30787 window.Helix.track(eventCaseId, payload) 30788 } else { 30789 this.showUnInitializedHelixMsg(eventCaseId, ""); 30790 } 30791 } 30792 }, 30793 30794 /** 30795 * possible connectionDeviceLocation values: [inMarket or outOfMarket or inHome or unknown] 30796 */ 30797 firesQuantumUserConfigPostMVP: function (hhid, mvpd) { 30798 var eventCaseId = 'SpectrumLocal_userConfigSet_postMVP'; 30799 if (window && window.Helix && window.Helix.track) { 30800 window.Helix.track(eventCaseId, { 30801 accountGUID: hhid, 30802 tvProvider: mvpd, 30803 appName: 'SpectrumLocal', 30804 }) 30805 } else { 30806 this.showUnInitializedHelixMsg(eventCaseId, ""); 30807 } 30808 this.userConfigPostMVPFired = true; 30809 }, 30810 30811 /* 30812 * This method will run when a user 30813 * click one of the mvpd icons to go to the login 30814 * page and login is successful 30815 * called from launch.html 30816 */ 30817 firesQuantumLoginStopSuccess: function (hhid, mvpd) { 30818 var eventCaseId = 'SpectrumLocal_loginStop_success_manualAuth'; 30819 if (Cookies.get('LIVETVLOGIN-CLICKED') === 'QuantumTagLoginStart') { 30820 Cookies.remove('LIVETVLOGIN-CLICKED'); 30821 if (window && window.Helix && window.Helix.track) { 30822 if (window.Helix.get('currentState') !== "initiating") { 30823 this.firesQuantumLoginStart(hhid); 30824 window.Helix.track(eventCaseId, { 30825 accountGUID: hhid, 30826 accountOauthToken: Cookies.get('login-token'), 30827 tvProvider: mvpd, 30828 opType: 'manualAuth', 30829 opSuccess: true 30830 }) 30831 } 30832 News.App.QuantumAnalytics.getNetworkStatus().then(netStat => { 30833 this.networkStatus = netStat; 30834 this.doSet(netStat) 30835 this.firesQuantumUserConfigSetGuidTvProvider(hhid, mvpd); 30836 this.firesQuantumUserConfigPostMVP(hhid, mvpd); 30837 }) 30838 } else { 30839 this.showUnInitializedHelixMsg(eventCaseId, ""); 30840 } 30841 } 30842 }, 30843 30844 // Auto Auth Events 30845 30846 autoLoginStart: function () { 30847 if (window && window.Helix && window.Helix.track) { 30848 window.Helix.track('SpectrumLocal_AutoAccess_Login_Start') 30849 } 30850 }, 30851 30852 autoLoginSuccess: function (hhid, mvpd) { 30853 if (window && window.Helix && window.Helix.track) { 30854 this.autoLoginStart(); 30855 window.Helix.track('SpectrumLocal_Auto_Login_Success', { 30856 loginCompletedTs: Date.now(), 30857 loginAttemptId: News.App.Pinxt.AuthState.authXTraceId 30858 }) 30859 } 30860 30861 // Set network as "OnNet" since we are behind the Modem 30862 this.doSet("onNet") 30863 30864 // COX analytics (NEWS-9891): emit legacy MVPD as visit.account.identityGUID on the 30865 // guid_tvProvider event for auto auth. Auto auth usually completes on the home page, 30866 // so bypass the watch-live/login page guard to fire wherever auto auth happened. Only 30867 // fired when a legacyMVPD value is resolved (MSO present); absent -> field/event omitted. 30868 var legacyMVPD = (News.App.Pinxt && News.App.Pinxt.AuthState && News.App.Pinxt.AuthState.legacyMVPD) || ''; 30869 if (legacyMVPD) { 30870 this.firesQuantumUserConfigSetGuidTvProvider(hhid, mvpd, legacyMVPD, true); 30871 } 30872 30873 this.firesQuantumUserConfigPostMVP(hhid, mvpd); 30874 localStorage.setItem("autoAuth", "false") 30875 }, 30876 30877 30878 isHomePage: function (digitalDataPg) { 30879 var retBool = false;
30880 var str = digitalDataPg.pageID; 30881 var newstr; 30882 if (str) { 30883 newstr = str.replace("/content/news/", ""); 30884 if (typeof newstr !== 'undefined' && newstr) { 30885 newstr = newstr.split("/"); 30886 // the on-air graphics at /section/On_Air_HTML_Overlay is not a home page 30887 if (newstr.length == 2 && !newstr[1].toLowerCase().includes('overlay')) { 30888 retBool = true 30889 } 30890 } 30891 30892 }//if(str) 30893 return retBool; 30894 }, 30895 30896 trackHomePage: function (digitalDataPg) { 30897 var eventCaseId = 'SpectrumLocal_pageView_home'; 30898 if (window && window.Helix && window.Helix.track) { 30899 var parentMarket = digitalDataPg.pageRegionParent !== "" ? digitalDataPg.pageRegionParent : "none"; 30900 var childMarket = digitalDataPg.pageRegion !== "" ? digitalDataPg.pageRegion : "none"; 30901 var msgEventTypes = ["pageViewInit", "pageViewCompleted"]; 30902 for (var i = 0; i < msgEventTypes.length; i++) { 30903 var msgEventType = msgEventTypes[i]; 30904 window.Helix.track(eventCaseId ? eventCaseId : 'pageView', { 30905 msgEventType: msgEventType, 30906 currPageTitle: digitalDataPg.pageTitle, 30907 msgTriggeredBy: 'user', 30908 viewChildMarket: childMarket, 30909 viewParentMarket: parentMarket, 30910 currPageIsLazyLoad: false 30911 }) 30912 } 30913 } else { 30914 this.showUnInitializedHelixMsg(eventCaseId, ""); 30915 } 30916 }, 30917 30918 getHelixPageName: function (pgnamekey) { 30919 var pageName = pgnamekey; 30920 if (this.contentListPageMap.hasOwnProperty(pgnamekey)) { 30921 pageName = this.contentListPageMap[pgnamekey]; 30922 } 30923 return pageName; 30924 }, 30925 30926 triggerHelixPageviewEvent: function (digitalData) { 30927 var pgName = digitalData.pageName; 30928 var pgTitle = digitalData.pageTitle; 30929 var parentMarket = digitalData.pageRegionParent !== "" ? digitalData.pageRegionParent : "none"; 30930 var childMarket = digitalData.pageRegion !== "" ? digitalData.pageRegion : "none"; 30931 if (pgName && pgName.includes('politics')) { 30932 this.trackPageView(this.getHelixPageName("politicsMain"), "politics", {eventCaseId: "SpectrumLocal_pageView_politicsMain"}, digitalData) 30933 } else if (pgName && pgName.includes('public-safety')) { 30934 this.trackPageView(this.getHelixPageName(pgName), "latestNews", {eventCaseId: "SpectrumLocal_pageView_publicSafety"}, digitalData) 30935 } else if (pgName && pgName.includes('health')) { 30936 if (/exploring-your-health/i.test(pgName)) { 30937 this.trackPageView("exploringYourHealth", "latestNews", {eventCaseId: "SpectrumLocal_pageView_exploringYourHealth"}, digitalData) 30938 } else { 30939 this.trackPageView("health", "latestNews", {eventCaseId: "SpectrumLocal_pageView_health"}, digitalData) 30940 } 30941 } else if (pgName && this.ourjournalists.includes(pgName)) { 30942 this.trackPageView("ourJournalists", "ourJournalists", {eventCaseId: "SpectrumLocal_pageView_ourJournalists"}, digitalData) 30943 } else if (pgName && (pgName.includes('lotto') || pgName.includes('lottery'))) { 30944 this.trackPageView("lottery", "latestNews", {eventCaseId: "SpectrumLocal_pageView_lottery"}, digitalData) 30945 } else if (pgName && (pgName.includes('sports') || pgName.includes('pro'))) { 30946 this.trackPageView("sports", "latestNews", {eventCaseId: "SpectrumLocal_pageView_sports"}, digitalData) 30947 } else if (pgName && (pgName.includes('business'))) { 30948 this.trackPageView("business", "latestNews", {eventCaseId: "SpectrumLocal_pageView_business"}, digitalData) 30949 } else if (pgName && pgName === 'news') { 30950 this.trackPageView("newsMain", "latestNews", {eventCaseId: "SpectrumLocal_pageView_newsMain"}, digitalData) 30951 } else if (pgName && (pgName.includes('recalls'))) { 30952 this.trackPageView("recalls", "latestNews", {eventCaseId: "SpectrumLocal_pageView_recalls"}, digitalData) 30953 } else if (pgName && (pgName.includes('trending'))) { 30954 this.trackPageView("trending-topics", "latestNews", {eventCaseId: "SpectrumLocal_pageView_trendingTopics"}, digitalData) 30955 } else if (pgName && (pgName.includes('radar'))) { 30956 this.trackPageView("interactiveRadar", "weather", {eventCaseId: "SpectrumLocal_pageView_interactiveRadar"}, digitalData) 30957 } else if (pgName && (pgName.includes('live-video'))) { 30958 this.trackPageView("playerLiveTv", "liveTv", {eventCaseId: "SpectrumLocal_pageView_playerLiveTv"}) 30959 } else if (pgName && (pgName.includes('splash'))) { 30960 this.trackPageView("splash", "splash", {eventCaseId: "SpectrumLocal_Web_pageView_splash"}, digitalData) 30961 } else if (pgName && /exploring-your-health/i.test(pgName)) { 30962 this.trackPageView("exploringYourHealth", "latestNews", {eventCaseId: "SpectrumLocal_pageView_exploringYourHealth"}, digitalData) 30963 } else if (pgName && (pgName.includes('7-day-forecast'))) { 30964 this.trackPageView("sevenDayForecast", "weather", {eventCaseId: "SpectrumLocal_pageView_sevenDayForecast"}, digitalData) 30965 } else if (pgName && (pgName.includes('weather'))) { 30966 if (/weather-blogs/i.test(pgName) || /weather-experts-blog/i.test(pgName)) { 30967 this.trackPageView("weatherBlog", "weather", {eventCaseId: "SpectrumLocal_pageView_weatherBlog"}, digitalData) 30968 } else this.trackPageView("weatherMain", "weather", {eventCaseId: "SpectrumLocal_pageView_weatherMain"}, digitalData) 30969 } else if (pgName && (pgName.includes('watches-warnings'))) { 30970 this.trackPageView("watchesWarnings", "weather", {eventCaseId: "SpectrumLocal_pageView_watchesWarnings"}, digitalData) 30971 } else if (pgName && (/traffic/i.test(pgName) || /transit/i.test(pgName))) { 30972 if (/traffic-news/i.test(pgName) || /traffic-growth/i.test(pgName) || /transit/i.test(pgName) || pgName === "traffic") { 30973 this.trackPageView("trafficNews", "traffic", {eventCaseId: "SpectrumLocal_pageView_trafficNews"}, digitalData) 30974 } else if (/traffic-map/i.test(pgName)) { 30975 this.trackPageView("trafficMap", "traffic", {eventCaseId: "SpectrumLocal_pageView_trafficMap"}, digitalData) 30976 } 30977 } else { 30978 this.trackPageView(pgName, pgTitle, {eventCaseId: "SpectrumLocal_pageView_generic"}, digitalData) 30979 } 30980 }, 30981 30982 trackPageView: function (pageName, pageTitle, adHocData, digitalData, pageUrl) { 30983 var eventCaseId = adHocData.eventCaseId; 30984 if (window && window.Helix && window.Helix.track) { 30985 var msgEventTypes = ["pageViewInit", "pageViewCompleted"]; 30986 var parentMarket = (digitalData && digitalData.pageRegionParent !== "") ? digitalData.pageRegionParent : "none"; 30987 var childMarket = (digitalData && digitalData.pageRegion !== "") ? digitalData.pageRegion : "none"; 30988 for (var i = 0; i < msgEventTypes.length; i++) { 30989 var msgEventType = msgEventTypes[i]; 30990 window.Helix.track( 30991 eventCaseId ? eventCaseId : 'SpectrumLocal_pageView_generic', 30992 Object.assign( 30993 { 30994 msgEventType: msgEventType, 30995 currPageUrl: pageUrl || window.location.href, 30996 currPageName: pageName, 30997 currPageAppSection: pageTitle, 30998 currPageId: digitalData ? digitalData.pageID : '', 30999 currPageIsLazyLoad: true, 31000 viewChildMarket: childMarket, 31001 viewParentMarket: parentMarket, 31002 }, 31003 adHocData 31004 ) 31005 ); 31006 } 31007 } else { 31008 this.showUnInitializedHelixMsg(eventCaseId, adHocData); 31009 } 31010 }, 31011 31012 trackArticle: function (digitalDataPg) { 31013 var eventCaseId = 'SpectrumLocal_pageView_article'; 31014 if (window && window.Helix && window.Helix.track) { 31015 var parentMarket = digitalDataPg.pageRegionParent !== "" ? digitalDataPg.pageRegionParent : "none"; 31016 var childMarket = digitalDataPg.pageRegion !== "" ? digitalDataPg.pageRegion : "none"; 31017 var msgEventTypes = ["pageViewInit", "pageViewCompleted"]; 31018 for (var i = 0; i < msgEventTypes.length; i++) { 31019 var msgEventType = msgEventTypes[i]; 31020 window.Helix.track(eventCaseId, { 31021 msgEventType: msgEventType, 31022 currPageAppSection: digitalDataPg.pageTitle, 31023 currPageId: digitalDataPg.pageID, 31024 msgTriggeredBy: 'user', 31025 currPageName: digitalDataPg.pageName, 31026 currPagePageType: digitalDataPg.pageFunction, 31027 viewChildMarket: childMarket, 31028 viewParentMarket: parentMarket, 31029 currPageIsLazyLoad: false 31030 }) 31031 } 31032 } else { 31033 this.showUnInitializedHelixMsg(eventCaseId, ""); 31034 } 31035 }, 31036 31037 trackHelixPageviewEvents: function (digitalData) { 31038 if (typeof digitalData !== 'undefined' && digitalData) { 31039 if (typeof $('#analyticsDataLayer').data('headline') === 'undefined') { 31040 if (this.isHomePage(digitalData.page)) { 31041 this.trackHomePage(digitalData.page) 31042 } else { 31043 this.triggerHelixPageviewEvent(digitalData.page) 31044 } 31045 31046 } else if (typeof $('#analyticsDataLayer').data('headline') !== 'undefined' && digitalData.page.pageID) { 31047 const arr = digitalData.page.pageID.split("/"); 31048 if (arr.length > 4 && /stories/i.test(arr[4])) { 31049 this.trackArticle(digitalData.page); 31050 } 31051 } 31052 } 31053 }, 31054 31055 /** 31056 * will generate 'All_Generic_API_Call_Success' quantum events 31057 * for each ajax api call or 'All_Generic_API_Call_Failure' quantum events 31058 * for each unsuccessful ajax api call 31059 */ 31060 quantumApiSuccessOrFailure: function (pathname, status, eventCaseId, ajaxTime, httpVerb, qp, responseText, responseObject, gqlOperationType) { 31061 // NEWS-9752: A response code of 0 means the request never received an 31062 // HTTP response â an offline/aborted request (interval pollers firing 31063 // while offline or backgrounded, or an in-flight call cancelled by page 31064 // navigation). These are not genuine API failures and must not be 31065 // reported to Quantum, where they distort the success-rate metric. 31066 if (status === 0 || status === '0') { 31067 return; 31068 } 31069 31070 let domain = ""; 31071 const responseTime = (new Date().getTime() - ajaxTime); 31072 const hasNoQueryStringParam = (!qp || qp.trim().length === 0 || qp === '{}'); 31073 let traceId = News.App.QuantumAnalytics.extractTraceId(responseObject); 31074 let responseSize = News.App.QuantumAnalytics.extractResponseSize(responseObject); 31075 31076 if (typeof pathname !== 'undefined' && pathname.startsWith("http")) { 31077 // valid URL so we can parse using URL API 31078 const pathUrl = new URL(pathname); 31079 domain = pathUrl.host; 31080 31081 // only use pathUrl.search for qp param value if not present in params 31082 if (hasNoQueryStringParam) { 31083 qp = pathUrl.search; 31084 } 31085 pathname = pathUrl.pathname; 31086 } 31087 else if (typeof pathname !== 'undefined') { 31088 // pathname doesn't start with http so try to parse out query string 31089 if (pathname.includes('?') && hasNoQueryStringParam) { 31090 qp = pathname.substring(pathname.indexOf('?')); 31091 } 31092 } 31093 31094 // NEWS-3732 -- Setting any blank domain value to "spectrumlocalnews.com" to align with other applications. 31095 domain = domain ? domain : "spectrumlocalnews.com"; 31096 31097 // For GQL events the qp parameter is a JSON-stringified request body, not a URL query string, 31098 // so the "must contain =" guard does not apply. For REST events keep the existing behaviour. 31099 // (NEWS-9788: fixes application.api.queryParameters being blanked for GQL events.) 31100 const isGqlEvent = eventCaseId === 'SpectrumLocal_apiCall_graphQL'; 31101 if (!isGqlEvent && ( !qp || qp.length === 0 || qp === "{}" || !qp.includes("="))) { 31102 qp = ''; 31103 } 31104 31105 let eventPayload = { 31106 appApiHost: domain, 31107 appApiHttpVerb: httpVerb, 31108 appApiPath: pathname, 31109 appApiResponseTimeMs: responseTime, 31110 appApiQueryParameters: qp, 31111 appApiResponseCode: status, 31112 appApiResponseText: responseText ? responseText : '', 31113 appApiTraceId: traceId, 31114 appApiResponseSize: responseSize 31115 } 31116 31117 // Add apiArchitecture for all events and other required fields for graphQL events 31118 if (isGqlEvent) { 31119 const isCallSuccess = status && status.toString()[0] === '2'; 31120 eventPayload.apiArchitecture = 'GQL'; 31121 eventPayload.opSuccess = isCallSuccess ? true : false;
31122 eventPayload.clientServiceResult = isCallSuccess ? 'success' : 'failure'; 31123 // the 'query' type call in getRecentActivityData() passes this parameter -- all others are mutations 31124 eventPayload.gqlOperationType = gqlOperationType ? gqlOperationType : 'mutation'; 31125 } else { 31126 eventPayload.apiArchitecture = 'REST'; 31127 } 31128 31129 if (window && window.Helix && window.Helix.track) { 31130 window.Helix.track(eventCaseId, eventPayload) 31131 } 31132 }, 31133 extractAjaxErrorMessage(jqXHR) { 31134 // Try to use parsed JSON if available 31135 if (jqXHR.responseJSON && typeof jqXHR.responseJSON === 'object') { 31136 return JSON.stringify(jqXHR.responseJSON); 31137 } 31138 // If responseText exists, try parsing it manually 31139 if (jqXHR.responseText) { 31140 try { 31141 const parsed = JSON.parse(jqXHR.responseText); 31142 return JSON.stringify(parsed) 31143 } catch (e) { 31144 // responseText wasn't valid JSON 31145 return jqXHR.responseText; 31146 } 31147 } 31148 // Fallback - return blank string 31149 return ''; 31150 }, 31151 async extractFetchErrorMessage(response) { 31152 try { 31153 const contentType = response.headers.get('content-type') || ''; 31154 if (contentType.includes('application/json')) { 31155 const json = await response.json(); 31156 return JSON.stringify(json); 31157 } else { 31158 const text = await response.text(); 31159 return text || `Request failed with status ${response.status}`; 31160 } 31161 } catch (err) { 31162 return `Request failed: ${err}`; 31163 } 31164 }, 31165 extractTraceId(response) { 31166 let traceId = ''; 31167 try { 31168 if (typeof Response !== 'undefined' && response instanceof Response) { 31169 // Fetch API response object 31170 if (response.headers.get('x-trace-id')) { 31171 traceId = `x-trace-id:${response.headers.get('x-trace-id')}`; 31172 } else if (response.headers.get('x-raven-request-id')) { 31173 traceId = `x-raven-request-id:${response.headers.get('x-raven-request-id')}`; 31174 } 31175 } else { 31176 // jqXHR response object 31177 if (response.getResponseHeader('x-trace-id')) { 31178 traceId = `x-trace-id:${response.getResponseHeader('x-trace-id')}`; 31179 } else if (response.getResponseHeader('x-raven-request-id')) { 31180 traceId = `x-raven-request-id:${response.getResponseHeader('x-raven-request-id')}`; 31181 } 31182 } 31183 } catch(e) { 31184 console.log('error getting traceID from response object', response) 31185 } 31186 return traceId; 31187 }, 31188 31189 extractResponseSize(response) { 31190 let responseSize = ''; 31191 try { 31192 if (typeof Response !== 'undefined' && response instanceof Response) { 31193 responseSize = response.headers.get('Content-Length'); 31194 } else { 31195 // jqXHR response object 31196 responseSize = response.getResponseHeader('Content-Length'); 31197 if (!responseSize) { 31198 // header is absent, so use responseText.length 31199 responseSize = response.responseText ? response.responseText.length : ''; 31200 } 31201 } 31202 } catch(e) { 31203 console.log('error getting responseSize from response object', response) 31204 } 31205 return responseSize; 31206 }, 31207 31208 // Playback events 31209 setContent: function (data) { 31210 this.streamType = data.streamType; 31211 this.videoCodec = data.codec; 31212 this.mediaDuration = data.length; 31213 this.pid = data.pid; 31214 this.tmsId = data.tmsid; 31215 this.seriesId = data.seriesId; 31216 this.title = data.title; 31217 this.streamUrl = Cookies.get('stream-url') 31218 this.csid = data.csid || this.getCallSign("csid"); 31219 }, 31220 31221 getCallSign: function (name) { 31222 var match = RegExp('[?&]' + name + '=([^&]*)').exec(this.streamUrl); 31223 return match && decodeURIComponent(match[1].replace(/\+/g, ' ')); 31224 }, 31225 31226 getDigitalDataContent: function () { 31227 if (typeof window.digitalData !== 'undefined' && window.digitalData) { 31228 this.detailsTitle = window.digitalData.page.pageTitle 31229 this.sourceMarket = window.digitalData.page.sourceMarketTag 31230 } 31231 }, 31232 31233 drmType: function () { 31234 let result = bowser.getParser(navigator.userAgent).getResult(); 31235 if (result.browser.name === "Safari") { 31236 return 'fairplay' 31237 } else { 31238 return 'widevine' 31239 } 31240 }, 31241 31242 ccCapable: function () { 31243 return !(this.streamType === 'progressive'); 31244 }, 31245 31246 playbackSelect: function (event_id, type, bookMarkPos, contentUri,analyticsData) { 31247 return new Promise((resolve, reject) => { 31248 this.isPlayBackExitedBeforeStartByUser = false;
31249 // NEWS-7558 Prevent playback tracking events when bitrate tracking unsupported by browser 31250 if (this.doesBrowserSupportBitrateTracking() === false) { 31251 console.log('browser does not support bitrate tracking. preventing playbackSelect event.'); 31252 let customEventDetails = { 31253 customName: 'QuantumPlaybackSuppressed', 31254 customDomain: 'AnalyticsSuppressed', 31255 customLevel: 'info', 31256 customMessage: { 31257 "playbackType": type === 'vod' || type === 'replay' ? 'vod' : 'linear', 31258 "reason": "Not possible to report bitRate for playback" 31259 } 31260 } 31261 this.sendCustomEvent(customEventDetails); 31262 return resolve(false); 31263 } else { 31264 console.log('browser supports bitrate tracking.') 31265 } 31266 31267 const firePlaybackSelect = (eventDetails) => { 31268 window.Helix && window.Helix.track && window.Helix.track(event_id, eventDetails); 31269 this.isPlayBackSelected = true; 31270 this.isPlaybackFailedAfterRetry = false; 31271 this.isPlayBackStopped = false; 31272 return resolve(true); 31273 } 31274 31275 const tryPlaybackSelect = (event_id, type, bookMarkPos, contentUri,analyticsData, retries) => { 31276 this.getDigitalDataContent(); 31277 this.setPageRegion(); 31278 if (type === 'vod' || type === 'replay') { 31279 this.scrubbingCapability = 'all' 31280 } else { 31281 this.scrubbingCapability = 'none' 31282 } 31283 let eventDetails = { 31284 msgTriggeredBy: this.APPLICATION_NAME, 31285 ctntContentFormat: 'HD', 31286 ctntStrmingFormat: this.streamType, 31287 ctntDetailsRuntime: this.mediaDuration, 31288 ctntStrmCCCapable: this.ccCapable(), 31289 ctntStrmEntitled: true, 31290 ctntStrmSapCapable: false, 31291 ctntStrmParntllyBlocked: true, 31292 ctntStrmScrubbingCapability: this.scrubbingCapability 31293 } 31294 31295 if (type === 'vod') { 31296 eventDetails.ctntStrmBkmrkPosSec = bookMarkPos; 31297 eventDetails.ctntIdProviderAssetId = this.pid; 31298 eventDetails.ctntDetailsTitle = analyticsData.text; 31299 eventDetails.sourceMarket = this.sourceMarket; 31300 } 31301 if (type === 'linear') { 31302 eventDetails.ctntIdTmsGuideId = this.tmsId; 31303 eventDetails.ctntStrmDrmType = this.drmType(); 31304 eventDetails.ctntStrmPgmrCallSign = this.csid; 31305 eventDetails.ctntIdTmsSeriesId = this.tmsId; 31306 } 31307 if (type === 'live' || type === 'replay') { 31308 eventDetails.ctntStrmDrmType = this.drmType(); 31309 eventDetails.ctntStrmPgmrCallSign = this.csid; 31310 eventDetails.ctntIdProviderAssetId = this.pid; 31311 eventDetails.ctntStrmCtntUri = contentUri; 31312 eventDetails.opType = "playbackPlaySelected"; 31313 } 31314 if (type === 'replay') { 31315 eventDetails.ctntStrmBkmrkPosSec = 0; 31316 } 31317 31318 // When loading a linear video page, playbackSelect sometimes fires before userConfigSet, which violates state rules in Helix 31319 // So we delay the playbackSelect event until userConfig event can fire 31320 if (this.userConfigPostMVPFired || type !== 'linear') { 31321 firePlaybackSelect(eventDetails); 31322 } else { 31323 let trackRetries = retries && typeof(retries) === 'number' ? retries + 1 : 1; 31324 if (trackRetries < 5) { 31325 // event not allowed with current Helix state, so retry again over next 2.5 seconds (5 x .5s) 31326 setTimeout(() => { 31327 tryPlaybackSelect(event_id, type, bookMarkPos, contentUri,analyticsData, trackRetries
31327); 31328 }, 500) 31329 } else { 31330 firePlaybackSelect(eventDetails); 31331 } 31332 } 31333 31334 } 31335 tryPlaybackSelect(event_id, type, bookMarkPos, contentUri,analyticsData); 31336 }) 31337 31338 }, 31339 31340 uriAcquiredSuccess: function (event_id, streamUrl) { 31341 if (this.isPlayBackSelected && !this.isPlayBackStarted && !(this.isPlayBackExitedBeforeStartByUser || this.isPlayBackExitedBeforeStartByApp)) { 31342 window.Helix && window.Helix.track && window.Helix.track(event_id, { 31343 msgTriggeredBy: this.APPLICATION_NAME, 31344 ctntStrmCtntUri: streamUrl, 31345 videoCodec: this.videoCodec 31346 }) 31347 this.isUriAcquired = true; 31348 } 31349 }, 31350 31351 uriAcquiredFailure: function (event_id) { 31352 if (this.isPlayBackSelected && !(this.isPlayBackStarted || this.isPlaybackStartedAfterRetry) && !(this.isPlayBackExitedBeforeStartByUser || this.isPlayBackExitedBeforeStartByApp) && !this.isUriAcquiredFailed) { 31353 window.Helix && window.Helix.track && window.Helix.track(event_id, { 31354 msgTriggeredBy: this.APPLICATION_NAME, 31355 opSuccess: false, 31356 videoCodec: this.videoCodec 31357 }) 31358 this.isUriAcquiredFailed = true; 31359 } 31360 }, 31361 31362 playbackStarted: function (event_id, bitRate) { 31363 if (event_id.includes('Boxcast') || event_id.includes('Hudl')) { 31364 // for HSS, the Uri Acquired event is not fired. Set it to true to allow following events to fire 31365 this.isUriAcquired = true; 31366 } 31367 if (this.isUriAcquired && !(this.isPlayBackExitedBeforeStartByUser || this.isPlayBackExitedBeforeStartByApp)) { 31368 let eventValues = { 31369 msgTriggeredBy: this.APPLICATION_NAME, 31370 plbkBtRtCurrBtRtBps: bitRate, 31371 } 31372 31373 // For HSS replay (VOD) events, include ctntDetailsActualRuntime 31374 if (event_id.includes('playbackStart_vod')) { 31375 eventValues.ctntDetailsActualRuntime = this.mediaDuration; 31376 } 31377 31378 window.Helix && window.Helix.track && window.Helix.track(event_id, eventValues); 31379 News.App.QuantumAnalytics.getNetworkStatus().then(netStat => { 31380 if (this.networkStatus !== netStat) { 31381 this.fireNetworkChange(netStat) 31382 } 31383 }) 31384 this.isPlayBackStarted = true; 31385 } 31386 }, 31387 31388 playbackFailed: function (event_id, errorMessage, errorCode, fullErrorObject) { 31389 if (this.isPlayBackSelected && !(this.isPlayBackExitedBeforeStartByUser || this.isPlayBackExitedBeforeStartByApp) && !this.isPlayBackFailed) { 31390 let category = fullErrorObject && fullErrorObject.category ? fullErrorObject.category : null; 31391 // errorParams were re-mapped in NEWS-2415 31392 let errorParams = { 31393 msgTriggeredBy: this.APPLICATION_NAME, 31394 // application.error.errorMessage 31395 appErrorMessage: errorMessage, 31396 // application.error.clientErrorCode 31397 appClientErrorCode: this.getShakaClientErrorCodeDescription(category), 31398 // application.error.errorCode 31399 appErrorCode: errorCode, 31400 // application.error.errorExtras.nativeErrorCode 31401 nativeErrorCode: errorCode, 31402 // application.error.errorExtras.nativeErrorName 31403 nativeErrorName: fullErrorObject.data ? fullErrorObject.data : fullErrorObject ? fullErrorObject : '' 31404 } 31405 if (event_id?.includes("Playback_Failure")) { 31406 errorParams.appErrorType = "playback"; 31407 } 31408 31409 window.Helix && window.Helix.track && window.Helix.track(event_id, errorParam
31409s) 31410 this.isPlayBackFailed = true; 31411 } 31412 }, 31413 31414 playbackStop: function (event_id) { 31415 if ((this.isPlayBackStarted || this.isPlaybackStartedAfterRetry) && !this.isPlayBackFailed && !this.isPlaybackFailedBeforeRetry && !this.isPlaybackFailedAfterRetry && !this.isPlayBackStopped) { 31416 window.Helix && window.Helix.track && window.Helix.track(event_id, { 31417 msgTriggeredBy: this.APPLICATION_NAME, 31418 }) 31419 this.isPlayBackStopped = true; 31420 this.isPlayBackStarted = false; 31421 return true; 31422 } 31423 return false; 31424 }, 31425 31426 playbackExitBeforeStartByUser: function (event_id) { 31427 if (!this.isPlayBackFailed && !this.isPlayBackExitedBeforeStartByApp) { 31428 window.Helix && window.Helix.track && window.Helix.track(event_id, { 31429 msgTriggeredBy: this.APPLICATION_NAME 31430 }); 31431 this.isPlayBackExitedBeforeStartByUser = true; 31432 } 31433 }, 31434 31435 playbackExitBeforeStartByApp: function (event_id, code, message) { 31436 if (News.App.QuantumAnalytics.isPlayBackSelected && !this.isPlayBackFailed) { 31437 window.Helix && window.Helix.track && window.Helix.track(event_id, { 31438 msgTriggeredBy: this.APPLICATION_NAME, 31439 appErrorCode: code, 31440 appErrorMessage: message 31441 }); 31442 this.isPlayBackExitedBeforeStartByApp = true; 31443 } 31444 }, 31445 31446 // Retry Tags 31447 31448 playbackFailureBeforeRetry: function (event_id, errorMessage, errorCode, fullErrorObject) { 31449 let category = fullErrorObject && fullErrorObject.category ? fullErrorObject.category : null; 31450 // errorParams were re-mapped in NEWS-2415 31451 window.Helix && window.Helix.track && window.Helix.track(event_id, { 31452 msgTriggeredBy: this.APPLICATION_NAME, 31453 // application.error.errorMessage 31454 appErrorMessage: errorMessage, 31455 // application.error.clientErrorCode 31456 appClientErrorCode: this.getShakaClientErrorCodeDescription(category), 31457 // application.error.errorCode 31458 appErrorCode: errorCode, 31459 // application.error.errorExtras.nativeErrorCode 31460 nativeErrorCode: errorCode, 31461 // application.error.errorExtras.nativeErrorName 31462 nativeErrorName: fullErrorObject.data ? fullErrorObject.data : '' 31463 }); 31464 this.playbackAttemptRestart("SpectrumLocal_attemptRestart_retryCount", "playbackRestartSelected") 31465 this.isPlaybackFailedBeforeRetry = true; 31466 }, 31467 31468 playbackFailureAfterRetry: function (event_id, errorMessage, errorCode, fullErrorObject) { 31469 let category = fullErrorObject && fullErrorObject.category ? fullErrorObject.category : null; 31470 // errorParams were re-mapped in NEWS-2415 31471 if (!this.isPlaybackFailedAfterRetry) { 31472 window.Helix && window.Helix.track && window.Helix.track(event_id, { 31473 msgTriggeredBy: this.APPLICATION_NAME, 31474 // application.error.errorMessage 31475 appErrorMessage: errorMessage, 31476 // application.error.clientErrorCode 31477 appClientErrorCode: this.getShakaClientErrorCodeDescription(category), 31478 // application.error.errorCode 31479 appErrorCode: errorCode, 31480 // application.error.errorExtras.nativeErrorCode 31481 nativeErrorCode: errorCode, 31482 // application.error.errorExtras.nativeErrorName 31483 nativeErrorName: fullErrorObject.data ? fullErrorObject.data : '' 31484 }); 31485 } 31486 31487 this.isPlaybackFailedAfterRetry = true; 31488 }, 31489 31490 playbackAttemptRestart: function (event_id, restartType) { 31491 window.Helix && window.Helix.track && window.Helix.track(event_id, { 31492 opType: restartType 31493 }); 31494 this.isPlaybackAttemptRestart = true; 31495 }, 31496 31497 playbackExitBeforeStartRetryByUser: function (event_id) {
31498 if (!(this.isPlayBackFailed || this.isPlaybackFailedAfterRetry) && !this.isPlayBackExitedBeforeStartByApp) { 31499 window.Helix && window.Helix.track && window.Helix.track(event_id, { 31500 plbkRetryAttempts: 1 31501 }); 31502 this.isPlaybackExitBeforeStartRetryByUser = true 31503 } 31504 }, 31505 31506 playbackStartRetrySuccess: function (event_id, bitRate) { 31507 if (this.isUriAcquired && !(this.isPlayBackExitedBeforeStartByUser || this.isPlayBackExitedBeforeStartByApp)) { 31508 window.Helix && window.Helix.track && window.Helix.track(event_id, { 31509 msgTriggeredBy: this.APPLICATION_NAME, 31510 plbkBtRtCurrBtRtBps: bitRate, 31511 plbkRetryMethod: "daiEnabledExistingStream" // TODO:: retry method to be dynamic 31512 }) 31513 this.isPlaybackStartRetrySuccess = true; 31514 News.App.QuantumAnalytics.getNetworkStatus().then(netStat => { 31515 if (this.networkStatus !== netStat) { 31516 this.fireNetworkChange(netStat) 31517 } 31518 }) 31519 } 31520 }, 31521 31522 playbackStartAfterRetry: function (event_id, bitRate) { 31523 if (this.isUriAcquired && !(this.isPlayBackExitedBeforeStartByUser || this.isPlayBackExitedBeforeStartByApp)) { 31524 window.Helix && window.Helix.track && window.Helix.track(event_id, { 31525 msgTriggeredBy: this.APPLICATION_NAME, 31526 plbkBtRtCurrBtRtBps: bitRate, 31527 }) 31528 News.App.QuantumAnalytics.getNetworkStatus().then(netStat => { 31529 if (this.networkStatus !== netStat) { 31530 this.fireNetworkChange(netStat) 31531 } 31532 }) 31533 this.isPlaybackStartedAfterRetry = true; 31534 this.isPlaybackFailedBeforeRetry = false; 31535 } 31536 }, 31537 31538 bufferStart: function (event_id) { 31539 if (window.Helix && window.Helix.get('currentState') === "playing") { 31540 if (this.isPlayBackStarted) { 31541 window.Helix && window.Helix.track && window.Helix.track(event_id, { 31542 msgTriggeredBy: this.APPLICATION_NAME, 31543 }) 31544 this.isBufferStarted = true; 31545 } 31546 } 31547 }, 31548 31549 bufferStop: function (event_id) { 31550 if (window.Helix && window.Helix.get('currentState') === "buffering") { 31551 if (this.isBufferStarted) { 31552 window.Helix && window.Helix.track && window.Helix.track(event_id, { 31553 msgTriggeredBy: this.APPLICATION_NAME, 31554 }) 31555 this.isBufferStarted = false; 31556 } 31557 } 31558 }, 31559 31560 playbackPause: function (event_id) { 31561 if (window.Helix && window.Helix.get('currentState') === "playing") { 31562 if (this.isPlayBackStarted && !this.isPlayBackStopped && !this.isPlayBackFailed && !this.isPlayBackPause && !this.isPlaybackFailedAfterRetry) { 31563 window.Helix && window.Helix.track && window.Helix.track(event_id, { 31564 msgTriggeredBy: this.APPLICATION_NAME, 31565 }) 31566 this.isPlayBackPause = true; 31567 } 31568 } 31569 }, 31570 31571 playbackUnPause: function (event_id) { 31572 if (window.Helix && window.Helix.get('currentState') === "paused") { 31573 if (this.isPlayBackPause) { 31574 window.Helix && window.Helix.track && window.Helix.track(event_id, { 31575 msgTriggeredBy: this.APPLICATION_NAME, 31576 }) 31577 this.isPlayBackPause = false; 31578 } 31579 } 31580 }, 31581 31582 playbackBitRateShift: function (event_id, bitrate) { 31583 // These event must comes after a playbackStart event 31584 let eventSent = false; 31585 if (this.isPlayBackStarted && !this.isPlaybackFailedAfterRetry && !this.isPlayBackFailed) { 31586 if (window.Helix && window.Helix.get('currentState') === "playing") { 31587 window.Helix && window.Helix.track && window.Helix.track(event_id, { 31588 msgTriggeredBy: this.APPLICATION_NAME, 31589 plbkBtRtCurrBtRtBps: bitrate 31590 }) 31591 eventSent = true; 31592 } 31593 this.isPlayBackPause = false;
31594 } 31595 return eventSent; 31596 }, 31597 31598 playbackTrackChange_audioCodec: function (event_id, audioCodec, availableAudioTracks) { 31599 if (this.isPlayBackStarted) { 31600 // availableAudioTracks is expected as a comma-separated string per Quantum schema 31601 var tracksValue = Array.isArray(availableAudioTracks) 31602 ? availableAudioTracks.join(',') 31603 : (availableAudioTracks || ''); 31604 window.Helix && window.Helix.track && window.Helix.track(event_id, { 31605 audioCodec: audioCodec, 31606 availableAudioTracks: tracksValue 31607 }); 31608 } 31609 }, 31610 31611 playbackFastForwardSelect: function (pos) { 31612 window.Helix && window.Helix.track && window.Helix.track("SpectrumLocal_user_selects_fastForward_clipVOD", { 31613 plbkTrickPlayScrubType: "fastForward" 31614 }) 31615 }, 31616 31617 playbackFastForwardDeSelect: function (pos) { 31618 window.Helix && window.Helix.track && window.Helix.track("SpectrumLocal_user_deselects_fastForward_clipVOD", { 31619 plbkTrickPlayScrubType: "fastForward", 31620 plbkTrickPlayScrubEndPosSec: Math.round(pos) 31621 }) 31622 }, 31623 31624 playbackFFEvents: function (startPos, endPos) { 31625 if (this.isPlayBackStarted) { 31626 this.playbackFastForwardSelect(startPos) 31627 this.playbackFastForwardDeSelect(endPos) 31628 } 31629 }, 31630 31631 31632 playbackRewindSelect: function (pos) { 31633 window.Helix && window.Helix.track && window.Helix.track("SpectrumLocal_user_selects_rewind_clipVOD", { 31634 plbkTrickPlayScrubType: "rewind" 31635 }) 31636 }, 31637 31638 playbackRewindDeSelect: function (pos) { 31639 window.Helix && window.Helix.track && window.Helix.track("SpectrumLocal_user_deselects_rewind_clipVOD", { 31640 plbkTrickPlayScrubType: "rewind", 31641 plbkTrickPlayScrubEndPosSec: Math.round(pos) 31642 }) 31643 }, 31644 31645 31646 playbackRWEvents: function (startPos, endPos) { 31647 if (this.isPlayBackStarted) { 31648 this.playbackRewindSelect(startPos) 31649 this.playbackRewindDeSelect(endPos) 31650 } 31651 }, 31652 31653 /** 31654 * used to set the cookie for the login resume event' cookies 31655 * @param cookieType 31656 * @returns 31657 */ 31658 setQuantumLoginResumeCookie: function () { 31659 if (typeof Cookies.get("login-resume") === 'undefined' || Cookies.get("login-resume") === undefined) { 31660 this.cookieGeneral("login-resume"); 31661 } 31662 }, 31663 31664 cookieGeneral: function (aCookieName) { 31665 var expireDate = new Date(); //get current date/time 31666 expireDate.setDate(expireDate.getDate() + 60); //add 60 days to today 31667 expireDate = new Date(expireDate.getFullYear(), expireDate.getMonth(), 0, 23, 59, 59); //set to midnight 31668 Cookies.set(aCookieName, true, {expires: expireDate, path: '/'}); 31669 }, 31670 31671 /** 31672 * called from footer-scripts.html 31673 */ 31674 checkQuantumLoginResume: function () { 31675 var isResume = Cookies.get('login-resume') 31676 if (!this.userConfigPostMVPFired) { 31677 if (isResume && isResume === "true") { 31678 this.firesQuantumLoginStopSuccessResumeAuth(); 31679 Cookies.remove('login-resume') 31680 } 31681 } 31682 }, 31683 31684 startTveLoginFlow: function (operationType) { 31685 var eventCaseId = 'NewsAgency_applicationActivity_startTveLoginFlow'; 31686 if (window && window.Helix && window.Helix.track) { 31687 window.Helix && window.Helix.track && window.Helix.track(eventCaseId, { 31688 msgTriggeredBy: this.APPLICATION_NAME, 31689 opType: operationType 31690 //opType : "manualAuth" 31691 }) 31692 } 31693 }, 31694 31695 fireNetworkChange: function (netStatus) { 31696 this.connType = this.getConnectionType(); 31697 // https://prism.spectruminternal.com/SpectrumLocal@Web/quantum-resources/event-cases/SpectrumLocal_connectionChange_networkStatusChange/video?source=client 31698 window.Helix && window.Helix.track && window.Helix.track('SpectrumLocal_connectionChange_networkStatusChange', { 31699 networkConnectType: this.connType, 31700 networkStatus: netStatus 31701 }) 31702 }, 31703 31704 // Behind the modem call 31705 behindTheModemCall: function () { 31706 let api = $('body').data('onplantapi'); 31707 let startTime = new Date().getTime(); 31708 return fetch(api, { 31709 method: 'GET', 31710 headers: { 31711 'Content-Type': 'application/json', 31712 'Accept': 'application/json' 31713 }, 31714 }).then(response => { 31715 if (response.ok) { 31716 News.App.QuantumAnalytics.quantumApiSuccessOrFailure(response.url, response.status, "All_Generic_API_Call_Success", startTime, "GET", "", "", response); 31717 return response.json(); 31718 } else { 31719 News.App.QuantumAnalytics.extractFetchErrorMessage(response).then(responseText => { 31720 News.App.QuantumAnalytics.quantumApiSuccessOrFailure(response.url, response.status, "All_Generic_API_Call_Failure", startTime, "GET", "", responseText, response); 31721 }) 31722 return "unknown" 31723 } 31724 }).catch(error => { 31725 console.error(error) 31726 }) 31727 }, 31728 31729 getNetworkStatus: function () { 31730 return this.behindTheModemCall().then(data => { 31731 if (data && data.WrappedResponse) { 31732 if (data.WrappedResponse.IsOnPlant) { 31733 return "onNet" 31734 } else return "offNet" 31735 } else { 31736 return "unknown" 31737 } 31738 }); 31739 }, 31740 31741 getConnectionType: function () { 31742 31743 if (!window.navigator.onLine) { 31744 return 'offline'; 31745 } 31746 if (window.navigator.connection) { 31747 const connectionType = window.navigator.connection.type; 31748 if (!connectionType) { 31749 return 'unknown'; 31750 } 31751 switch (connectionType) { 31752 case 'ethernet': 31753 return 'wired'; 31754 case 'cellular': 31755 return 'cell'; 31756 case 'none': 31757 return 'offline'; 31758 default: 31759 return connectionType; 31760 } 31761 } 31762 }, 31763 31764 // Ad Events 31765 adBreakStarted: function (adBreakNumber) { 31766 this.isPlayBackSelected && window.Helix && window.Helix.track && window.Helix.track('SpectrumLocal_adBreakStart', { 31767 adBreakNumber: adBreakNumber 31768 }) 31769 }, 31770 31771 adBreakEnded: function () { 31772 this.isPlayBackSelected && window.Helix && window.Helix.track && window.Helix.track('SpectrumLocal_adBreakStop') 31773 }, 31774 31775 adStarted: function (adId, adNbr, adTitle) { 31776 this.isPlayBackSelected && window.Helix && window.Helix.track && window.Helix.track('SpectrumLocal_adStart', { 31777 adId: adId, 31778 adNbr: adNbr, 31779 adTitle: adTitle, 31780 }) 31781 }, 31782 31783 adEnded: function (adDurSec, adStoppedReason) { 31784 this.isPlayBackSelected && window.Helix && window.Helix.track && window.Helix.track('SpectrumLocal_adStop', { 31785 adDurSec: adDurSec, 31786 adStoppedReason: adStoppedReason 31787 }) 31788 }, 31789 31790 // NEWS-7558 - Detect browsers that do not support bitrate (ex: webview / Facebook on iOS) 31791 doesBrowserSupportBitrateTracking: function () { 31792 // on subsequent runs, use last value since browser / ios doesn't change 31793 if (this.browserSupportsBitrateTracking !== undefined) { 31794 return this.browserSupportsBitrateTracking 31795 } 31796 31797 function alertBitrateSupportAndQuantumId(browserSupportsBitrateTracking) { 31798 // Safari UK/WKWebView doesn't allow inspection, so adding a mechanism for QA to find bitrateSupport status and the Helix visitId by using a string in the URL 31799 if (window.location.href.indexOf('qabitratesupportalert=true') !== -1){ 31800 alert(`Browser supports bitrate tracking: ${browserSupportsBitrateTracking}. Helix visitId: ${window.Helix.get("visitId")}`); 31801 } 31802 } 31803 let result = bowser.getParser(navigator.userAgent).getResult(); 31804 if (result.os.name.indexOf('iOS') !== -1) { 31805 // on iOS devices, these userAgent strings represent UI/WKWebView in-app browsers where bitrate tracking is not possible 31806 const facebookRegex = /((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i; 31807 const instagramRegex = /(chromium|instagram)[\/ ]([-\w\.]+)/i; 31808 const chromeMobileIOSRegex = /(CriOS)\/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)(?:\.(\d+)|)/ 31809 if (facebookRegex.test(navigator.userAgent) || instagramRegex.test(navigator.userAgent) || chromeMobileIOSRegex.test(navigator.userAgent)) { 31810 this.browserSupportsBitrateTracking = false;
31811 alertBitrateSupportAndQuantumId(false); 31812 return false; 31813 } 31814 } 31815 if ((result.os.name.indexOf('macOS') !== -1 || result.os.name.indexOf('iOS') !== -1 ) && location.protocol === 'https:' && 'serviceWorker' in navigator !== true){ 31816 // HLS bitrate cannot be determined via serviceWorker because the browser (UIWebView or WKWebView) doesn't allow it 31817 // This will weed out the Safari UI/WKWebView in iOS and Apple Mail in Mac OS X 31818 // serviceWorker functionality is only available in https, so we can only check when page is https 31819 this.browserSupportsBitrateTracking = false; 31820 alertBitrateSupportAndQuantumId(false); 31821 return false; 31822 } else { 31823 this.browserSupportsBitrateTracking = true; 31824 alertBitrateSupportAndQuantumId(true); 31825 return true; 31826 } 31827 }, 31828 31829 getShakaClientErrorCodeDescription: function(category) { 31830 const mapFirstDigitToErrorType = { 31831 "1": "Network", 31832 "2": "Text", 31833 "3": "Media", 31834 "4": "Manifest", 31835 "5": "Streaming", 31836 "6": "DRM", 31837 "7": "Player", 31838 "8": "Cast", 31839 "9": "Storage", 31840 "10": "Ads" 31841 } 31842 if (category && mapFirstDigitToErrorType[`${category}`] ) { 31843 return mapFirstDigitToErrorType[`${category}`] 31844 } else { 31845 return 'Unknown' 31846 } 31847 }, 31848 31849 sendCustomEvent: function(eventDetails) { 31850 window.Helix && window.Helix.track && window.Helix.track("generic_customEvent_video", eventDetails); 31851 } 31852 31853 }; 31854 31855})(jQuery); 31856 31857(function ($) { 31858 31859 ns("News.App").MediaAnalytics = { 31860 STREAMPLAYHEAD: 0, 31861 IsPaused: false, 31862 31863 initMediaAnalyticsData: function (Player, data, playhead) { 31864 this.STREAMPLAYHEAD = Number.isInteger(playhead) ? parseInt(playhead) : 0; 31865 function getParams(data) { 31866 if (data.contentType === "Replay" || data.contentType === "Live") { 31867 // hss live or vod 31868 return { 31869 "media.name": data.text, 31870 "media.id": data.pid, 31871 "media.length": data.length, 31872 "media.contentType": data.contentType === "Replay" ? "vod" : "live", // Replay or Live 31873 "media.playerName": data.playerName, 31874 "media.channel": "High School Sports", 31875 "media.network": data.mediaNetwork, 31876 "analytics.trackingServer": "metrics.timewarnercable.com", 31877 "analytics.reportSuite": window.s ? window.s.account : 'tsgnewsglobal1', 31878 "visitor.marketingCloudOrgId": "5BB1123F5245AE4E0A490D45@AdobeOrg", 31879 "visitor.marketingCloudUserId": window.s ? window.s.marketingCloudVisitorID : '', 31880 "media.sdkVersion": "ma-api-0.0.0", 31881 "analytics.enableSSL": true, 31882 } 31883 31884 } else { 31885 // vod and linear 31886 return { 31887 "media.playerName": Player.getVersion(), 31888 "analytics.trackingServer": "metrics.timewarnercable.com", 31889 "analytics.reportSuite": window.s ? window.s.account : 'tsgnewsglobal1', 31890 "media.contentType": data.contentType, 31891 "media.length": data.length, 31892 "media.id": data.contentType === "linear" ? data.tmsid : data.pid, 31893 "visitor.marketingCloudOrgId": "5BB1123F5245AE4E0A490D45@AdobeOrg", 31894 "visitor.marketingCloudUserId": window.s ? window.s.marketingCloudVisitorID : '', 31895 "media.name": data.text, 31896 "media.channel": "", 31897 "media.sdkVersion": "ma-api-0.0.0", 31898 "analytics.enableSSL": true, 31899 } 31900 } 31901 } 31902 31903 const params = getParams(data); 31904 31905 const analyticsData = { 31906 "playerTime": { 31907 "playhead": Number.isInteger(playhead) ? parseInt(playhead) : 0, 31908 "ts": +new Date() 31909 }, 31910 "eventType": "sessionStart", 31911 "params": params, 31912 "qoeData": News.App.MediaAnalytics.qoeData(Player), 31913 "customMetadata": News.App.MediaAnalytics.customMetaData(data) 31914 } 31915 31916 var promise = News.App.MediaAnalytics.createSession('/api/v1/sessions', analyticsData); 31917 return promise.done(function (res, status, xhr) { 31918 return xhr.getResponseHeader('Location'); 31919 }) 31920 }, 31921 31922 getMediaAnalyticsApi: function () { 31923 let mediaAnalyticsApi = $('body').data('mediaanalyticsapi'); 31924 return mediaAnalyticsApi; 31925 }, 31926 31927 createSession: function (path, data) { 31928 return $.post({ 31929 url: News.App.MediaAnalytics.getMediaAnalyticsApi() + path, 31930 data: JSON.stringify(data), 31931 }) 31932 }, 31933 31934 triggerEvent: function (location, data, useBeacon) { 31935 if (!useBeacon){ 31936 $.post({ 31937 url: News.App.MediaAnalytics.getMediaAnalyticsApi() + location + "/events", 31938 data: JSON.stringify(data) 31939 }) 31940 } else { 31941 const url = News.App.MediaAnalytics.getMediaAnalyticsApi() + location + "/events"; 31942 const beaconData = JSON.stringify(data); 31943 navigator.sendBeacon(url, beaconData); 31944 } 31945 }, 31946 31947 customMetaData: function (data) { 31948 if (data.contentType === "linear") { 31949 if(data.playerState && data.playerState === 'webMiniPlayer'){ 31950 return { 31951 "mvpd": window.digitalData.user.mvpd, 31952 "hhid": window.digitalData.user.hhid, 31953 "platformName": "web", 31954 "tmsID": data.tmsid, 31955 "tmsSeriesId": data.tmsSeriesId, 31956 "liveStreamStartMode" : data.liveStreamStartMode, 31957 "network" : data.network, 31958 "platformName" : 'web', 31959 "playerState" : data.playerState 31960 } 31961 31962 } 31963 return { 31964 "mvpd": window.digitalData.user.mvpd, 31965 "hhid": window.digitalData.user.hhid, 31966 "platformName": "web", 31967 "network" : data.network, 31968 "tmsID": data.tmsid 31969 } 31970 } else if (data.contentType === "vod") { 31971 return { 31972 "mvpd": window.digitalData.user.mvpd, 31973 "hhid": window.digitalData.user.hhid, 31974 "platformName": "web", 31975 "streamType": "video", 31976 "vodAuthType": data.authType, 31977 "network": "Spectrum News: " + window.location.hostname 31978 } 31979 } else if (data.contentType === "Replay" || data.contentType === "Live") { 31980 return { 31981 "streamType": data.contentType === "Replay" ? "vod" : "video", 31982 "mvpd": window.digitalData.user.mvpd, 31983 "hhid": window.digitalData.user.hhid, 31984 "platformName": "web", 31985 "assetSelectContext": data.contentType === "Live" ? "High School Sports-Live" : "High School Sports-Replay" 31986 } 31987 } 31988 }, 31989 31990 playEvent: function (Player, time) { 31991 if (time === undefined) { 31992 time = News.App.MediaAnalytics.STREAMPLAYHEAD; 31993 } 31994 return { 31995 "playerTime": { 31996 "playhead": time, 31997 "ts": +new Date() 31998 }, 31999 "qoeData": News.App.MediaAnalytics.qoeData(Player), 32000 "eventType": "play" 32001 } 32002 }, 32003 32004 pauseStart: function (Player, time) { 32005 News.App.MediaAnalytics.IsPaused = true; 32006 if (time === undefined) { 32007 time = News.App.MediaAnalytics.STREAMPLAYHEAD; 32008 } 32009 return { 32010 "playerTime": { 32011 "playhead": time, 32012 "ts": +new Date() 32013 }, 32014 "qoeData": News.App.MediaAnalytics.qoeData(Player), 32015 "eventType": "pauseStart" 32016 }; 32017 }, 32018 32019 unPause: function (Player, time) { 32020 News.App.MediaAnalytics.IsPaused = false;
32021 if (time === undefined) { 32022 time = News.App.MediaAnalytics.STREAMPLAYHEAD; 32023 } 32024 return { 32025 "playerTime": { 32026 "playhead": time, 32027 "ts": +new Date() 32028 }, 32029 "qoeData": News.App.MediaAnalytics.qoeData(Player), 32030 "eventType": "play" 32031 } 32032 }, 32033 32034 playbackMuteStart: function (time) { 32035 console.log('playbackMuteStart') 32036 if (time === undefined) { 32037 time = News.App.MediaAnalytics.STREAMPLAYHEAD; 32038 } 32039 return { 32040 "playerTime": { 32041 "playhead": time, 32042 "ts": +new Date() 32043 }, 32044 "eventType": "stateStart", 32045 "params": { 32046 "media.state.name": "mute" 32047 } 32048 } 32049 }, 32050 32051 playbackMuteEnd: function (time) { 32052 console.log('playbackMuteEnd') 32053 if (time === undefined) { 32054 time = News.App.MediaAnalytics.STREAMPLAYHEAD; 32055 } 32056 return { 32057 "playerTime": { 32058 "playhead": time, 32059 "ts": +new Date() 32060 }, 32061 "eventType": "stateEnd", 32062 "params": { 32063 "media.state.name": "mute" 32064 } 32065 } 32066 }, 32067 32068 miniPlayerStart: function (time) { 32069 News.App.MediaAnalytics.isMiniPlayerStarted = true; 32070 if (time === undefined) { 32071 time = News.App.MediaAnalytics.STREAMPLAYHEAD; 32072 } 32073 return { 32074 "playerTime": { 32075 "playhead": time, 32076 "ts": +new Date() 32077 }, 32078 "eventType": "stateStart", 32079 "params": { 32080 "media.state.name": "miniplayer" 32081 } 32082 } 32083 }, 32084 32085 miniPlayerStop: function (time) { 32086 News.App.MediaAnalytics.isMiniPlayerStarted = false; 32087 if (time === undefined) { 32088 time = News.App.MediaAnalytics.STREAMPLAYHEAD; 32089 } 32090 return { 32091 "playerTime": { 32092 "playhead": time, 32093 "ts": +new Date() 32094 }, 32095 "eventType": "stateEnd", 32096 "params": { 32097 "media.state.name": "miniplayer" 32098 } 32099 } 32100 }, 32101 fullscreenStart: function (time) { 32102 News.App.MediaAnalytics.isfullscreenStarted = true; 32103 if (time === undefined) { 32104 time = News.App.MediaAnalytics.STREAMPLAYHEAD; 32105 } 32106 return { 32107 "playerTime": { 32108 "playhead": time, 32109 "ts": +new Date() 32110 }, 32111 "eventType": "stateStart", 32112 "params": { 32113 "media.state.name": "fullscreen" 32114 } 32115 } 32116 }, 32117 32118 fullscreenStop: function (time) { 32119 News.App.MediaAnalytics.isfullscreenStarted = false; 32120 if (time === undefined) { 32121 time = News.App.MediaAnalytics.STREAMPLAYHEAD; 32122 } 32123 return { 32124 "playerTime": { 32125 "playhead": time, 32126 "ts": +new Date() 32127 }, 32128 "eventType": "stateEnd", 32129 "params": { 32130 "media.state.name": "fullscreen" 32131 } 32132 } 32133 }, 32134 32135 miniPlayerUnmutedStart: function(time) { 32136 console.log('miniPlayerUnmutedStart') 32137 News.App.MediaAnalytics.isMiniPlayerPlaybackUnmuted = true; 32138 if (time === undefined) { 32139 time = News.App.MediaAnalytics.STREAMPLAYHEAD; 32140 } 32141 return { 32142 "playerTime": { 32143 "playhead": time, 32144 "ts": +new Date() 32145 }, 32146 "eventType": "stateStart", 32147 "params": { 32148 "media.state.name": "miniPlayerUnmute" 32149 } 32150 } 32151 }, 32152 32153 miniPlayerUnmutedEnd: function(time) { 32154 console.log('miniPlayerUnmutedEnd') 32155 News.App.MediaAnalytics.isMiniPlayerPlaybackUnmuted = false;
32156 if (time === undefined) { 32157 time = News.App.MediaAnalytics.STREAMPLAYHEAD; 32158 } 32159 return { 32160 "playerTime": { 32161 "playhead": time, 32162 "ts": +new Date() 32163 }, 32164 "eventType": "stateEnd", 32165 "params": { 32166 "media.state.name": "miniPlayerUnmute" 32167 } 32168 } 32169 }, 32170 32171 playBackFinished: function (Player, time) { 32172 if (time === undefined) { 32173 time = News.App.MediaAnalytics.STREAMPLAYHEAD; 32174 } 32175 return { 32176 "playerTime": { 32177 "playhead": time, 32178 "ts": +new Date() 32179 }, 32180 "qoeData": News.App.MediaAnalytics.qoeData(Player), 32181 "eventType": "sessionComplete" 32182 } 32183 }, 32184 32185 mediaPing: function (Player, time) { 32186 if (time === undefined) { 32187 time = News.App.MediaAnalytics.STREAMPLAYHEAD; 32188 } 32189 return { 32190 "playerTime": { 32191 "playhead": time, 32192 "ts": +new Date() 32193 }, 32194 "qoeData": News.App.MediaAnalytics.qoeData(Player), 32195 "eventType": "ping" 32196 } 32197 }, 32198 32199 bufferStart: function (Player, time) { 32200 if (time === undefined) { 32201 time = News.App.MediaAnalytics.STREAMPLAYHEAD; 32202 } 32203 return { 32204 "playerTime": { 32205 "playhead": time, 32206 "ts": +new Date() 32207 }, 32208 "qoeData": News.App.MediaAnalytics.qoeData(Player), 32209 "eventType": "bufferStart" 32210 }; 32211 }, 32212 sessionEnd: function (Player, time) { 32213 if (time === undefined) { 32214 time = News.App.MediaAnalytics.STREAMPLAYHEAD; 32215 } 32216 return { 32217 "playerTime": { 32218 "playhead": time, 32219 "ts": +new Date() 32220 }, 32221 "qoeData": News.App.MediaAnalytics.qoeData(Player), 32222 "eventType": "sessionEnd" 32223 } 32224 }, 32225 32226 adBreakStart: function (Player) { 32227 return { 32228 "playerTime": { 32229 "playhead": 0, 32230 "ts": +new Date() 32231 }, 32232 "eventType": "adBreakStart", 32233 "params": { 32234 "media.ad.podFriendlyName": "pre-roll", 32235 "media.ad.podIndex": 1, 32236 "media.ad.podSecond": 0 32237 }, 32238 "qoeData": News.App.MediaAnalytics.qoeData(Player), 32239 } 32240 }, 32241 32242 adStart: function (Player) { 32243 return { 32244 "playerTime": { 32245 "playhead": 0, 32246 "ts": +new Date() 32247 }, 32248 "eventType": "adStart", 32249 "params": { 32250 "media.ad.name": "pre-roll", 32251 "media.ad.id": "pre-roll", 32252 "media.ad.length": 0, 32253 "media.ad.podPosition": 1, 32254 "media.ad.playerName": "bitmovin " + Player.bitmovinVersion 32255 }, 32256 "qoeData": News.App.MediaAnalytics.qoeData(Player), 32257 } 32258 }, 32259 32260 adFinished: function (Player) { 32261 return { 32262 "playerTime": { 32263 "playhead": 0, 32264 "ts": +new Date() 32265 }, 32266 "eventType": "adComplete", 32267 "qoeData": News.App.MediaAnalytics.qoeData(Player), 32268 } 32269 }, 32270 adBreakFinished: function (Player) { 32271 return { 32272 "playerTime": { 32273 "playhead": 0, 32274 "ts": +new Date() 32275 }, 32276 "eventType": "adBreakComplete", 32277 "qoeData": News.App.MediaAnalytics.qoeData(Player), 32278 } 32279 }, 32280 32281 qoeData: function (Player) { 32282 let metrics = {}; 32283 if (Player) { 32284 metrics = Player.getPlayerMetrics(); 32285 } 32286 if (!metrics) { 32287 console.debug("currentMetrics are unavailable for player") 32288 } 32289 if (metrics.videoBitrate === 0 || metrics.videoBitrate === undefined || metrics.videoBitrate === null) { 32290 metrics.videoBitrate === 0; 32291 if (window?.shakaPlayerAdapter?.bitrate?.getFirstSegmentBitrate()) { 32292 // for HLS, Shaka player metrics does not have the videoBitrate. Instead, service worker will provide bitrate by parsing the manifest file. 32293 metrics.videoBitrate = window.shakaPlayerAdapter.bitrate.getFirstSegmentBitrate(); 32294 console.debug('metrics.videoBitrate was 0, using shakaPlayerAdapter.bitrate.getFirstSegmentBitrate() value: ' + metrics.videoBitrate); 32295 } else if (metrics.streamBandwidth) { 32296 metrics.videoBitrate = metrics.streamBandwidth 32297 console.debug('metrics.videoBitrate was 0, using metrics.streamBandwidth value: ' + metrics.videoBitrate); 32298 } else { 32299 console.debug('metrics.videoBitrate was 0 and no other bitrate value was available for Adobe Media Analytics qoe'); 32300 } 32301 } 32302 32303 let framesPerSecond = Math.round(metrics.videoFrameRate) || 0, 32304 timeToStart = Math.round(metrics.liveLatency) || 0, 32305 droppedFrames = metrics.droppedFrames || 0 32306 return { 32307 "media.qoe.droppedFrames": droppedFrames, // value returned from player ex. 15 32308 "media.qoe.timeToStart": timeToStart, // value returned from player ex. 5 32309 "media.qoe.framesPerSecond": framesPerSecond, // value returned from player ex. 40 32310 "media.qoe.bitrate": metrics.videoBitrate, // value returned from player ex. 1600 32311 } 32312 }, 32313 32314 streamPingInterval: function (Player, location) { 32315 //set interval to track how long stream has been watched 32316 //store value in this.streamPlayhead 32317 if (!this.streamInterval) { 32318 32319 this.streamInterval = setInterval(function () { 32320 ++News.App.MediaAnalytics.STREAMPLAYHEAD; 32321 }, 1000); 32322 } 32323 if (!this.mediaInterval) { 32324 this.mediaInterval = setInterval(function () { 32325 News.App.MediaAnalytics.triggerEvent(location, News.App.MediaAnalytics.mediaPing(Player)); 32326 }, 10000); 32327 } 32328 }, 32329 32330 vodPingInterval: function (Player, location) { 32331 if (!this.mediaInterval) { 32332 this.mediaInterval = setInterval(function () { 32333 News.App.MediaAnalytics.triggerEvent(location, News.App.MediaAnalytics.mediaPing(Player, Math.round(Player.lastCurrentTime))); 32334 }, 10000); 32335 } 32336 32337 }, 32338 32339 pausePingInterval: function (Player, location) { 32340 if (!this.pauseInterval) { 32341 this.pauseInterval = setInterval(function () { 32342 News.App.MediaAnalytics.triggerEvent(location, News.App.MediaAnalytics.mediaPing(Player, Math.round(Player.lastCurrentTime))); 32343 }, 10000); 32344 } 32345 }, 32346 32347 bufferingPingInterval: function (Player, location) { 32348 if (!this.bufferInterval) { 32349 this.bufferInterval = setInterval(function () { 32350 News.App.MediaAnalytics.triggerEvent(location, News.App.MediaAnalytics.mediaPing(Player, Math.round(Player.lastCurrentTime))); 32351 }, 10000); 32352 } 32353 }, 32354 32355 adPing: function () { 32356 return { 32357 "playerTime": { 32358 "playhead": 0, 32359 "ts": +new Date() 32360 }, 32361 "eventType": "ping" 32362 } 32363 }, 32364 32365 adPingInterval: function (location) { 32366 this.adInterval = setInterval(function () { 32367 News.App.MediaAnalytics.triggerEvent(location, News.App.MediaAnalytics.adPing()) 32368 }, 1000); 32369 }, 32370 32371 clearAdPingInterval: function () { 32372 if (this.adInterval) { 32373 clearInterval(this.adInterval); 32374 this.adInterval = null; 32375 } 32376 }, 32377 32378 clearMediaPingInterval: function () { 32379 if (this.mediaInterval) { 32380 clearInterval(this.mediaInterval); 32381 this.mediaInterval = null; 32382 } 32383 }, 32384 32385 clearStreamPlayheadPingInterval: function () { 32386 if (this.streamInterval) { 32387 clearInterval(this.streamInterval); 32388 this.streamInterval = null; 32389 } 32390 }, 32391 32392 clearBufferPingInterval: function () { 32393 if (this.bufferInterval) { 32394 clearInterval(this.bufferInterval); 32395 this.bufferInterval = null; 32396 } 32397 }, 32398 32399 clearPausePingInterval: function () { 32400 if (this.pauseInterval) { 32401 clearInterval(this.pauseInterval); 32402 this.pauseInterval = null; 32403 } 32404 } 32405 32406 } 32407})(jQuery); 32408 32409$(function () { 32410 var pdfHostname = $('.body-container').data('pdfhost'); 32411 var pdfPathname = $('.body-container').data('pdfpath'); 32412 if (pdfPathname && pdfHostname) { 32413 $('.embedpdf').each(function (index, value) { 32414 $(this).hide(); 32415 var currentElement = $(this); 32416 var pdfPath = $(this).find('iframe').attr('src'); 32417 var pdfDocTitle = $(this).find('iframe').attr('alt'); 32418 setTimeout(function () { 32419 if (pdfPath) { 32420 pdfPath = pdfPath.replace('#toolbar=0&navpanes=0', ''); 32421 var serverUrl = pdfHostname + pdfPathname + "?file=" + pdfPath+"&title="+pdfDocTitle; 32422 var pdfElement = '<div class="embed-' + index + '" ><iframe src="' + serverUrl + '" allowfullscreen="allowfullscreen"></div>'; 32423 currentElement.find('iframe').replaceWith(pdfElement); 32424 } 32425 currentElement.show(); 32426 }, 500); 32427 }); 32428 } 32429 32430}
32430); 32431 32432+function ($) { 32433 32434 let noticiasRegion = $('.site-header .header-ele').data('noticias-region'); 32435 32436 if (noticiasRegion) { 32437 32438 // Constants for Spanish translations 32439 const CONSTANTS = { 32440 SEARCH_PLACEHOLDER: 'Buscar', 32441 LIVE_NOW: 'EN VIVO', 32442 CURRENTLY_PLAYING: 'REPRODUCIENDO ACTUALMENTE', 32443 ALL_SPECTRUM_NEWS_CHANNELS: 'TODOS LOS CANALES DE SPECTRUM NEWS', 32444 MOBILEACCOUNT: 'CUENTA', 32445 SOCIAL_SHARE: 'COMPARTIR', 32446 SUBMIT_EVENT:{ 32447 EVENT_CALENDAR:{ 32448 MON: 'Lu', 32449 TUE: 'Ma', 32450 WED: 'Mi', 32451 THU: 'Ju', 32452 FRI: 'Vi', 32453 SAT: 'Sà ', 32454 SUN: 'Do' 32455 }, 32456 LIMIT: '65', 32457 SUBMIT_BTN: 'ENVIAR EVENTO DEL CALENDARIO', 32458 SUBMIT_BTN_CAL: 'ENVIAR EVENTO DEL CALENDARIO', 32459 EVENT_HEAD: 'Enviar evento', 32460 EVENT_INFO: 'Información del evento', 32461 CONT_INFO: 'Información de contacto', 32462 EVENT_FORM: { 32463 NAME: 'Nombre del evento *', 32464 URL: 'URL del evento', 32465 LOCATION: 'Vecindario *', 32466 EVENT_TYPE: 'Tipo de evento *', 32467 START_DATE: 'Fecha de inicio del evento *', 32468 END_DATE: 'Fecha de finalización del evento *', 32469 START_TIME: 'Hora de inicio del evento *', 32470 END_TIME: 'Hora de finalización del evento *', 32471 COST: 'Costo', 32472 COST_RANGE: 'Rango de costos', 32473 DESCRIPTION: 'Descripción del evento *', 32474 VENUE: 'Nombre del lugar *', 32475 VENUE_STREET: 'Nombre y número de la calle del lugar *', 32476 VENUE_CITY: 'Ciudad/Vecindario del lugar *', 32477 ZIPCODE: 'Código postal', 32478 CONTACT_NAME: 'Nombre del contacto', 32479 CONTACT_EMAIL: 'Correo electrónico del contacto', 32480 CONTACT_PHONE: 'Número de teléfono del contacto', 32481 VALIDATION_MESSAGE: 'Completa este campo' , 32482 REQUIRED: '* Obligatorio', 32483 CHAR_LIMIT: (limit)=>{ 32484 return `Máximo ${limit} caracteres` 32485 }, 32486 COST_VALIDATION: '* Se requiere el costo o el rango de costos', 32487 FREQUENCY_OPTIONS: ['Frecuencia del evento', 'Semanal', 'Mensual'], 32488 OR_LABEL: 'O', 32489 COST_OPTION_FREE: 'Gratis', 32490 CONTACT_INFO:`La información no se mostrará en la página del evento, pero nos brindará detalles sobre la mejor manera de comunicarnos con su organización.`, 32491 REPEAT: 'Repetir cada', 32492 MONTH: 'Mes', 32493 DATEPICKER_PLACEHOLDER: 'dd/mm/yyyy' 32494 } 32495 } 32496 32497 } 32498 32499 //Search placeholder - spanish changes 32500 $('.searchNav .empire-header-search-field').each(function () { 32501 $(this).attr('placeholder', CONSTANTS.SEARCH_PLACEHOLDER); 32502 }) 32503 32504 //Watch Live component - spanish changes 32505 $('.live-tv .watch-live-card-container').each(function () { 32506 $(this).find('.live-status').text(CONSTANTS.LIVE_NOW); 32507 $(this).find('.currently-playing').text(CONSTANTS.CURRENTLY_PLAYING); 32508 $(this).find('.card-container h2').text(CONSTANTS.ALL_SPECTRUM_NEWS_CHANNELS); 32509 }); 32510 32511 // Live Stream Promo component - spanish changes 32512 $('.live-stream-promo--container .live-stream-right-block').each(function () { 32513 $(this).find('.live-badge-text').text(CONSTANTS.LIVE_NOW); 32514 }); 32515 32516 //Mini Live Player - spanish changes 32517 $('.live-tv.live-stream-promo--container.mini-player').each(function () { 32518 $(this).find('.show-when-authenticated.live-badge .live-badge-text').text(CONSTANTS.LIVE_NOW); 32519 $(this).find('.live-stream-right-block .live-badge .live-badge-text').text(CONSTANTS.LIVE_NOW); 32520 $(this).find('.mini-player-fallback__live-badge-text').text(CONSTANTS.LIVE_NOW); 32521 $(this).find('.mini-player-fallback__default-live-badge-text').text(CONSTANTS.LIVE_NOW); 32522 }); 32523 32524 //Mobile Menu - spanish changes 32525 document.querySelectorAll('.empire-mobile-item-list .my-account').forEach(element =>{ 32526 element.innerText = CONSTANTS.MOBILEACCOUNT 32527 }) 32528 // Submit Event 32529 let eventForm = $('.event-submit-form'); 32530 eventHead = $('.section-header-inner')[0], 32531 eventInfo = $('.event-info'), 32532 contactInfo = $('.contact-info'); 32533 32534 if (eventForm.length > 0) { 32535 $('#weeklyInput .checkbox .control-label span').each((index, value)=>{ 32536 value.innerText = Object.values(CONSTANTS.SUBMIT_EVENT.EVENT_CALENDAR)[index]; 32537 }); 32538 32539 eventHead.outerText == 'SUBMIT EVENT' ? eventHead.innerText = CONSTANTS.SUBMIT_EVENT.EVENT_HEAD : ''; 32540 eventInfo.find('label')[0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_INFO; 32541 contactInfo.find('label')[0].innerText = CONSTANTS.SUBMIT_EVENT.CONT_INFO; 32542 eventForm.find('.btn')[0].value = CONSTANTS.SUBMIT_EVENT.SUBMIT_BTN; 32543 32544 !!$('#eventName')? $('#eventName').attr('placeholder', CONSTANTS.SUBMIT_EVENT.EVENT_FORM.NAME) : ''; 32545 !!$('#eventUrl') ? $('#eventUrl').attr('placeholder', CONSTANTS.SUBMIT_EVENT.EVENT_FORM.URL) : ''; 32546 !!$('#location')[0] ? $('#location')[0][0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.LOCATION : ''; 32547 !!$('#location')[0] ? $('#location')[0].title = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.LOCATION : ''; 32548 !!$('#eventType')[0] ? $('#eventType')[0][0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.EVENT_TYPE : ''; 32549 !!$('#eventType')[0] ? $('#eventType')[0].title = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.EVENT_TYPE : ''; 32550 !!$('#repeat option') ? $('#repeat option').each((index, value)=> value.innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.FREQUENCY_OPTIONS[index]) : ''; 32551 !!$('#repeat')[0] ? $('#repeat')[0].title = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.FREQUENCY_OPTIONS[0] : '';
32552 !!$('.start-date label')[0] ? $('.start-date label')[0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.START_DATE : ''; 32553 !!$('.end-date label')[0] ? $('.end-date label')[0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.END_DATE : ''; 32554 !!$('.start-time label')[0] ? $('.start-time label')[0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.START_TIME : ''; 32555 !!$('.end-time label')[0] ? $('.end-time label')[0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.END_TIME : ''; 32556 !!$('#costDefined') ? $('#costDefined').attr('placeholder', CONSTANTS.SUBMIT_EVENT.EVENT_FORM.COST) : ''; 32557 !!$('.control-label[for="cost"]')[0] ? $('.control-label[for="cost"]')[0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.OR_LABEL : ''; 32558 !!$('#cost')[0] ? $('#cost')[0][0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.COST_RANGE : ''; 32559 !!$('#cost')[0] ? $('#cost')[0][1].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.COST_OPTION_FREE: ''; 32560 !!$('#cost')[0] ? $('#cost')[0].title = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.COST_RANGE : ''; 32561 !!$('#description') ? $('#description').attr('placeholder', CONSTANTS.SUBMIT_EVENT.EVENT_FORM.DESCRIPTION) : ''; 32562 !!$('#venueName') ? $('#venueName').attr('placeholder', CONSTANTS.SUBMIT_EVENT.EVENT_FORM.VENUE) : ''; 32563 !!$('#street') ? $('#street').attr('placeholder', CONSTANTS.SUBMIT_EVENT.EVENT_FORM.VENUE_STREET): ''; 32564 !!$('#city') ? $('#city').attr('placeholder', CONSTANTS.SUBMIT_EVENT.EVENT_FORM.VENUE_CITY) : ''; 32565 !!$('#zipcode') ? $('#zipcode').attr('placeholder', CONSTANTS.SUBMIT_EVENT.EVENT_FORM.ZIPCODE): ''; 32566 !!$('#name') ? $('#name').attr('placeholder', CONSTANTS.SUBMIT_EVENT.EVENT_FORM.CONTACT_NAME): ''; 32567 !!$('#email') ? $('#email').attr('placeholder', CONSTANTS.SUBMIT_EVENT.EVENT_FORM.CONTACT_EMAIL) : ''; 32568 !!$('#phoneNumber') ? $('#phoneNumber').attr('placeholder', CONSTANTS.SUBMIT_EVENT.EVENT_FORM.CONTACT_PHONE) :''; 32569 !!$('.event-info .help-block')[0] ? $('.event-info .help-block')[0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.REQUIRED:''; 32570 !!$('.cost-validation')[0] ? $('.cost-validation')[0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.COST_VALIDATION : ''; 32571 !!$('.contact-info .help-block')[0] ? $('.contact-info .help-block')[0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.CONTACT_INFO : ''; 32572 !!$('#eventSubmissionUrl')[0] ? $('#eventSubmissionUrl')[0].innerText = CONSTANTS.SUBMIT_EVENT.SUBMIT_BTN_CAL : ''; 32573 !!$('.share-text')[0] ? $('.share-text')[0].innerText = CONSTANTS.SOCIAL_SHARE : ''; 32574 !!$('.event-name .help-block')[0] ? $('.event-name .help-block')[0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.CHAR_LIMIT('65') : ''; 32575 !!$('.description .help-block')[0] ? $('.description .help-block')[0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.CHAR_LIMIT('300') : ''; 32576 !!$('.venue-name .help-block')[0] ? $('.venue-name .help-block')[0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.CHAR_LIMIT('65') : ''; 32577 !!$('.street .help-block')[0] ? $('.street .help-block')[0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.CHAR_LIMIT('32') : ''; 32578 !!$('.city .help-block')[0] ? $('.city .help-block')[0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.CHAR_LIMIT('32') : ''; 32579 !!$('#weeklyInput') ? $('#weeklyInput .label-first')[0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.REPEAT : ''; 32580 !!$('#monthlyInput') ? $('#monthlyInput .label-first')[0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.REPEAT : ''; 32581 !!$('#monthlyInput') ? $('#monthlyInput .label-last')[0].innerText = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.MONTH : ''; 32582 $('.datepicker-field').each((index,value)=>{ 32583 value.placeholder = CONSTANTS.SUBMIT_EVENT.EVENT_FORM.DATEPICKER_PLACEHOLDER 32584 }); 32585 } 32586 } 32587 32588 if (!isAuthorMode()) { 32589 // Check if the host is for spectrumnoticias domain 32590 if (window.location.host.includes('spectrumnoticias')) { 32591 const searchParams = new URLSearchParams(window.location.search); 32592 const overrideLang = searchParams.get('lang'); 32593 if (overrideLang === 'en') {
32594 // With lang=en param on spectrumnoticias domain, hide #es-404 and keep #en-404 32595 $('#es-404').hide(); 32596 } else { 32597 // Without lang=en param on spectrumnoticias, keep #es-404 and hide #en-404 32598 $('#en-404').hide(); 32599 } 32600 32601 } else { 32602 //Hide Spanish 404 content for non-spectrumnoticias hosts 32603 $('#es-404').hide(); 32604 } 32605 } 32606 32607 function isAuthorMode() { 32608 if (typeof CQ != "undefined") { 32609 if (CQ && CQ.WCM && CQ.WCM.isEditMode) { 32610 return CQ.WCM.isEditMode('True') 32611 } 32612 } 32613 } 32614 32615}(jQuery); 32616(function ($) { 32617 "use strict"; 32618 32619 // EXIT IF NOT IN WCM MODE 32620 if (!window.CQ || !CQ.WCM) return; 32621 32622 // CONSTANTS 32623 var LOCK_PROPERTY = "isColumnLocked"; 32624 var SERVLET_URL = "/services/columnlock/state"; 32625 32626 var LOCKABLE_COMPONENTS = [ 32627 ".row.news-column-control[data-path]" 32628 ]; 32629 32630 var COMBINED_SELECTOR = LOCKABLE_COMPONENTS.join(", "); 32631 32632 32633 var LOCKABLE_BUTTON_TEXTS = ["Edit", "Delete"]; 32634 32635 /** 32636 * Walk the EditBar toolbar items and disable/enable buttons whose 32637 * text matches LOCKABLE_BUTTON_TEXTS 32638 */ 32639 function setEditBarButtonStates(editbar, locked) { 32640 if (!editbar || !editbar.items) return; 32641 // EditBar items[0] is the CQ.Ext.Toolbar 32642 var tbar = editbar.items.get(0); 32643 if (!tbar || !tbar.items) return; 32644 32645 tbar.items.each(function (item) { 32646 if (!item || typeof item.getText !== "function") return; 32647 var txt = (item.getText() || "").replace(/<[^>]*>/g, "").trim(); 32648 if (LOCKABLE_BUTTON_TEXTS.indexOf(txt) !== -1) { 32649 if (locked) { 32650 item.disable(); 32651 } else { 32652 item.enable(); 32653 } 32654 } 32655 }); 32656 } 32657 32658 /** 32659 * Disable/enable the physical drag handle on the EditBar. 32660 */ 32661 function setEditBarDrag(editbar, locked) { 32662 if (!editbar) return; 32663 if (locked) { 32664 if (typeof editbar.disableDrag === "function") { 32665 editbar.disableDrag(); 32666 } 32667 } else { 32668 if (typeof editbar.enableDrag === "function") { 32669 editbar.enableDrag(); 32670 } 32671 } 32672 } 32673 32674 /** 32675 * Disable/enable the drop targets on the EditBar so nothing can 32676 * be dropped into a locked column control. 32677 */ 32678 function setEditBarDropTargets(editbar, locked) { 32679 if (!editbar) return; 32680 if (locked) { 32681 if (typeof editbar.suspendDropTargets === "function") { 32682 editbar.suspendDropTargets(); 32683 } 32684 } else { 32685 if (typeof editbar.resumeDropTargets === "function") { 32686 editbar.resumeDropTargets(); 32687 } 32688 } 32689 } 32690 32691 /** 32692 * Apply or remove all OOTB-API-based restrictions on the EditBar 32693 * that corresponds to the given row's column control. 32694 * Resolves the EditBar via CQ.WCM.getEditable(path). 32695 */ 32696 function applyEditBarRestrictions($row, locked) { 32697 var fullPath = $row.data("path"); 32698 if (!fullPath) return; 32699 32700 // Resolve the EditBar instance 32701 // CQ.WCM.getEditable(path) returns the EditBar/EditRollover for that path. 32702 var editbar = CQ.WCM.getEditable(fullPath); 32703 if (!editbar) return; 32704 32705 setEditBarButtonStates(editbar, locked); 32706 setEditBarDrag(editbar, locked); 32707 setEditBarDropTargets(editbar, locked); 32708 } 32709 32710 // ------------------------------------------------------------------------- 32711 // CHILD EDITBARS â find all child .cq-editbar elements that belong to 32712 // this column control using the CSS class prefix pattern. 32713 // 32714 // From the real HTML: 32715 // Parent class : cq-element-main-content-area_47columns_47column0_47columns_95527713850 32716 // Child classes: cq-element-main-content-area_47columns_47column0_47columns_95527713850_47column0_47content_95list_95547414340 32717 // cq-element-main-content-area_47columns_47column0_47columns_95527713850_47column1_47content_95list_951946654155 32718 // cq-element-main-content-area_47columns_47column0_47columns_95527713850_47column2_47content_95list 32719 // cq-element-main-content-area_47columns_47column0_47columns_95527713850_47column3_47campaign 32720 // 32721 // Every child class starts with the parent class + "_47" ("_47" = encoded "/"). 32722 // ------------------------------------------------------------------------- 32723 32724 /** 32725 * Given the parent column control's $editbar DOM element, return a jQuery 32726 * object of all child .cq-editbar elements on the page whose cq-element-* 32727 * class starts with the parent's cq-element-* class + "_47". 32728 */ 32729 function findChildEditbars($parentEditbar) { 32730 if (!$parentEditbar || !$parentEditbar.length) return $(); 32731 32732 // Extract the value after "cq-element-" from the parent editbar's class 32733 var parentClasses = $parentEditbar.attr("class") || ""; 32734 var m = parentClasses.match(/cq-element-(\S+)/); 32735 if (!m) return $(); 32736 32737 var parentElementClass = m[1]; 32738 // Every child's cq-element-* class starts with this prefix 32739 var childPrefix = parentElementClass + "_47"; 32740 32741 return $(".cq-editbar").filter(function () { 32742 var cls = $(this).attr("class") || ""; 32743 var cm = cls.match(/cq-element-(\S+)/); 32744 if (!cm) return false;
32745 return cm[1].indexOf(childPrefix) === 0; 32746 }); 32747 } 32748 32749 32750 /** 32751 * Find the cq-editbar DOM element for a given row using the placeholder 32752 * CSS class pattern. This is the existing approach kept unchanged. 32753 */ 32754 function findEditbarForRow($row) { 32755 var $ph = $row.find('[class*="cq-placeholder-main-content-area"]').first(); 32756 if (!$ph.length) return null; 32757 32758 var match = $ph.attr("class").match(/(main-content-area(?:_[^_]+)*_47columns(?:_\d+)?)_47column[^_]*$/); 32759 if (!match) return null; 32760 32761 var targetClass = "cq-element-" + match[1]; 32762 var $editbar = $(".cq-editbar." + targetClass); 32763 return $editbar.length ? $editbar : null; 32764 } 32765 32766 // ------------------------------------------------------------------------- 32767 // button disable/enable (kept as fallback for 32768 // cases where the OOTB EditBar instance is not yet available on the page) 32769 // ------------------------------------------------------------------------- 32770 32771 function updateButtonStates(locked, $editbar) { 32772 if (!$editbar || !$editbar.length) return; 32773 32774 var buttons = $editbar.find("button.x-btn-text").filter(function () { 32775 var text = $(this).text().trim(); 32776 return text === "Edit" || text === "Delete"; 32777 }); 32778 32779 buttons.each(function () { 32780 var $b = $(this); 32781 var $table = $b.closest("table.x-btn"); 32782 if (locked) { 32783 $table.addClass("x-item-disabled"); 32784 $b.prop("disabled", true); 32785 } else { 32786 $table.removeClass("x-item-disabled"); 32787 $b.prop("disabled", false); 32788 } 32789 }); 32790 32791 32792 } 32793 32794 function updateLockBtnUI($btnEl, locked) { 32795 if (locked) { 32796 $btnEl.text("Unlock").css({ 32797 "color": "#d00", 32798 "font-weight": "bold" 32799 }); 32800 } else { 32801 $btnEl.text("Lock").css({ 32802 "color": "#d00", 32803 "font-weight": "bold" 32804 }); 32805 } 32806 } 32807 32808 32809 // Add lock button to row 32810 function addLockButton($row, $parentColumn) { 32811 // AVOID DUPLICATES 32812 if ($row.data("lock-added")) return; 32813 32814 // VERIFY THIS IS A COLUMNS ROW 32815 var fullPath = $row.data("path"); 32816 if (!fullPath || !fullPath.includes("columns")) return; 32817 32818 // FIND THE MAIN CONTENT AREA TO IDENTIFY THE CORRECT EDITBAR 32819 var $ph = $row.find('[class*="cq-placeholder-main-content-area"]').first(); 32820 if (!$ph.length) return; 32821 32822 // EXTRACT THE TARGET CLASS FROM THE PLACEHOLDER 32823 var match = $ph.attr("class").match(/(main-content-area(?:_[^_]+)*_47columns(?:_\d+)?)_47column[^_]*$/); 32824 if (!match) return; 32825 32826 var targetClass = "cq-element-" + match[1]; 32827 var $editbar = $(".cq-editbar." + targetClass); 32828 if (!$editbar.length) return; 32829 32830 // FIND THE PASTE BUTTON TO INSERT AFTER 32831 var $pasteCell = $editbar.find("button:contains('Paste')").closest("td.x-toolbar-cell").last(); 32832 if (!$pasteCell.length) return; 32833 32834 // CREATE THE BUTTON 32835 var $btn = $('<td class="x-toolbar-cell">' + 32836 '<table cellspacing="0" class="x-btn x-btn-noicon" style="width:auto;">' + 32837 '<tbody class="x-btn-small x-btn-icon-small-left">' + 32838 '<tr><td class="x-btn-tl"><i></i></td><td class="x-btn-tc"></td><td class="x-btn-tr"><i></i></td></tr>' + 32839 '<tr>' + 32840 '<td class="x-btn-ml"><i></i></td>' + 32841 '<td class="x-btn-mc">' + 32842 '<em unselectable="on">' + 32843 '<button type="button" class="x-btn-text lock-toggle-btn" style="color:#d00;font-weight:bold;padding:0 12px;">' + 32844 'Loading...' + 32845 '</button>' + 32846 '</em>' + 32847 '</td>' + 32848 '<td class="x-btn-mr"><i></i></td>' + 32849 '</tr>' + 32850 '<tr><td class="x-btn-bl"><i></i></td><td class="x-btn-bc"></td><td class="x-btn-br"><i></i></td></tr>' + 32851 '</tbody>' + 32852 '</table>' + 32853 '</td>'); 32854 32855 // INSERT THE BUTTON 32856 $pasteCell.after($btn); 32857 $row.data("lock-added", true); 32858
32859 var isLocked = false; 32860 32861 // READ STATE FROM SERVLET 32862 $.get(SERVLET_URL, { path: fullPath }) 32863 .done(function (data) { 32864 isLocked = data.locked === true; 32865 $row.toggleClass("column-locked", isLocked); 32866 updateLockBtnUI($btn.find(".lock-toggle-btn"), isLocked); 32867 32868 // Apply to parent column control 32869 updateButtonStates(isLocked, $editbar); 32870 32871 if (isLocked) { 32872 applyEditBarRestrictions($row, true); 32873 // CHILD: apply same restrictions to all child editbars on load 32874 applyToChildren($editbar, true); 32875 } 32876 }) 32877 .fail(function () { 32878 $btn.find(".lock-toggle-btn").text("Error"); 32879 }); 32880 32881 // CLICK HANDLER 32882 $btn.find(".lock-toggle-btn").on("click", function () { 32883 var newLocked = !isLocked; 32884 var payload = { "_charset_": "utf-8" }; 32885 payload[newLocked ? "./" + LOCK_PROPERTY : "./" + LOCK_PROPERTY + "@Delete"] = "true"; 32886 32887 // SEND UPDATE TO SERVLET 32888 $.post(fullPath, payload) 32889 .done(function () { 32890 isLocked = newLocked; 32891 $row.toggleClass("column-locked", isLocked); 32892 updateLockBtnUI($btn.find(".lock-toggle-btn"), isLocked); 32893 32894 // Apply to parent column control 32895 updateButtonStates(isLocked, $editbar); 32896 applyEditBarRestrictions($row, isLocked); 32897 32898 // CHILD: apply the same jQuery + OOTB restrictions to every 32899 // child component editbar inside this column control 32900 applyToChildren($editbar, isLocked); 32901 }) 32902 .fail(function () { 32903 $btn.find(".lock-toggle-btn").text("Error"); 32904 }); 32905 }); 32906 } 32907 32908 // ------------------------------------------------------------------------- 32909 // APPLY RESTRICTIONS TO ALL CHILD EDITBARS 32910 // 32911 // When a Column Control is locked, child components must remain EDITABLE 32912 // but must NOT be movable. So unlike the parent, we deliberately do NOT 32913 // disable the child Edit/Delete buttons â we only restrict movement by 32914 // disabling the drag handle and suspending the drop targets. 32915 // ------------------------------------------------------------------------- 32916 32917 function applyToChildren($parentEditbar, locked) { 32918 var $children = findChildEditbars($parentEditbar); 32919 $children.each(function () { 32920 var $childEditbar = $(this); 32921 32922 // NOTE: Intentionally NOT calling updateButtonStates()/ 32923 // setEditBarButtonStates() here so that Edit (and Delete) stay 32924 // enabled on child components even while the column is locked. 32925 // Ensure any previously disabled buttons are re-enabled. 32926 updateButtonStates(false, $childEditbar); 32927 32928 // Get the live CQ.Ext component instance directly from the child 32929 // editbar's DOM id using CQ.Ext.getCmp(id). 32930 var childDomId = $childEditbar.attr("id"); 32931 if (!childDomId) return; 32932 32933 var childCmp = CQ.Ext.getCmp(childDomId); 32934 if (!childCmp) return; 32935 32936 // Keep the OOTB Edit/Delete buttons enabled on children. 32937 setEditBarButtonStates(childCmp, false); 32938 32939 // Restrict ONLY movement: disable drag handle and drop targets so 32940 // the child cannot be moved while the column control is locked. 32941 if (locked) { 32942 if (typeof childCmp.disableDrag === "function") { 32943 childCmp.disableDrag(); 32944 } 32945 if (typeof childCmp.suspendDropTargets === "function") { 32946 childCmp.suspendDropTargets(); 32947 } 32948 } else { 32949 if (typeof childCmp.enableDrag === "function") { 32950 childCmp.enableDrag(); 32951 } 32952 if (typeof childCmp.resumeDropTargets === "function") { 32953 childCmp.resumeDropTargets(); 32954 } 32955 } 32956 }); 32957 } 32958 32959 // Update lock states 32960 function updateLockStates() { 32961 var $rows = $(COMBINED_SELECTOR); 32962 $rows.each(function () { 32963 var $row = $(this); 32964 var $editbar = findEditbarForRow($row); 32965 if (!$editbar) return; 32966
32967 var isLocked = $row.hasClass("column-locked"); 32968 32969 // Parent column control 32970 updateButtonStates(isLocked, $editbar); 32971 applyEditBarRestrictions($row, isLocked); 32972 32973 // Children inside this column control 32974 applyToChildren($editbar, isLocked); 32975 }); 32976 } 32977 32978 // ------------------------------------------------------------------------- 32979 // SCAN - existing logic, enhanced with combined selector from registry 32980 // ------------------------------------------------------------------------- 32981 32982 // ------------------------------------------------------------------------- 32983 // SCAN WITH RETRY - keeps retrying until all rows have lock buttons 32984 // ------------------------------------------------------------------------- 32985 32986 var MAX_RETRY_TIME = 30000; // 30 seconds max 32987 var RETRY_INTERVAL = 2000; // retry every 2 seconds 32988 var _retryTimer = null; 32989 var _retryStart = null; 32990 32991 function scan() { 32992 var $rows = $(COMBINED_SELECTOR); 32993 var allAdded = true; 32994 32995 $rows.each(function () { 32996 var $row = $(this); 32997 if (!$row.data("lock-added")) { 32998 var $parentColumn = $row.closest(".columns"); 32999 addLockButton($row, $parentColumn); 33000 if (!$row.data("lock-added")) { 33001 allAdded = false; 33002 } 33003 } 33004 }); 33005 33006 // If some rows didn't get their button, retry 33007 if (!allAdded && $rows.length > 0) { 33008 if (!_retryStart) _retryStart = Date.now(); 33009 if (Date.now() - _retryStart < MAX_RETRY_TIME) { 33010 clearTimeout(_retryTimer); 33011 _retryTimer = setTimeout(scan, RETRY_INTERVAL); 33012 } 33013 } else { 33014 _retryStart = null; 33015 } 33016 } 33017 33018 // ------------------------------------------------------------------------- 33019 // MUTATION OBSERVER â scoped to editbar containers, debounced 33020 // ------------------------------------------------------------------------- 33021 33022 var _mutationDebounceTimer = null; 33023 33024 var observer = new MutationObserver(function (mutations) { 33025 var relevant = mutations.some(function (m) { 33026 return m.target && (m.target.className || "").indexOf("cq-editbar") !== -1; 33027 }); 33028 if (!relevant) return; 33029 33030 clearTimeout(_mutationDebounceTimer); 33031 _mutationDebounceTimer = setTimeout(function () { 33032 updateLockStates(); 33033 }, 250); 33034 }); 33035 observer.observe(document.body, { childList: true, subtree: true }); 33036 33037 // UPDATE LOCK STATES ON EDITBAR CLICK (scoped to editbars only) 33038 $(document).on("click", ".cq-editbar", function () { 33039 updateLockStates(); 33040 }); 33041 33042 // INITIALIZE (existing) 33043 $(document).ready(scan); 33044 33045 // RE-SCAN ON EDITOR EVENTS (existing) 33046 $(document).on("cq-editables-loaded cq-layer-activated foundation-contentloaded", function () { 33047 setTimeout(scan, 500); 33048 }); 33049 33050 // ADDITIONAL SCAN AS FALLBACK 33051 setTimeout(scan, 2000); 33052 33053})(jQuery); 33054 33055 33056(function ($) { 33057 // ---- helpers: read dataset keys in both formats and normalize tag strings ---- 33058 function val(el, k1, k2) { 33059 // read dataset in either camelCase or kebab-case data-* 33060 return el.dataset[k1] || el.dataset[k2] || ""; 33061 } 33062 function normalizeTags(raw) { 33063 // Turn "[regions:fl, regions:fl/tampa]" OR "regions:fl,regions:fl/tampa" -> "regions:fl,regions:fl/tampa" 33064 if (!raw) return ""; 33065 return String(raw).replace(/[\[\]\s]/g, "").trim(); 33066 } 33067 33068 // ---- core: resolve latest article link for a single image component ---- 33069 function resolveLatestForImage(container) { 33070 try { 33071 var $container = $(container); 33072 var $anchor = $container.find('a.dynamic-article-url').first(); 33073 if (!$anchor.length) return; 33074 33075 var $src = $container.find('.js-latest-article-source').first(); 33076 if (!$src.length) return; 33077 33078 // read tags and params from data-*; accept both existing and new names 33079 var required = normalizeTags(val($src[0], 'requiredtags', 'reqTags')); 33080 var optional = normalizeTags(val($src[0], 'optionaltags', 'optTags')); 33081 var excluded = normalizeTags(val($src[0], 'excludedtags', 'exTags')); 33082 var rootPath = val($src[0], 'rootPath', 'rootPath') || "/content/news/stories"; 33083 var daysLimit = val($src[0], 'dayslimit', 'dayslimit') || ""; 33084 var tz = val($src[0], 'dayslimittimezone', 'dayslimittimezone') || ""; 33085 33086 // Build URI exactly like dynamic list service does 33087 var uri = '/services/ms/articles' 33088 + '?reqTags=' + encodeURIComponent(required) 33089 + '&optTags=' + encodeURIComponent(optional) 33090 + '&exTags=' + encodeURIComponent(excluded) 33091 + '&path=' + encodeURIComponent(rootPath) 33092 + (daysLimit ? '&daysLimit=' + encodeURIComponent(daysLimit) : '') 33093 + (tz ? '&daysLimitTimezone=' + encodeURIComponent(tz) : ''); 33094 33095 var startTime = Date.now();
33096 $.ajax({ url: uri, dataType: 'json' }) 33097 .done(function (data, textStatus, jqXHR) { 33098 News.ContentList.ajaxLoadFinished(container, data); 33099 try { 33100 var articles = (data && data.articles) ? data.articles : []; 33101 // filter out current page same as content list 33102 if (News && News.ContentList && typeof News.ContentList.currentArticleExcludeFilter === 'function') { 33103 articles = $(articles).filter(News.ContentList.currentArticleExcludeFilter); 33104 } 33105 33106 if (articles.length > 0) { 33107 var first = articles[0]; 33108 var url = first.url; 33109 if(News.ContentList.authorMode) {url = url + ".html";} 33110 $anchor.attr('href', url).attr('data-dynamic-href', 'true'); 33111 } 33112 33113 // optional analytics hook if present 33114 if (News && News.App && News.App.QuantumAnalytics && typeof News.App.QuantumAnalytics.quantumApiSuccessOrFailure === 'function') { 33115 News.App.QuantumAnalytics.quantumApiSuccessOrFailure(uri, jqXHR.status, "All_Generic_API_Call_Success", startTime, "GET", "", "", jqXHR); 33116 } 33117 } catch (e) { 33118 // swallow to avoid author breakage 33119 } 33120 }) 33121 .fail(function (jqXHR) { 33122 // optional analytics 33123 if (News && News.App && News.App.QuantumAnalytics && typeof News.App.QuantumAnalytics.quantumApiSuccessOrFailure === 'function') { 33124 var msg = (News.App.QuantumAnalytics.extractAjaxErrorMessage) ? News.App.QuantumAnalytics.extractAjaxErrorMessage(jqXHR) : ''; 33125 News.App.QuantumAnalytics.quantumApiSuccessOrFailure(uri, jqXHR.status, "All_Generic_API_Call_Failure", startTime, "GET", "", msg, jqXHR); 33126 } 33127 }); 33128 } catch (ex) { 33129 // no-op 33130 } 33131 } 33132 33133 // ---- init ---- 33134 33135 $(function () { 33136 $('.image').each(function () { 33137 var hasDynamic = $(this).find('a.dynamic-article-url').length > 0; 33138 if (hasDynamic) resolveLatestForImage(this); 33139 }); 33140 }); 33141 33142})(jQuery); 33143
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.