diff --git a/static/js/slate.js b/static/js/slate.js index a48cc6a..1a1ee16 100644 --- a/static/js/slate.js +++ b/static/js/slate.js @@ -1,3502 +1,2 @@ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global.shuffle = factory()); -}(this, (function () { 'use strict'; - -// Polyfill for creating CustomEvents on IE9/10/11 - -// code pulled from: -// https://github.com/d4tocchini/customevent-polyfill -// https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent#Polyfill - -try { - var ce = new window.CustomEvent('test'); - ce.preventDefault(); - if (ce.defaultPrevented !== true) { - // IE has problems with .preventDefault() on custom events - // http://stackoverflow.com/questions/23349191 - throw new Error('Could not prevent default'); - } -} catch(e) { - var CustomEvent$1 = function(event, params) { - var evt, origPrevent; - params = params || { - bubbles: false, - cancelable: false, - detail: undefined - }; - - evt = document.createEvent("CustomEvent"); - evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail); - origPrevent = evt.preventDefault; - evt.preventDefault = function () { - origPrevent.call(this); - try { - Object.defineProperty(this, 'defaultPrevented', { - get: function () { - return true; - } - }); - } catch(e) { - this.defaultPrevented = true; - } - }; - return evt; - }; - - CustomEvent$1.prototype = window.Event.prototype; - window.CustomEvent = CustomEvent$1; // expose definition to window -} - -var proto = Element.prototype; -var vendor = proto.matches - || proto.matchesSelector - || proto.webkitMatchesSelector - || proto.mozMatchesSelector - || proto.msMatchesSelector - || proto.oMatchesSelector; - -var index = match; - -/** - * Match `el` to `selector`. - * - * @param {Element} el - * @param {String} selector - * @return {Boolean} - * @api public - */ - -function match(el, selector) { - if (vendor) return vendor.call(el, selector); - var nodes = el.parentNode.querySelectorAll(selector); - for (var i = 0; i < nodes.length; i++) { - if (nodes[i] == el) return true; - } - return false; -} - -var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; - - - - - -function createCommonjsModule(fn, module) { - return module = { exports: {} }, fn(module, module.exports), module.exports; -} - -var index$1 = createCommonjsModule(function (module) { -'use strict'; - -// there's 3 implementations written in increasing order of efficiency - -// 1 - no Set type is defined -function uniqNoSet(arr) { - var ret = []; - - for (var i = 0; i < arr.length; i++) { - if (ret.indexOf(arr[i]) === -1) { - ret.push(arr[i]); - } - } - - return ret; -} - -// 2 - a simple Set type is defined -function uniqSet(arr) { - var seen = new Set(); - return arr.filter(function (el) { - if (!seen.has(el)) { - seen.add(el); - return true; - } - - return false; - }); -} - -// 3 - a standard Set type is defined and it has a forEach method -function uniqSetWithForEach(arr) { - var ret = []; - - (new Set(arr)).forEach(function (el) { - ret.push(el); - }); - - return ret; -} - -// V8 currently has a broken implementation -// https://github.com/joyent/node/issues/8449 -function doesForEachActuallyWork() { - var ret = false; - - (new Set([true])).forEach(function (el) { - ret = el; - }); - - return ret === true; -} - -if ('Set' in commonjsGlobal) { - if (typeof Set.prototype.forEach === 'function' && doesForEachActuallyWork()) { - module.exports = uniqSetWithForEach; - } else { - module.exports = uniqSet; - } -} else { - module.exports = uniqNoSet; -} -}); - -var immutable = extend; - -var hasOwnProperty = Object.prototype.hasOwnProperty; - -function extend() { - var target = {}; - - for (var i = 0; i < arguments.length; i++) { - var source = arguments[i]; - - for (var key in source) { - if (hasOwnProperty.call(source, key)) { - target[key] = source[key]; - } - } - } - - return target -} - -var index$2 = throttle; - -/** - * Returns a new function that, when invoked, invokes `func` at most once per `wait` milliseconds. - * - * @param {Function} func Function to wrap. - * @param {Number} wait Number of milliseconds that must elapse between `func` invocations. - * @return {Function} A new function that wraps the `func` function passed in. - */ - -function throttle (func, wait) { - var ctx, args, rtn, timeoutID; // caching - var last = 0; - - return function throttled () { - ctx = this; - args = arguments; - var delta = new Date() - last; - if (!timeoutID) - if (delta >= wait) call(); - else timeoutID = setTimeout(call, wait - delta); - return rtn; - }; - - function call () { - timeoutID = 0; - last = +new Date(); - rtn = func.apply(ctx, args); - ctx = null; - args = null; - } -} - -var index$3 = function parallel(fns, context, callback) { - if (!callback) { - if (typeof context === 'function') { - callback = context; - context = null; - } else { - callback = noop; - } - } - - var pending = fns && fns.length; - if (!pending) return callback(null, []); - - var finished = false; - var results = new Array(pending); - - fns.forEach(context ? function (fn, i) { - fn.call(context, maybeDone(i)); - } : function (fn, i) { - fn(maybeDone(i)); - }); - - function maybeDone(i) { - return function (err, result) { - if (finished) return; - - if (err) { - callback(err, results); - finished = true; - return - } - - results[i] = result; - - if (!--pending) callback(null, results); - } - } -}; - -function noop() {} - -/** - * Always returns a numeric value, given a value. Logic from jQuery's `isNumeric`. - * @param {*} value Possibly numeric value. - * @return {number} `value` or zero if `value` isn't numeric. - */ -function getNumber(value) { - return parseFloat(value) || 0; -} - -var classCallCheck = function (instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } -}; - -var createClass = function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - - return function (Constructor, protoProps, staticProps) { - if (protoProps) defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; -}(); - -var Point = function () { - - /** - * Represents a coordinate pair. - * @param {number} [x=0] X. - * @param {number} [y=0] Y. - */ - function Point(x, y) { - classCallCheck(this, Point); - - this.x = getNumber(x); - this.y = getNumber(y); - } - - /** - * Whether two points are equal. - * @param {Point} a Point A. - * @param {Point} b Point B. - * @return {boolean} - */ - - - createClass(Point, null, [{ - key: 'equals', - value: function equals(a, b) { - return a.x === b.x && a.y === b.y; - } - }]); - return Point; -}(); - -var Classes = { - BASE: 'shuffle', - SHUFFLE_ITEM: 'shuffle-item', - VISIBLE: 'shuffle-item--visible', - HIDDEN: 'shuffle-item--hidden' -}; - -var id$1 = 0; - -var ShuffleItem = function () { - function ShuffleItem(element) { - classCallCheck(this, ShuffleItem); - - id$1 += 1; - this.id = id$1; - this.element = element; - this.isVisible = true; - } - - createClass(ShuffleItem, [{ - key: 'show', - value: function show() { - this.isVisible = true; - this.element.classList.remove(Classes.HIDDEN); - this.element.classList.add(Classes.VISIBLE); - } - }, { - key: 'hide', - value: function hide() { - this.isVisible = false; - this.element.classList.remove(Classes.VISIBLE); - this.element.classList.add(Classes.HIDDEN); - } - }, { - key: 'init', - value: function init() { - this.addClasses([Classes.SHUFFLE_ITEM, Classes.VISIBLE]); - this.applyCss(ShuffleItem.Css.INITIAL); - this.scale = ShuffleItem.Scale.VISIBLE; - this.point = new Point(); - } - }, { - key: 'addClasses', - value: function addClasses(classes) { - var _this = this; - - classes.forEach(function (className) { - _this.element.classList.add(className); - }); - } - }, { - key: 'removeClasses', - value: function removeClasses(classes) { - var _this2 = this; - - classes.forEach(function (className) { - _this2.element.classList.remove(className); - }); - } - }, { - key: 'applyCss', - value: function applyCss(obj) { - var _this3 = this; - - Object.keys(obj).forEach(function (key) { - _this3.element.style[key] = obj[key]; - }); - } - }, { - key: 'dispose', - value: function dispose() { - this.removeClasses([Classes.HIDDEN, Classes.VISIBLE, Classes.SHUFFLE_ITEM]); - - this.element.removeAttribute('style'); - this.element = null; - } - }]); - return ShuffleItem; -}(); - -ShuffleItem.Css = { - INITIAL: { - position: 'absolute', - top: 0, - left: 0, - visibility: 'visible', - 'will-change': 'transform' - }, - VISIBLE: { - before: { - opacity: 1, - visibility: 'visible' - }, - after: {} - }, - HIDDEN: { - before: { - opacity: 0 - }, - after: { - visibility: 'hidden' - } - } -}; - -ShuffleItem.Scale = { - VISIBLE: 1, - HIDDEN: 0.001 -}; - -var element = document.body || document.documentElement; -var e$1 = document.createElement('div'); -e$1.style.cssText = 'width:10px;padding:2px;box-sizing:border-box;'; -element.appendChild(e$1); - -var width = window.getComputedStyle(e$1, null).width; -var ret = width === '10px'; - -element.removeChild(e$1); - -/** - * Retrieve the computed style for an element, parsed as a float. - * @param {Element} element Element to get style for. - * @param {string} style Style property. - * @param {CSSStyleDeclaration} [styles] Optionally include clean styles to - * use instead of asking for them again. - * @return {number} The parsed computed value or zero if that fails because IE - * will return 'auto' when the element doesn't have margins instead of - * the computed style. - */ -function getNumberStyle(element, style) { - var styles = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : window.getComputedStyle(element, null); - - var value = getNumber(styles[style]); - - // Support IE<=11 and W3C spec. - if (!ret && style === 'width') { - value += getNumber(styles.paddingLeft) + getNumber(styles.paddingRight) + getNumber(styles.borderLeftWidth) + getNumber(styles.borderRightWidth); - } else if (!ret && style === 'height') { - value += getNumber(styles.paddingTop) + getNumber(styles.paddingBottom) + getNumber(styles.borderTopWidth) + getNumber(styles.borderBottomWidth); - } - - return value; -} - -/** - * Fisher-Yates shuffle. - * http://stackoverflow.com/a/962890/373422 - * https://bost.ocks.org/mike/shuffle/ - * @param {Array} array Array to shuffle. - * @return {Array} Randomly sorted array. - */ -function randomize(array) { - var n = array.length; - - while (n) { - n -= 1; - var i = Math.floor(Math.random() * (n + 1)); - var temp = array[i]; - array[i] = array[n]; - array[n] = temp; - } - - return array; -} - -var defaults$1 = { - // Use array.reverse() to reverse the results - reverse: false, - - // Sorting function - by: null, - - // If true, this will skip the sorting and return a randomized order in the array - randomize: false, - - // Determines which property of each item in the array is passed to the - // sorting method. - key: 'element' -}; - -// You can return `undefined` from the `by` function to revert to DOM order. -function sorter(arr, options) { - var opts = immutable(defaults$1, options); - var original = [].slice.call(arr); - var revert = false; - - if (!arr.length) { - return []; - } - - if (opts.randomize) { - return randomize(arr); - } - - // Sort the elements by the opts.by function. - // If we don't have opts.by, default to DOM order - if (typeof opts.by === 'function') { - arr.sort(function (a, b) { - // Exit early if we already know we want to revert - if (revert) { - return 0; - } - - var valA = opts.by(a[opts.key]); - var valB = opts.by(b[opts.key]); - - // If both values are undefined, use the DOM order - if (valA === undefined && valB === undefined) { - revert = true; - return 0; - } - - if (valA < valB || valA === 'sortFirst' || valB === 'sortLast') { - return -1; - } - - if (valA > valB || valA === 'sortLast' || valB === 'sortFirst') { - return 1; - } - - return 0; - }); - } - - // Revert to the original array if necessary - if (revert) { - return original; - } - - if (opts.reverse) { - arr.reverse(); - } - - return arr; -} - -var transitions = {}; -var eventName = 'transitionend'; -var count = 0; - -function uniqueId() { - count += 1; - return eventName + count; -} - -function cancelTransitionEnd(id) { - if (transitions[id]) { - transitions[id].element.removeEventListener(eventName, transitions[id].listener); - transitions[id] = null; - return true; - } - - return false; -} - -function onTransitionEnd(element, callback) { - var id = uniqueId(); - var listener = function listener(evt) { - if (evt.currentTarget === evt.target) { - cancelTransitionEnd(id); - callback(evt); - } - }; - - element.addEventListener(eventName, listener); - - transitions[id] = { element: element, listener: listener }; - - return id; -} - -function arrayMax(array) { - return Math.max.apply(Math, array); // eslint-disable-line prefer-spread -} - -function arrayMin(array) { - return Math.min.apply(Math, array); // eslint-disable-line prefer-spread -} - -/** - * Determine the number of columns an items spans. - * @param {number} itemWidth Width of the item. - * @param {number} columnWidth Width of the column (includes gutter). - * @param {number} columns Total number of columns - * @param {number} threshold A buffer value for the size of the column to fit. - * @return {number} - */ -function getColumnSpan(itemWidth, columnWidth, columns, threshold) { - var columnSpan = itemWidth / columnWidth; - - // If the difference between the rounded column span number and the - // calculated column span number is really small, round the number to - // make it fit. - if (Math.abs(Math.round(columnSpan) - columnSpan) < threshold) { - // e.g. columnSpan = 4.0089945390298745 - columnSpan = Math.round(columnSpan); - } - - // Ensure the column span is not more than the amount of columns in the whole layout. - return Math.min(Math.ceil(columnSpan), columns); -} - -/** - * Retrieves the column set to use for placement. - * @param {number} columnSpan The number of columns this current item spans. - * @param {number} columns The total columns in the grid. - * @return {Array.} An array of numbers represeting the column set. - */ -function getAvailablePositions(positions, columnSpan, columns) { - // The item spans only one column. - if (columnSpan === 1) { - return positions; - } - - // The item spans more than one column, figure out how many different - // places it could fit horizontally. - // The group count is the number of places within the positions this block - // could fit, ignoring the current positions of items. - // Imagine a 2 column brick as the second item in a 4 column grid with - // 10px height each. Find the places it would fit: - // [20, 10, 10, 0] - // | | | - // * * * - // - // Then take the places which fit and get the bigger of the two: - // max([20, 10]), max([10, 10]), max([10, 0]) = [20, 10, 0] - // - // Next, find the first smallest number (the short column). - // [20, 10, 0] - // | - // * - // - // And that's where it should be placed! - // - // Another example where the second column's item extends past the first: - // [10, 20, 10, 0] => [20, 20, 10] => 10 - var available = []; - - // For how many possible positions for this item there are. - for (var i = 0; i <= columns - columnSpan; i++) { - // Find the bigger value for each place it could fit. - available.push(arrayMax(positions.slice(i, i + columnSpan))); - } - - return available; -} - -/** - * Find index of short column, the first from the left where this item will go. - * - * @param {Array.} positions The array to search for the smallest number. - * @param {number} buffer Optional buffer which is very useful when the height - * is a percentage of the width. - * @return {number} Index of the short column. - */ -function getShortColumn(positions, buffer) { - var minPosition = arrayMin(positions); - for (var i = 0, len = positions.length; i < len; i++) { - if (positions[i] >= minPosition - buffer && positions[i] <= minPosition + buffer) { - return i; - } - } - - return 0; -} - -/** - * Determine the location of the next item, based on its size. - * @param {Object} itemSize Object with width and height. - * @param {Array.} positions Positions of the other current items. - * @param {number} gridSize The column width or row height. - * @param {number} total The total number of columns or rows. - * @param {number} threshold Buffer value for the column to fit. - * @param {number} buffer Vertical buffer for the height of items. - * @return {Point} - */ -function getItemPosition(_ref) { - var itemSize = _ref.itemSize, - positions = _ref.positions, - gridSize = _ref.gridSize, - total = _ref.total, - threshold = _ref.threshold, - buffer = _ref.buffer; - - var span = getColumnSpan(itemSize.width, gridSize, total, threshold); - var setY = getAvailablePositions(positions, span, total); - var shortColumnIndex = getShortColumn(setY, buffer); - - // Position the item - var point = new Point(Math.round(gridSize * shortColumnIndex), Math.round(setY[shortColumnIndex])); - - // Update the columns array with the new values for each column. - // e.g. before the update the columns could be [250, 0, 0, 0] for an item - // which spans 2 columns. After it would be [250, itemHeight, itemHeight, 0]. - var setHeight = setY[shortColumnIndex] + itemSize.height; - for (var i = 0; i < span; i++) { - positions[shortColumnIndex + i] = setHeight; - } - - return point; -} - -function toArray$$1(arrayLike) { - return Array.prototype.slice.call(arrayLike); -} - -function arrayIncludes(array, obj) { - return array.indexOf(obj) > -1; -} - -// Used for unique instance variables -var id = 0; - -var Shuffle = function () { - - /** - * Categorize, sort, and filter a responsive grid of items. - * - * @param {Element} element An element which is the parent container for the grid items. - * @param {Object} [options=Shuffle.options] Options object. - * @constructor - */ - function Shuffle(element) { - var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - classCallCheck(this, Shuffle); - - this.options = immutable(Shuffle.options, options); - - this.useSizer = false; - this.lastSort = {}; - this.group = Shuffle.ALL_ITEMS; - this.lastFilter = Shuffle.ALL_ITEMS; - this.isEnabled = true; - this.isDestroyed = false; - this.isInitialized = false; - this._transitions = []; - this.isTransitioning = false; - this._queue = []; - - var el = this._getElementOption(element); - - if (!el) { - throw new TypeError('Shuffle needs to be initialized with an element.'); - } - - this.element = el; - this.id = 'shuffle_' + id; - id += 1; - - this._init(); - this.isInitialized = true; - } - - createClass(Shuffle, [{ - key: '_init', - value: function _init() { - this.items = this._getItems(); - - this.options.sizer = this._getElementOption(this.options.sizer); - - if (this.options.sizer) { - this.useSizer = true; - } - - // Add class and invalidate styles - this.element.classList.add(Shuffle.Classes.BASE); - - // Set initial css for each item - this._initItems(); - - // Bind resize events - this._onResize = this._getResizeFunction(); - window.addEventListener('resize', this._onResize); - - // Get container css all in one request. Causes reflow - var containerCss = window.getComputedStyle(this.element, null); - var containerWidth = Shuffle.getSize(this.element).width; - - // Add styles to the container if it doesn't have them. - this._validateStyles(containerCss); - - // We already got the container's width above, no need to cause another - // reflow getting it again... Calculate the number of columns there will be - this._setColumns(containerWidth); - - // Kick off! - this.filter(this.options.group, this.options.initialSort); - - // The shuffle items haven't had transitions set on them yet so the user - // doesn't see the first layout. Set them now that the first layout is done. - // First, however, a synchronous layout must be caused for the previous - // styles to be applied without transitions. - this.element.offsetWidth; // eslint-disable-line no-unused-expressions - this._setTransitions(); - this.element.style.transition = 'height ' + this.options.speed + 'ms ' + this.options.easing; - } - - /** - * Returns a throttled and proxied function for the resize handler. - * @return {Function} - * @private - */ - - }, { - key: '_getResizeFunction', - value: function _getResizeFunction() { - var resizeFunction = this._handleResize.bind(this); - return this.options.throttle ? this.options.throttle(resizeFunction, this.options.throttleTime) : resizeFunction; - } - - /** - * Retrieve an element from an option. - * @param {string|jQuery|Element} option The option to check. - * @return {?Element} The plain element or null. - * @private - */ - - }, { - key: '_getElementOption', - value: function _getElementOption(option) { - // If column width is a string, treat is as a selector and search for the - // sizer element within the outermost container - if (typeof option === 'string') { - return this.element.querySelector(option); - - // Check for an element - } else if (option && option.nodeType && option.nodeType === 1) { - return option; - - // Check for jQuery object - } else if (option && option.jquery) { - return option[0]; - } - - return null; - } - - /** - * Ensures the shuffle container has the css styles it needs applied to it. - * @param {Object} styles Key value pairs for position and overflow. - * @private - */ - - }, { - key: '_validateStyles', - value: function _validateStyles(styles) { - // Position cannot be static. - if (styles.position === 'static') { - this.element.style.position = 'relative'; - } - - // Overflow has to be hidden. - if (styles.overflow !== 'hidden') { - this.element.style.overflow = 'hidden'; - } - } - - /** - * Filter the elements by a category. - * @param {string} [category] Category to filter by. If it's given, the last - * category will be used to filter the items. - * @param {Array} [collection] Optionally filter a collection. Defaults to - * all the items. - * @return {!{visible: Array, hidden: Array}} - * @private - */ - - }, { - key: '_filter', - value: function _filter() { - var category = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.lastFilter; - var collection = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.items; - - var set$$1 = this._getFilteredSets(category, collection); - - // Individually add/remove hidden/visible classes - this._toggleFilterClasses(set$$1); - - // Save the last filter in case elements are appended. - this.lastFilter = category; - - // This is saved mainly because providing a filter function (like searching) - // will overwrite the `lastFilter` property every time its called. - if (typeof category === 'string') { - this.group = category; - } - - return set$$1; - } - - /** - * Returns an object containing the visible and hidden elements. - * @param {string|Function} category Category or function to filter by. - * @param {Array.} items A collection of items to filter. - * @return {!{visible: Array, hidden: Array}} - * @private - */ - - }, { - key: '_getFilteredSets', - value: function _getFilteredSets(category, items) { - var _this = this; - - var visible = []; - var hidden = []; - - // category === 'all', add visible class to everything - if (category === Shuffle.ALL_ITEMS) { - visible = items; - - // Loop through each item and use provided function to determine - // whether to hide it or not. - } else { - items.forEach(function (item) { - if (_this._doesPassFilter(category, item.element)) { - visible.push(item); - } else { - hidden.push(item); - } - }); - } - - return { - visible: visible, - hidden: hidden - }; - } - - /** - * Test an item to see if it passes a category. - * @param {string|Function} category Category or function to filter by. - * @param {Element} element An element to test. - * @return {boolean} Whether it passes the category/filter. - * @private - */ - - }, { - key: '_doesPassFilter', - value: function _doesPassFilter(category, element) { - if (typeof category === 'function') { - return category.call(element, element, this); - } - - // Check each element's data-groups attribute against the given category. - var attr = element.getAttribute('data-' + Shuffle.FILTER_ATTRIBUTE_KEY); - var keys = this.options.delimeter ? attr.split(this.options.delimeter) : JSON.parse(attr); - - function testCategory(category) { - return arrayIncludes(keys, category); - } - - if (Array.isArray(category)) { - if (this.options.filterMode === Shuffle.FilterMode.ANY) { - return category.some(testCategory); - } - return category.every(testCategory); - } - - return arrayIncludes(keys, category); - } - - /** - * Toggles the visible and hidden class names. - * @param {{visible, hidden}} Object with visible and hidden arrays. - * @private - */ - - }, { - key: '_toggleFilterClasses', - value: function _toggleFilterClasses(_ref) { - var visible = _ref.visible, - hidden = _ref.hidden; - - visible.forEach(function (item) { - item.show(); - }); - - hidden.forEach(function (item) { - item.hide(); - }); - } - - /** - * Set the initial css for each item - * @param {Array.} [items] Optionally specifiy at set to initialize. - * @private - */ - - }, { - key: '_initItems', - value: function _initItems() { - var items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.items; - - items.forEach(function (item) { - item.init(); - }); - } - - /** - * Remove element reference and styles. - * @private - */ - - }, { - key: '_disposeItems', - value: function _disposeItems() { - var items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.items; - - items.forEach(function (item) { - item.dispose(); - }); - } - - /** - * Updates the visible item count. - * @private - */ - - }, { - key: '_updateItemCount', - value: function _updateItemCount() { - this.visibleItems = this._getFilteredItems().length; - } - - /** - * Sets css transform transition on a group of elements. This is not executed - * at the same time as `item.init` so that transitions don't occur upon - * initialization of Shuffle. - * @param {Array.} items Shuffle items to set transitions on. - * @private - */ - - }, { - key: '_setTransitions', - value: function _setTransitions() { - var items = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.items; - - var speed = this.options.speed; - var easing = this.options.easing; - - var str = this.options.useTransforms ? 'transform ' + speed + 'ms ' + easing + ', opacity ' + speed + 'ms ' + easing : 'top ' + speed + 'ms ' + easing + ', left ' + speed + 'ms ' + easing + ', opacity ' + speed + 'ms ' + easing; - - items.forEach(function (item) { - item.element.style.transition = str; - }); - } - }, { - key: '_getItems', - value: function _getItems() { - var _this2 = this; - - return toArray$$1(this.element.children).filter(function (el) { - return index(el, _this2.options.itemSelector); - }).map(function (el) { - return new ShuffleItem(el); - }); - } - - /** - * When new elements are added to the shuffle container, update the array of - * items because that is the order `_layout` calls them. - */ - - }, { - key: '_updateItemsOrder', - value: function _updateItemsOrder() { - var children = this.element.children; - this.items = sorter(this.items, { - by: function by(element) { - return Array.prototype.indexOf.call(children, element); - } - }); - } - }, { - key: '_getFilteredItems', - value: function _getFilteredItems() { - return this.items.filter(function (item) { - return item.isVisible; - }); - } - }, { - key: '_getConcealedItems', - value: function _getConcealedItems() { - return this.items.filter(function (item) { - return !item.isVisible; - }); - } - - /** - * Returns the column size, based on column width and sizer options. - * @param {number} containerWidth Size of the parent container. - * @param {number} gutterSize Size of the gutters. - * @return {number} - * @private - */ - - }, { - key: '_getColumnSize', - value: function _getColumnSize(containerWidth, gutterSize) { - var size = void 0; - - // If the columnWidth property is a function, then the grid is fluid - if (typeof this.options.columnWidth === 'function') { - size = this.options.columnWidth(containerWidth); - - // columnWidth option isn't a function, are they using a sizing element? - } else if (this.useSizer) { - size = Shuffle.getSize(this.options.sizer).width; - - // if not, how about the explicitly set option? - } else if (this.options.columnWidth) { - size = this.options.columnWidth; - - // or use the size of the first item - } else if (this.items.length > 0) { - size = Shuffle.getSize(this.items[0].element, true).width; - - // if there's no items, use size of container - } else { - size = containerWidth; - } - - // Don't let them set a column width of zero. - if (size === 0) { - size = containerWidth; - } - - return size + gutterSize; - } - - /** - * Returns the gutter size, based on gutter width and sizer options. - * @param {number} containerWidth Size of the parent container. - * @return {number} - * @private - */ - - }, { - key: '_getGutterSize', - value: function _getGutterSize(containerWidth) { - var size = void 0; - if (typeof this.options.gutterWidth === 'function') { - size = this.options.gutterWidth(containerWidth); - } else if (this.useSizer) { - size = getNumberStyle(this.options.sizer, 'marginLeft'); - } else { - size = this.options.gutterWidth; - } - - return size; - } - - /** - * Calculate the number of columns to be used. Gets css if using sizer element. - * @param {number} [containerWidth] Optionally specify a container width if - * it's already available. - */ - - }, { - key: '_setColumns', - value: function _setColumns() { - var containerWidth = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : Shuffle.getSize(this.element).width; - - var gutter = this._getGutterSize(containerWidth); - var columnWidth = this._getColumnSize(containerWidth, gutter); - var calculatedColumns = (containerWidth + gutter) / columnWidth; - - // Widths given from getStyles are not precise enough... - if (Math.abs(Math.round(calculatedColumns) - calculatedColumns) < this.options.columnThreshold) { - // e.g. calculatedColumns = 11.998876 - calculatedColumns = Math.round(calculatedColumns); - } - - this.cols = Math.max(Math.floor(calculatedColumns), 1); - this.containerWidth = containerWidth; - this.colWidth = columnWidth; - } - - /** - * Adjust the height of the grid - */ - - }, { - key: '_setContainerSize', - value: function _setContainerSize() { - this.element.style.height = this._getContainerSize() + 'px'; - } - - /** - * Based on the column heights, it returns the biggest one. - * @return {number} - * @private - */ - - }, { - key: '_getContainerSize', - value: function _getContainerSize() { - return arrayMax(this.positions); - } - - /** - * Get the clamped stagger amount. - * @param {number} index Index of the item to be staggered. - * @return {number} - */ - - }, { - key: '_getStaggerAmount', - value: function _getStaggerAmount(index$$1) { - return Math.min(index$$1 * this.options.staggerAmount, this.options.staggerAmountMax); - } - - /** - * @return {boolean} Whether the event was prevented or not. - */ - - }, { - key: '_dispatch', - value: function _dispatch(name) { - var details = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - if (this.isDestroyed) { - return false; - } - - details.shuffle = this; - return !this.element.dispatchEvent(new CustomEvent(name, { - bubbles: true, - cancelable: false, - detail: details - })); - } - - /** - * Zeros out the y columns array, which is used to determine item placement. - * @private - */ - - }, { - key: '_resetCols', - value: function _resetCols() { - var i = this.cols; - this.positions = []; - while (i) { - i -= 1; - this.positions.push(0); - } - } - - /** - * Loops through each item that should be shown and calculates the x, y position. - * @param {Array.} items Array of items that will be shown/layed - * out in order in their array. - */ - - }, { - key: '_layout', - value: function _layout(items) { - var _this3 = this; - - var count = 0; - items.forEach(function (item) { - var currPos = item.point; - var currScale = item.scale; - var itemSize = Shuffle.getSize(item.element, true); - var pos = _this3._getItemPosition(itemSize); - - function callback() { - item.element.style.transitionDelay = ''; - item.applyCss(ShuffleItem.Css.VISIBLE.after); - } - - // If the item will not change its position, do not add it to the render - // queue. Transitions don't fire when setting a property to the same value. - if (Point.equals(currPos, pos) && currScale === ShuffleItem.Scale.VISIBLE) { - item.applyCss(ShuffleItem.Css.VISIBLE.before); - callback(); - return; - } - - item.point = pos; - item.scale = ShuffleItem.Scale.VISIBLE; - - // Use xtend here to clone the object so that the `before` object isn't - // modified when the transition delay is added. - var styles = immutable(ShuffleItem.Css.VISIBLE.before); - styles.transitionDelay = _this3._getStaggerAmount(count) + 'ms'; - - _this3._queue.push({ - item: item, - styles: styles, - callback: callback - }); - - count += 1; - }); - } - - /** - * Determine the location of the next item, based on its size. - * @param {{width: number, height: number}} itemSize Object with width and height. - * @return {Point} - * @private - */ - - }, { - key: '_getItemPosition', - value: function _getItemPosition(itemSize) { - return getItemPosition({ - itemSize: itemSize, - positions: this.positions, - gridSize: this.colWidth, - total: this.cols, - threshold: this.options.columnThreshold, - buffer: this.options.buffer - }); - } - - /** - * Hides the elements that don't match our filter. - * @param {Array.} collection Collection to shrink. - * @private - */ - - }, { - key: '_shrink', - value: function _shrink() { - var _this4 = this; - - var collection = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this._getConcealedItems(); - - var count = 0; - collection.forEach(function (item) { - function callback() { - item.applyCss(ShuffleItem.Css.HIDDEN.after); - } - - // Continuing would add a transitionend event listener to the element, but - // that listener would not execute because the transform and opacity would - // stay the same. - // The callback is executed here because it is not guaranteed to be called - // after the transitionend event because the transitionend could be - // canceled if another animation starts. - if (item.scale === ShuffleItem.Scale.HIDDEN) { - item.applyCss(ShuffleItem.Css.HIDDEN.before); - callback(); - return; - } - - item.scale = ShuffleItem.Scale.HIDDEN; - - var styles = immutable(ShuffleItem.Css.HIDDEN.before); - styles.transitionDelay = _this4._getStaggerAmount(count) + 'ms'; - - _this4._queue.push({ - item: item, - styles: styles, - callback: callback - }); - - count += 1; - }); - } - - /** - * Resize handler. - * @private - */ - - }, { - key: '_handleResize', - value: function _handleResize() { - // If shuffle is disabled, destroyed, don't do anything - if (!this.isEnabled || this.isDestroyed) { - return; - } - - // Will need to check height in the future if it's layed out horizontaly - var containerWidth = Shuffle.getSize(this.element).width; - - // containerWidth hasn't changed, don't do anything - if (containerWidth === this.containerWidth) { - return; - } - - this.update(); - } - - /** - * Returns styles which will be applied to the an item for a transition. - * @param {Object} obj Transition options. - * @return {!Object} Transforms for transitions, left/top for animate. - * @private - */ - - }, { - key: '_getStylesForTransition', - value: function _getStylesForTransition(_ref2) { - var item = _ref2.item, - styles = _ref2.styles; - - if (!styles.transitionDelay) { - styles.transitionDelay = '0ms'; - } - - var x = item.point.x; - var y = item.point.y; - - if (this.options.useTransforms) { - styles.transform = 'translate(' + x + 'px, ' + y + 'px) scale(' + item.scale + ')'; - } else { - styles.left = x + 'px'; - styles.top = y + 'px'; - } - - return styles; - } - - /** - * Listen for the transition end on an element and execute the itemCallback - * when it finishes. - * @param {Element} element Element to listen on. - * @param {Function} itemCallback Callback for the item. - * @param {Function} done Callback to notify `parallel` that this one is done. - */ - - }, { - key: '_whenTransitionDone', - value: function _whenTransitionDone(element, itemCallback, done) { - var id = onTransitionEnd(element, function (evt) { - itemCallback(); - done(null, evt); - }); - - this._transitions.push(id); - } - - /** - * Return a function which will set CSS styles and call the `done` function - * when (if) the transition finishes. - * @param {Object} opts Transition object. - * @return {Function} A function to be called with a `done` function. - */ - - }, { - key: '_getTransitionFunction', - value: function _getTransitionFunction(opts) { - var _this5 = this; - - return function (done) { - opts.item.applyCss(_this5._getStylesForTransition(opts)); - _this5._whenTransitionDone(opts.item.element, opts.callback, done); - }; - } - - /** - * Execute the styles gathered in the style queue. This applies styles to elements, - * triggering transitions. - * @private - */ - - }, { - key: '_processQueue', - value: function _processQueue() { - if (this.isTransitioning) { - this._cancelMovement(); - } - - var hasSpeed = this.options.speed > 0; - var hasQueue = this._queue.length > 0; - - if (hasQueue && hasSpeed && this.isInitialized) { - this._startTransitions(this._queue); - } else if (hasQueue) { - this._styleImmediately(this._queue); - this._dispatchLayout(); - - // A call to layout happened, but none of the newly visible items will - // change position or the transition duration is zero, which will not trigger - // the transitionend event. - } else { - this._dispatchLayout(); - } - - // Remove everything in the style queue - this._queue.length = 0; - } - - /** - * Wait for each transition to finish, the emit the layout event. - * @param {Array.} transitions Array of transition objects. - */ - - }, { - key: '_startTransitions', - value: function _startTransitions(transitions) { - var _this6 = this; - - // Set flag that shuffle is currently in motion. - this.isTransitioning = true; - - // Create an array of functions to be called. - var callbacks = transitions.map(function (obj) { - return _this6._getTransitionFunction(obj); - }); - - index$3(callbacks, this._movementFinished.bind(this)); - } - }, { - key: '_cancelMovement', - value: function _cancelMovement() { - // Remove the transition end event for each listener. - this._transitions.forEach(cancelTransitionEnd); - - // Reset the array. - this._transitions.length = 0; - - // Show it's no longer active. - this.isTransitioning = false; - } - - /** - * Apply styles without a transition. - * @param {Array.} objects Array of transition objects. - * @private - */ - - }, { - key: '_styleImmediately', - value: function _styleImmediately(objects) { - var _this7 = this; - - if (objects.length) { - var elements = objects.map(function (obj) { - return obj.item.element; - }); - - Shuffle._skipTransitions(elements, function () { - objects.forEach(function (obj) { - obj.item.applyCss(_this7._getStylesForTransition(obj)); - obj.callback(); - }); - }); - } - } - }, { - key: '_movementFinished', - value: function _movementFinished() { - this._transitions.length = 0; - this.isTransitioning = false; - this._dispatchLayout(); - } - }, { - key: '_dispatchLayout', - value: function _dispatchLayout() { - this._dispatch(Shuffle.EventType.LAYOUT); - } - - /** - * The magic. This is what makes the plugin 'shuffle' - * @param {string|Function|Array.} [category] Category to filter by. - * Can be a function, string, or array of strings. - * @param {Object} [sortObj] A sort object which can sort the visible set - */ - - }, { - key: 'filter', - value: function filter(category, sortObj) { - if (!this.isEnabled) { - return; - } - - if (!category || category && category.length === 0) { - category = Shuffle.ALL_ITEMS; // eslint-disable-line no-param-reassign - } - - this._filter(category); - - // Shrink each hidden item - this._shrink(); - - // How many visible elements? - this._updateItemCount(); - - // Update transforms on visible elements so they will animate to their new positions. - this.sort(sortObj); - } - - /** - * Gets the visible elements, sorts them, and passes them to layout. - * @param {Object} opts the options object for the sorted plugin - */ - - }, { - key: 'sort', - value: function sort() { - var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.lastSort; - - if (!this.isEnabled) { - return; - } - - this._resetCols(); - - var items = this._getFilteredItems(); - items = sorter(items, opts); - - this._layout(items); - - // `_layout` always happens after `_shrink`, so it's safe to process the style - // queue here with styles from the shrink method. - this._processQueue(); - - // Adjust the height of the container. - this._setContainerSize(); - - this.lastSort = opts; - } - - /** - * Reposition everything. - * @param {boolean} isOnlyLayout If true, column and gutter widths won't be - * recalculated. - */ - - }, { - key: 'update', - value: function update(isOnlyLayout) { - if (this.isEnabled) { - if (!isOnlyLayout) { - // Get updated colCount - this._setColumns(); - } - - // Layout items - this.sort(); - } - } - - /** - * Use this instead of `update()` if you don't need the columns and gutters updated - * Maybe an image inside `shuffle` loaded (and now has a height), which means calculations - * could be off. - */ - - }, { - key: 'layout', - value: function layout() { - this.update(true); - } - - /** - * New items have been appended to shuffle. Mix them in with the current - * filter or sort status. - * @param {Array.} newItems Collection of new items. - */ - - }, { - key: 'add', - value: function add(newItems) { - var items = index$1(newItems).map(function (el) { - return new ShuffleItem(el); - }); - - // Add classes and set initial positions. - this._initItems(items); - - // Add transition to each item. - this._setTransitions(items); - - // Update the list of items. - this.items = this.items.concat(items); - this._updateItemsOrder(); - this.filter(this.lastFilter); - } - - /** - * Disables shuffle from updating dimensions and layout on resize - */ - - }, { - key: 'disable', - value: function disable() { - this.isEnabled = false; - } - - /** - * Enables shuffle again - * @param {boolean} [isUpdateLayout=true] if undefined, shuffle will update columns and gutters - */ - - }, { - key: 'enable', - value: function enable(isUpdateLayout) { - this.isEnabled = true; - if (isUpdateLayout !== false) { - this.update(); - } - } - - /** - * Remove 1 or more shuffle items - * @param {Array.} elements An array containing one or more - * elements in shuffle - * @return {Shuffle} The shuffle object - */ - - }, { - key: 'remove', - value: function remove(elements) { - var _this8 = this; - - if (!elements.length) { - return; - } - - var collection = index$1(elements); - - var oldItems = collection.map(function (element) { - return _this8.getItemByElement(element); - }).filter(function (item) { - return !!item; - }); - - var handleLayout = function handleLayout() { - _this8.element.removeEventListener(Shuffle.EventType.LAYOUT, handleLayout); - _this8._disposeItems(oldItems); - - // Remove the collection in the callback - collection.forEach(function (element) { - element.parentNode.removeChild(element); - }); - - _this8._dispatch(Shuffle.EventType.REMOVED, { collection: collection }); - }; - - // Hide collection first. - this._toggleFilterClasses({ - visible: [], - hidden: oldItems - }); - - this._shrink(oldItems); - - this.sort(); - - // Update the list of items here because `remove` could be called again - // with an item that is in the process of being removed. - this.items = this.items.filter(function (item) { - return !arrayIncludes(oldItems, item); - }); - this._updateItemCount(); - - this.element.addEventListener(Shuffle.EventType.LAYOUT, handleLayout); - } - - /** - * Retrieve a shuffle item by its element. - * @param {Element} element Element to look for. - * @return {?ShuffleItem} A shuffle item or null if it's not found. - */ - - }, { - key: 'getItemByElement', - value: function getItemByElement(element) { - for (var i = this.items.length - 1; i >= 0; i--) { - if (this.items[i].element === element) { - return this.items[i]; - } - } - - return null; - } - - /** - * Destroys shuffle, removes events, styles, and classes - */ - - }, { - key: 'destroy', - value: function destroy() { - this._cancelMovement(); - window.removeEventListener('resize', this._onResize); - - // Reset container styles - this.element.classList.remove('shuffle'); - this.element.removeAttribute('style'); - - // Reset individual item styles - this._disposeItems(); - - // Null DOM references - this.items = null; - this.options.sizer = null; - this.element = null; - this._transitions = null; - - // Set a flag so if a debounced resize has been triggered, - // it can first check if it is actually isDestroyed and not doing anything - this.isDestroyed = true; - } - - /** - * Returns the outer width of an element, optionally including its margins. - * - * There are a few different methods for getting the width of an element, none of - * which work perfectly for all Shuffle's use cases. - * - * 1. getBoundingClientRect() `left` and `right` properties. - * - Accounts for transform scaled elements, making it useless for Shuffle - * elements which have shrunk. - * 2. The `offsetWidth` property. - * - This value stays the same regardless of the elements transform property, - * however, it does not return subpixel values. - * 3. getComputedStyle() - * - This works great Chrome, Firefox, Safari, but IE<=11 does not include - * padding and border when box-sizing: border-box is set, requiring a feature - * test and extra work to add the padding back for IE and other browsers which - * follow the W3C spec here. - * - * @param {Element} element The element. - * @param {boolean} [includeMargins] Whether to include margins. Default is false. - * @return {{width: number, height: number}} The width and height. - */ - - }], [{ - key: 'getSize', - value: function getSize(element, includeMargins) { - // Store the styles so that they can be used by others without asking for it again. - var styles = window.getComputedStyle(element, null); - var width = getNumberStyle(element, 'width', styles); - var height = getNumberStyle(element, 'height', styles); - - if (includeMargins) { - var marginLeft = getNumberStyle(element, 'marginLeft', styles); - var marginRight = getNumberStyle(element, 'marginRight', styles); - var marginTop = getNumberStyle(element, 'marginTop', styles); - var marginBottom = getNumberStyle(element, 'marginBottom', styles); - width += marginLeft + marginRight; - height += marginTop + marginBottom; - } - - return { - width: width, - height: height - }; - } - - /** - * Change a property or execute a function which will not have a transition - * @param {Array.} elements DOM elements that won't be transitioned. - * @param {Function} callback A function which will be called while transition - * is set to 0ms. - * @private - */ - - }, { - key: '_skipTransitions', - value: function _skipTransitions(elements, callback) { - var zero = '0ms'; - - // Save current duration and delay. - var data = elements.map(function (element) { - var style = element.style; - var duration = style.transitionDuration; - var delay = style.transitionDelay; - - // Set the duration to zero so it happens immediately - style.transitionDuration = zero; - style.transitionDelay = zero; - - return { - duration: duration, - delay: delay - }; - }); - - callback(); - - // Cause reflow. - elements[0].offsetWidth; // eslint-disable-line no-unused-expressions - - // Put the duration back - elements.forEach(function (element, i) { - element.style.transitionDuration = data[i].duration; - element.style.transitionDelay = data[i].delay; - }); - } - }]); - return Shuffle; -}(); - -Shuffle.ShuffleItem = ShuffleItem; - -Shuffle.ALL_ITEMS = 'all'; -Shuffle.FILTER_ATTRIBUTE_KEY = 'groups'; - -/** - * @enum {string} - */ -Shuffle.EventType = { - LAYOUT: 'shuffle:layout', - REMOVED: 'shuffle:removed' -}; - -/** @enum {string} */ -Shuffle.Classes = Classes; - -/** - * @enum {string} - */ -Shuffle.FilterMode = { - ANY: 'any', - ALL: 'all' -}; - -// Overrideable options -Shuffle.options = { - // Initial filter group. - group: Shuffle.ALL_ITEMS, - - // Transition/animation speed (milliseconds). - speed: 250, - - // CSS easing function to use. - easing: 'ease', - - // e.g. '.picture-item'. - itemSelector: '*', - - // Element or selector string. Use an element to determine the size of columns - // and gutters. - sizer: null, - - // A static number or function that tells the plugin how wide the gutters - // between columns are (in pixels). - gutterWidth: 0, - - // A static number or function that returns a number which tells the plugin - // how wide the columns are (in pixels). - columnWidth: 0, - - // If your group is not json, and is comma delimeted, you could set delimeter - // to ','. - delimeter: null, - - // Useful for percentage based heights when they might not always be exactly - // the same (in pixels). - buffer: 0, - - // Reading the width of elements isn't precise enough and can cause columns to - // jump between values. - columnThreshold: 0.01, - - // Shuffle can be isInitialized with a sort object. It is the same object - // given to the sort method. - initialSort: null, - - // By default, shuffle will throttle resize events. This can be changed or - // removed. - throttle: index$2, - - // How often shuffle can be called on resize (in milliseconds). - throttleTime: 300, - - // Transition delay offset for each item in milliseconds. - staggerAmount: 15, - - // Maximum stagger delay in milliseconds. - staggerAmountMax: 250, - - // Whether to use transforms or absolute positioning. - useTransforms: true, - - // Affects using an array with filter. e.g. `filter(['one', 'two'])`. With "any", - // the element passes the test if any of its groups are in the array. With "all", - // the element only passes if all groups are in the array. - filterMode: Shuffle.FilterMode.ANY -}; - -// Expose for testing. Hack at your own risk. -Shuffle.__Point = Point; -Shuffle.__sorter = sorter; -Shuffle.__getColumnSpan = getColumnSpan; -Shuffle.__getAvailablePositions = getAvailablePositions; -Shuffle.__getShortColumn = getShortColumn; - -return Shuffle; - -}))); -//# sourceMappingURL=shuffle.js.map - -// TinyColor v1.4.1 -// https://github.com/bgrins/TinyColor -// Brian Grinstead, MIT License - -(function(Math) { - -var trimLeft = /^\s+/, - trimRight = /\s+$/, - tinyCounter = 0, - mathRound = Math.round, - mathMin = Math.min, - mathMax = Math.max, - mathRandom = Math.random; - -function tinycolor (color, opts) { - - color = (color) ? color : ''; - opts = opts || { }; - - // If input is already a tinycolor, return itself - if (color instanceof tinycolor) { - return color; - } - // If we are called as a function, call using new instead - if (!(this instanceof tinycolor)) { - return new tinycolor(color, opts); - } - - var rgb = inputToRGB(color); - this._originalInput = color, - this._r = rgb.r, - this._g = rgb.g, - this._b = rgb.b, - this._a = rgb.a, - this._roundA = mathRound(100*this._a) / 100, - this._format = opts.format || rgb.format; - this._gradientType = opts.gradientType; - - // Don't let the range of [0,255] come back in [0,1]. - // Potentially lose a little bit of precision here, but will fix issues where - // .5 gets interpreted as half of the total, instead of half of 1 - // If it was supposed to be 128, this was already taken care of by `inputToRgb` - if (this._r < 1) { this._r = mathRound(this._r); } - if (this._g < 1) { this._g = mathRound(this._g); } - if (this._b < 1) { this._b = mathRound(this._b); } - - this._ok = rgb.ok; - this._tc_id = tinyCounter++; -} - -tinycolor.prototype = { - isDark: function() { - return this.getBrightness() < 128; - }, - isLight: function() { - return !this.isDark(); - }, - isValid: function() { - return this._ok; - }, - getOriginalInput: function() { - return this._originalInput; - }, - getFormat: function() { - return this._format; - }, - getAlpha: function() { - return this._a; - }, - getBrightness: function() { - //http://www.w3.org/TR/AERT#color-contrast - var rgb = this.toRgb(); - return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000; - }, - getLuminance: function() { - //http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef - var rgb = this.toRgb(); - var RsRGB, GsRGB, BsRGB, R, G, B; - RsRGB = rgb.r/255; - GsRGB = rgb.g/255; - BsRGB = rgb.b/255; - - if (RsRGB <= 0.03928) {R = RsRGB / 12.92;} else {R = Math.pow(((RsRGB + 0.055) / 1.055), 2.4);} - if (GsRGB <= 0.03928) {G = GsRGB / 12.92;} else {G = Math.pow(((GsRGB + 0.055) / 1.055), 2.4);} - if (BsRGB <= 0.03928) {B = BsRGB / 12.92;} else {B = Math.pow(((BsRGB + 0.055) / 1.055), 2.4);} - return (0.2126 * R) + (0.7152 * G) + (0.0722 * B); - }, - setAlpha: function(value) { - this._a = boundAlpha(value); - this._roundA = mathRound(100*this._a) / 100; - return this; - }, - toHsv: function() { - var hsv = rgbToHsv(this._r, this._g, this._b); - return { h: hsv.h * 360, s: hsv.s, v: hsv.v, a: this._a }; - }, - toHsvString: function() { - var hsv = rgbToHsv(this._r, this._g, this._b); - var h = mathRound(hsv.h * 360), s = mathRound(hsv.s * 100), v = mathRound(hsv.v * 100); - return (this._a == 1) ? - "hsv(" + h + ", " + s + "%, " + v + "%)" : - "hsva(" + h + ", " + s + "%, " + v + "%, "+ this._roundA + ")"; - }, - toHsl: function() { - var hsl = rgbToHsl(this._r, this._g, this._b); - return { h: hsl.h * 360, s: hsl.s, l: hsl.l, a: this._a }; - }, - toHslString: function() { - var hsl = rgbToHsl(this._r, this._g, this._b); - var h = mathRound(hsl.h * 360), s = mathRound(hsl.s * 100), l = mathRound(hsl.l * 100); - return (this._a == 1) ? - "hsl(" + h + ", " + s + "%, " + l + "%)" : - "hsla(" + h + ", " + s + "%, " + l + "%, "+ this._roundA + ")"; - }, - toHex: function(allow3Char) { - return rgbToHex(this._r, this._g, this._b, allow3Char); - }, - toHexString: function(allow3Char) { - return '#' + this.toHex(allow3Char); - }, - toHex8: function(allow4Char) { - return rgbaToHex(this._r, this._g, this._b, this._a, allow4Char); - }, - toHex8String: function(allow4Char) { - return '#' + this.toHex8(allow4Char); - }, - toRgb: function() { - return { r: mathRound(this._r), g: mathRound(this._g), b: mathRound(this._b), a: this._a }; - }, - toRgbString: function() { - return (this._a == 1) ? - "rgb(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ")" : - "rgba(" + mathRound(this._r) + ", " + mathRound(this._g) + ", " + mathRound(this._b) + ", " + this._roundA + ")"; - }, - toPercentageRgb: function() { - return { r: mathRound(bound01(this._r, 255) * 100) + "%", g: mathRound(bound01(this._g, 255) * 100) + "%", b: mathRound(bound01(this._b, 255) * 100) + "%", a: this._a }; - }, - toPercentageRgbString: function() { - return (this._a == 1) ? - "rgb(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%)" : - "rgba(" + mathRound(bound01(this._r, 255) * 100) + "%, " + mathRound(bound01(this._g, 255) * 100) + "%, " + mathRound(bound01(this._b, 255) * 100) + "%, " + this._roundA + ")"; - }, - toName: function() { - if (this._a === 0) { - return "transparent"; - } - - if (this._a < 1) { - return false; - } - - return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false; - }, - toFilter: function(secondColor) { - var hex8String = '#' + rgbaToArgbHex(this._r, this._g, this._b, this._a); - var secondHex8String = hex8String; - var gradientType = this._gradientType ? "GradientType = 1, " : ""; - - if (secondColor) { - var s = tinycolor(secondColor); - secondHex8String = '#' + rgbaToArgbHex(s._r, s._g, s._b, s._a); - } - - return "progid:DXImageTransform.Microsoft.gradient("+gradientType+"startColorstr="+hex8String+",endColorstr="+secondHex8String+")"; - }, - toString: function(format) { - var formatSet = !!format; - format = format || this._format; - - var formattedString = false; - var hasAlpha = this._a < 1 && this._a >= 0; - var needsAlphaFormat = !formatSet && hasAlpha && (format === "hex" || format === "hex6" || format === "hex3" || format === "hex4" || format === "hex8" || format === "name"); - - if (needsAlphaFormat) { - // Special case for "transparent", all other non-alpha formats - // will return rgba when there is transparency. - if (format === "name" && this._a === 0) { - return this.toName(); - } - return this.toRgbString(); - } - if (format === "rgb") { - formattedString = this.toRgbString(); - } - if (format === "prgb") { - formattedString = this.toPercentageRgbString(); - } - if (format === "hex" || format === "hex6") { - formattedString = this.toHexString(); - } - if (format === "hex3") { - formattedString = this.toHexString(true); - } - if (format === "hex4") { - formattedString = this.toHex8String(true); - } - if (format === "hex8") { - formattedString = this.toHex8String(); - } - if (format === "name") { - formattedString = this.toName(); - } - if (format === "hsl") { - formattedString = this.toHslString(); - } - if (format === "hsv") { - formattedString = this.toHsvString(); - } - - return formattedString || this.toHexString(); - }, - clone: function() { - return tinycolor(this.toString()); - }, - - _applyModification: function(fn, args) { - var color = fn.apply(null, [this].concat([].slice.call(args))); - this._r = color._r; - this._g = color._g; - this._b = color._b; - this.setAlpha(color._a); - return this; - }, - lighten: function() { - return this._applyModification(lighten, arguments); - }, - brighten: function() { - return this._applyModification(brighten, arguments); - }, - darken: function() { - return this._applyModification(darken, arguments); - }, - desaturate: function() { - return this._applyModification(desaturate, arguments); - }, - saturate: function() { - return this._applyModification(saturate, arguments); - }, - greyscale: function() { - return this._applyModification(greyscale, arguments); - }, - spin: function() { - return this._applyModification(spin, arguments); - }, - - _applyCombination: function(fn, args) { - return fn.apply(null, [this].concat([].slice.call(args))); - }, - analogous: function() { - return this._applyCombination(analogous, arguments); - }, - complement: function() { - return this._applyCombination(complement, arguments); - }, - monochromatic: function() { - return this._applyCombination(monochromatic, arguments); - }, - splitcomplement: function() { - return this._applyCombination(splitcomplement, arguments); - }, - triad: function() { - return this._applyCombination(triad, arguments); - }, - tetrad: function() { - return this._applyCombination(tetrad, arguments); - } -}; - -// If input is an object, force 1 into "1.0" to handle ratios properly -// String input requires "1.0" as input, so 1 will be treated as 1 -tinycolor.fromRatio = function(color, opts) { - if (typeof color == "object") { - var newColor = {}; - for (var i in color) { - if (color.hasOwnProperty(i)) { - if (i === "a") { - newColor[i] = color[i]; - } - else { - newColor[i] = convertToPercentage(color[i]); - } - } - } - color = newColor; - } - - return tinycolor(color, opts); -}; - -// Given a string or object, convert that input to RGB -// Possible string inputs: -// -// "red" -// "#f00" or "f00" -// "#ff0000" or "ff0000" -// "#ff000000" or "ff000000" -// "rgb 255 0 0" or "rgb (255, 0, 0)" -// "rgb 1.0 0 0" or "rgb (1, 0, 0)" -// "rgba (255, 0, 0, 1)" or "rgba 255, 0, 0, 1" -// "rgba (1.0, 0, 0, 1)" or "rgba 1.0, 0, 0, 1" -// "hsl(0, 100%, 50%)" or "hsl 0 100% 50%" -// "hsla(0, 100%, 50%, 1)" or "hsla 0 100% 50%, 1" -// "hsv(0, 100%, 100%)" or "hsv 0 100% 100%" -// -function inputToRGB(color) { - - var rgb = { r: 0, g: 0, b: 0 }; - var a = 1; - var s = null; - var v = null; - var l = null; - var ok = false; - var format = false; - - if (typeof color == "string") { - color = stringInputToObject(color); - } - - if (typeof color == "object") { - if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) { - rgb = rgbToRgb(color.r, color.g, color.b); - ok = true; - format = String(color.r).substr(-1) === "%" ? "prgb" : "rgb"; - } - else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) { - s = convertToPercentage(color.s); - v = convertToPercentage(color.v); - rgb = hsvToRgb(color.h, s, v); - ok = true; - format = "hsv"; - } - else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) { - s = convertToPercentage(color.s); - l = convertToPercentage(color.l); - rgb = hslToRgb(color.h, s, l); - ok = true; - format = "hsl"; - } - - if (color.hasOwnProperty("a")) { - a = color.a; - } - } - - a = boundAlpha(a); - - return { - ok: ok, - format: color.format || format, - r: mathMin(255, mathMax(rgb.r, 0)), - g: mathMin(255, mathMax(rgb.g, 0)), - b: mathMin(255, mathMax(rgb.b, 0)), - a: a - }; -} - - -// Conversion Functions -// -------------------- - -// `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from: -// - -// `rgbToRgb` -// Handle bounds / percentage checking to conform to CSS color spec -// -// *Assumes:* r, g, b in [0, 255] or [0, 1] -// *Returns:* { r, g, b } in [0, 255] -function rgbToRgb(r, g, b){ - return { - r: bound01(r, 255) * 255, - g: bound01(g, 255) * 255, - b: bound01(b, 255) * 255 - }; -} - -// `rgbToHsl` -// Converts an RGB color value to HSL. -// *Assumes:* r, g, and b are contained in [0, 255] or [0, 1] -// *Returns:* { h, s, l } in [0,1] -function rgbToHsl(r, g, b) { - - r = bound01(r, 255); - g = bound01(g, 255); - b = bound01(b, 255); - - var max = mathMax(r, g, b), min = mathMin(r, g, b); - var h, s, l = (max + min) / 2; - - if(max == min) { - h = s = 0; // achromatic - } - else { - var d = max - min; - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - switch(max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - - h /= 6; - } - - return { h: h, s: s, l: l }; -} - -// `hslToRgb` -// Converts an HSL color value to RGB. -// *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100] -// *Returns:* { r, g, b } in the set [0, 255] -function hslToRgb(h, s, l) { - var r, g, b; - - h = bound01(h, 360); - s = bound01(s, 100); - l = bound01(l, 100); - - function hue2rgb(p, q, t) { - if(t < 0) t += 1; - if(t > 1) t -= 1; - if(t < 1/6) return p + (q - p) * 6 * t; - if(t < 1/2) return q; - if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; - return p; - } - - if(s === 0) { - r = g = b = l; // achromatic - } - else { - var q = l < 0.5 ? l * (1 + s) : l + s - l * s; - var p = 2 * l - q; - r = hue2rgb(p, q, h + 1/3); - g = hue2rgb(p, q, h); - b = hue2rgb(p, q, h - 1/3); - } - - return { r: r * 255, g: g * 255, b: b * 255 }; -} - -// `rgbToHsv` -// Converts an RGB color value to HSV -// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1] -// *Returns:* { h, s, v } in [0,1] -function rgbToHsv(r, g, b) { - - r = bound01(r, 255); - g = bound01(g, 255); - b = bound01(b, 255); - - var max = mathMax(r, g, b), min = mathMin(r, g, b); - var h, s, v = max; - - var d = max - min; - s = max === 0 ? 0 : d / max; - - if(max == min) { - h = 0; // achromatic - } - else { - switch(max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h, s: s, v: v }; -} - -// `hsvToRgb` -// Converts an HSV color value to RGB. -// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100] -// *Returns:* { r, g, b } in the set [0, 255] - function hsvToRgb(h, s, v) { - - h = bound01(h, 360) * 6; - s = bound01(s, 100); - v = bound01(v, 100); - - var i = Math.floor(h), - f = h - i, - p = v * (1 - s), - q = v * (1 - f * s), - t = v * (1 - (1 - f) * s), - mod = i % 6, - r = [v, q, p, p, t, v][mod], - g = [t, v, v, q, p, p][mod], - b = [p, p, t, v, v, q][mod]; - - return { r: r * 255, g: g * 255, b: b * 255 }; -} - -// `rgbToHex` -// Converts an RGB color to hex -// Assumes r, g, and b are contained in the set [0, 255] -// Returns a 3 or 6 character hex -function rgbToHex(r, g, b, allow3Char) { - - var hex = [ - pad2(mathRound(r).toString(16)), - pad2(mathRound(g).toString(16)), - pad2(mathRound(b).toString(16)) - ]; - - // Return a 3 character hex if possible - if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) { - return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0); - } - - return hex.join(""); -} - -// `rgbaToHex` -// Converts an RGBA color plus alpha transparency to hex -// Assumes r, g, b are contained in the set [0, 255] and -// a in [0, 1]. Returns a 4 or 8 character rgba hex -function rgbaToHex(r, g, b, a, allow4Char) { - - var hex = [ - pad2(mathRound(r).toString(16)), - pad2(mathRound(g).toString(16)), - pad2(mathRound(b).toString(16)), - pad2(convertDecimalToHex(a)) - ]; - - // Return a 4 character hex if possible - if (allow4Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1) && hex[3].charAt(0) == hex[3].charAt(1)) { - return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0); - } - - return hex.join(""); -} - -// `rgbaToArgbHex` -// Converts an RGBA color to an ARGB Hex8 string -// Rarely used, but required for "toFilter()" -function rgbaToArgbHex(r, g, b, a) { - - var hex = [ - pad2(convertDecimalToHex(a)), - pad2(mathRound(r).toString(16)), - pad2(mathRound(g).toString(16)), - pad2(mathRound(b).toString(16)) - ]; - - return hex.join(""); -} - -// `equals` -// Can be called with any tinycolor input -tinycolor.equals = function (color1, color2) { - if (!color1 || !color2) { return false; } - return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString(); -}; - -tinycolor.random = function() { - return tinycolor.fromRatio({ - r: mathRandom(), - g: mathRandom(), - b: mathRandom() - }); -}; - - -// Modification Functions -// ---------------------- -// Thanks to less.js for some of the basics here -// - -function desaturate(color, amount) { - amount = (amount === 0) ? 0 : (amount || 10); - var hsl = tinycolor(color).toHsl(); - hsl.s -= amount / 100; - hsl.s = clamp01(hsl.s); - return tinycolor(hsl); -} - -function saturate(color, amount) { - amount = (amount === 0) ? 0 : (amount || 10); - var hsl = tinycolor(color).toHsl(); - hsl.s += amount / 100; - hsl.s = clamp01(hsl.s); - return tinycolor(hsl); -} - -function greyscale(color) { - return tinycolor(color).desaturate(100); -} - -function lighten (color, amount) { - amount = (amount === 0) ? 0 : (amount || 10); - var hsl = tinycolor(color).toHsl(); - hsl.l += amount / 100; - hsl.l = clamp01(hsl.l); - return tinycolor(hsl); -} - -function brighten(color, amount) { - amount = (amount === 0) ? 0 : (amount || 10); - var rgb = tinycolor(color).toRgb(); - rgb.r = mathMax(0, mathMin(255, rgb.r - mathRound(255 * - (amount / 100)))); - rgb.g = mathMax(0, mathMin(255, rgb.g - mathRound(255 * - (amount / 100)))); - rgb.b = mathMax(0, mathMin(255, rgb.b - mathRound(255 * - (amount / 100)))); - return tinycolor(rgb); -} - -function darken (color, amount) { - amount = (amount === 0) ? 0 : (amount || 10); - var hsl = tinycolor(color).toHsl(); - hsl.l -= amount / 100; - hsl.l = clamp01(hsl.l); - return tinycolor(hsl); -} - -// Spin takes a positive or negative amount within [-360, 360] indicating the change of hue. -// Values outside of this range will be wrapped into this range. -function spin(color, amount) { - var hsl = tinycolor(color).toHsl(); - var hue = (hsl.h + amount) % 360; - hsl.h = hue < 0 ? 360 + hue : hue; - return tinycolor(hsl); -} - -// Combination Functions -// --------------------- -// Thanks to jQuery xColor for some of the ideas behind these -// - -function complement(color) { - var hsl = tinycolor(color).toHsl(); - hsl.h = (hsl.h + 180) % 360; - return tinycolor(hsl); -} - -function triad(color) { - var hsl = tinycolor(color).toHsl(); - var h = hsl.h; - return [ - tinycolor(color), - tinycolor({ h: (h + 120) % 360, s: hsl.s, l: hsl.l }), - tinycolor({ h: (h + 240) % 360, s: hsl.s, l: hsl.l }) - ]; -} - -function tetrad(color) { - var hsl = tinycolor(color).toHsl(); - var h = hsl.h; - return [ - tinycolor(color), - tinycolor({ h: (h + 90) % 360, s: hsl.s, l: hsl.l }), - tinycolor({ h: (h + 180) % 360, s: hsl.s, l: hsl.l }), - tinycolor({ h: (h + 270) % 360, s: hsl.s, l: hsl.l }) - ]; -} - -function splitcomplement(color) { - var hsl = tinycolor(color).toHsl(); - var h = hsl.h; - return [ - tinycolor(color), - tinycolor({ h: (h + 72) % 360, s: hsl.s, l: hsl.l}), - tinycolor({ h: (h + 216) % 360, s: hsl.s, l: hsl.l}) - ]; -} - -function analogous(color, results, slices) { - results = results || 6; - slices = slices || 30; - - var hsl = tinycolor(color).toHsl(); - var part = 360 / slices; - var ret = [tinycolor(color)]; - - for (hsl.h = ((hsl.h - (part * results >> 1)) + 720) % 360; --results; ) { - hsl.h = (hsl.h + part) % 360; - ret.push(tinycolor(hsl)); - } - return ret; -} - -function monochromatic(color, results) { - results = results || 6; - var hsv = tinycolor(color).toHsv(); - var h = hsv.h, s = hsv.s, v = hsv.v; - var ret = []; - var modification = 1 / results; - - while (results--) { - ret.push(tinycolor({ h: h, s: s, v: v})); - v = (v + modification) % 1; - } - - return ret; -} - -// Utility Functions -// --------------------- - -tinycolor.mix = function(color1, color2, amount) { - amount = (amount === 0) ? 0 : (amount || 50); - - var rgb1 = tinycolor(color1).toRgb(); - var rgb2 = tinycolor(color2).toRgb(); - - var p = amount / 100; - - var rgba = { - r: ((rgb2.r - rgb1.r) * p) + rgb1.r, - g: ((rgb2.g - rgb1.g) * p) + rgb1.g, - b: ((rgb2.b - rgb1.b) * p) + rgb1.b, - a: ((rgb2.a - rgb1.a) * p) + rgb1.a - }; - - return tinycolor(rgba); -}; - - -// Readability Functions -// --------------------- -// false -// tinycolor.isReadable("#000", "#111",{level:"AA",size:"large"}) => false -tinycolor.isReadable = function(color1, color2, wcag2) { - var readability = tinycolor.readability(color1, color2); - var wcag2Parms, out; - - out = false; - - wcag2Parms = validateWCAG2Parms(wcag2); - switch (wcag2Parms.level + wcag2Parms.size) { - case "AAsmall": - case "AAAlarge": - out = readability >= 4.5; - break; - case "AAlarge": - out = readability >= 3; - break; - case "AAAsmall": - out = readability >= 7; - break; - } - return out; - -}; - -// `mostReadable` -// Given a base color and a list of possible foreground or background -// colors for that base, returns the most readable color. -// Optionally returns Black or White if the most readable color is unreadable. -// *Example* -// tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:false}).toHexString(); // "#112255" -// tinycolor.mostReadable(tinycolor.mostReadable("#123", ["#124", "#125"],{includeFallbackColors:true}).toHexString(); // "#ffffff" -// tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"large"}).toHexString(); // "#faf3f3" -// tinycolor.mostReadable("#a8015a", ["#faf3f3"],{includeFallbackColors:true,level:"AAA",size:"small"}).toHexString(); // "#ffffff" -tinycolor.mostReadable = function(baseColor, colorList, args) { - var bestColor = null; - var bestScore = 0; - var readability; - var includeFallbackColors, level, size ; - args = args || {}; - includeFallbackColors = args.includeFallbackColors ; - level = args.level; - size = args.size; - - for (var i= 0; i < colorList.length ; i++) { - readability = tinycolor.readability(baseColor, colorList[i]); - if (readability > bestScore) { - bestScore = readability; - bestColor = tinycolor(colorList[i]); - } - } - - if (tinycolor.isReadable(baseColor, bestColor, {"level":level,"size":size}) || !includeFallbackColors) { - return bestColor; - } - else { - args.includeFallbackColors=false; - return tinycolor.mostReadable(baseColor,["#fff", "#000"],args); - } -}; - - -// Big List of Colors -// ------------------ -// -var names = tinycolor.names = { - aliceblue: "f0f8ff", - antiquewhite: "faebd7", - aqua: "0ff", - aquamarine: "7fffd4", - azure: "f0ffff", - beige: "f5f5dc", - bisque: "ffe4c4", - black: "000", - blanchedalmond: "ffebcd", - blue: "00f", - blueviolet: "8a2be2", - brown: "a52a2a", - burlywood: "deb887", - burntsienna: "ea7e5d", - cadetblue: "5f9ea0", - chartreuse: "7fff00", - chocolate: "d2691e", - coral: "ff7f50", - cornflowerblue: "6495ed", - cornsilk: "fff8dc", - crimson: "dc143c", - cyan: "0ff", - darkblue: "00008b", - darkcyan: "008b8b", - darkgoldenrod: "b8860b", - darkgray: "a9a9a9", - darkgreen: "006400", - darkgrey: "a9a9a9", - darkkhaki: "bdb76b", - darkmagenta: "8b008b", - darkolivegreen: "556b2f", - darkorange: "ff8c00", - darkorchid: "9932cc", - darkred: "8b0000", - darksalmon: "e9967a", - darkseagreen: "8fbc8f", - darkslateblue: "483d8b", - darkslategray: "2f4f4f", - darkslategrey: "2f4f4f", - darkturquoise: "00ced1", - darkviolet: "9400d3", - deeppink: "ff1493", - deepskyblue: "00bfff", - dimgray: "696969", - dimgrey: "696969", - dodgerblue: "1e90ff", - firebrick: "b22222", - floralwhite: "fffaf0", - forestgreen: "228b22", - fuchsia: "f0f", - gainsboro: "dcdcdc", - ghostwhite: "f8f8ff", - gold: "ffd700", - goldenrod: "daa520", - gray: "808080", - green: "008000", - greenyellow: "adff2f", - grey: "808080", - honeydew: "f0fff0", - hotpink: "ff69b4", - indianred: "cd5c5c", - indigo: "4b0082", - ivory: "fffff0", - khaki: "f0e68c", - lavender: "e6e6fa", - lavenderblush: "fff0f5", - lawngreen: "7cfc00", - lemonchiffon: "fffacd", - lightblue: "add8e6", - lightcoral: "f08080", - lightcyan: "e0ffff", - lightgoldenrodyellow: "fafad2", - lightgray: "d3d3d3", - lightgreen: "90ee90", - lightgrey: "d3d3d3", - lightpink: "ffb6c1", - lightsalmon: "ffa07a", - lightseagreen: "20b2aa", - lightskyblue: "87cefa", - lightslategray: "789", - lightslategrey: "789", - lightsteelblue: "b0c4de", - lightyellow: "ffffe0", - lime: "0f0", - limegreen: "32cd32", - linen: "faf0e6", - magenta: "f0f", - maroon: "800000", - mediumaquamarine: "66cdaa", - mediumblue: "0000cd", - mediumorchid: "ba55d3", - mediumpurple: "9370db", - mediumseagreen: "3cb371", - mediumslateblue: "7b68ee", - mediumspringgreen: "00fa9a", - mediumturquoise: "48d1cc", - mediumvioletred: "c71585", - midnightblue: "191970", - mintcream: "f5fffa", - mistyrose: "ffe4e1", - moccasin: "ffe4b5", - navajowhite: "ffdead", - navy: "000080", - oldlace: "fdf5e6", - olive: "808000", - olivedrab: "6b8e23", - orange: "ffa500", - orangered: "ff4500", - orchid: "da70d6", - palegoldenrod: "eee8aa", - palegreen: "98fb98", - paleturquoise: "afeeee", - palevioletred: "db7093", - papayawhip: "ffefd5", - peachpuff: "ffdab9", - peru: "cd853f", - pink: "ffc0cb", - plum: "dda0dd", - powderblue: "b0e0e6", - purple: "800080", - rebeccapurple: "663399", - red: "f00", - rosybrown: "bc8f8f", - royalblue: "4169e1", - saddlebrown: "8b4513", - salmon: "fa8072", - sandybrown: "f4a460", - seagreen: "2e8b57", - seashell: "fff5ee", - sienna: "a0522d", - silver: "c0c0c0", - skyblue: "87ceeb", - slateblue: "6a5acd", - slategray: "708090", - slategrey: "708090", - snow: "fffafa", - springgreen: "00ff7f", - steelblue: "4682b4", - tan: "d2b48c", - teal: "008080", - thistle: "d8bfd8", - tomato: "ff6347", - turquoise: "40e0d0", - violet: "ee82ee", - wheat: "f5deb3", - white: "fff", - whitesmoke: "f5f5f5", - yellow: "ff0", - yellowgreen: "9acd32" -}; - -// Make it easy to access colors via `hexNames[hex]` -var hexNames = tinycolor.hexNames = flip(names); - - -// Utilities -// --------- - -// `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }` -function flip(o) { - var flipped = { }; - for (var i in o) { - if (o.hasOwnProperty(i)) { - flipped[o[i]] = i; - } - } - return flipped; -} - -// Return a valid alpha value [0,1] with all invalid values being set to 1 -function boundAlpha(a) { - a = parseFloat(a); - - if (isNaN(a) || a < 0 || a > 1) { - a = 1; - } - - return a; -} - -// Take input from [0, n] and return it as [0, 1] -function bound01(n, max) { - if (isOnePointZero(n)) { n = "100%"; } - - var processPercent = isPercentage(n); - n = mathMin(max, mathMax(0, parseFloat(n))); - - // Automatically convert percentage into number - if (processPercent) { - n = parseInt(n * max, 10) / 100; - } - - // Handle floating point rounding errors - if ((Math.abs(n - max) < 0.000001)) { - return 1; - } - - // Convert into [0, 1] range if it isn't already - return (n % max) / parseFloat(max); -} - -// Force a number between 0 and 1 -function clamp01(val) { - return mathMin(1, mathMax(0, val)); -} - -// Parse a base-16 hex value into a base-10 integer -function parseIntFromHex(val) { - return parseInt(val, 16); -} - -// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1 -// -function isOnePointZero(n) { - return typeof n == "string" && n.indexOf('.') != -1 && parseFloat(n) === 1; -} - -// Check to see if string passed in is a percentage -function isPercentage(n) { - return typeof n === "string" && n.indexOf('%') != -1; -} - -// Force a hex value to have 2 characters -function pad2(c) { - return c.length == 1 ? '0' + c : '' + c; -} - -// Replace a decimal with it's percentage value -function convertToPercentage(n) { - if (n <= 1) { - n = (n * 100) + "%"; - } - - return n; -} - -// Converts a decimal to a hex value -function convertDecimalToHex(d) { - return Math.round(parseFloat(d) * 255).toString(16); -} -// Converts a hex value to a decimal -function convertHexToDecimal(h) { - return (parseIntFromHex(h) / 255); -} - -var matchers = (function() { - - // - var CSS_INTEGER = "[-\\+]?\\d+%?"; - - // - var CSS_NUMBER = "[-\\+]?\\d*\\.\\d+%?"; - - // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome. - var CSS_UNIT = "(?:" + CSS_NUMBER + ")|(?:" + CSS_INTEGER + ")"; - - // Actual matching. - // Parentheses and commas are optional, but not required. - // Whitespace can take the place of commas or opening paren - var PERMISSIVE_MATCH3 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; - var PERMISSIVE_MATCH4 = "[\\s|\\(]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")[,|\\s]+(" + CSS_UNIT + ")\\s*\\)?"; - - return { - CSS_UNIT: new RegExp(CSS_UNIT), - rgb: new RegExp("rgb" + PERMISSIVE_MATCH3), - rgba: new RegExp("rgba" + PERMISSIVE_MATCH4), - hsl: new RegExp("hsl" + PERMISSIVE_MATCH3), - hsla: new RegExp("hsla" + PERMISSIVE_MATCH4), - hsv: new RegExp("hsv" + PERMISSIVE_MATCH3), - hsva: new RegExp("hsva" + PERMISSIVE_MATCH4), - hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, - hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/, - hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/, - hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/ - }; -})(); - -// `isValidCSSUnit` -// Take in a single string / number and check to see if it looks like a CSS unit -// (see `matchers` above for definition). -function isValidCSSUnit(color) { - return !!matchers.CSS_UNIT.exec(color); -} - -// `stringInputToObject` -// Permissive string parsing. Take in a number of formats, and output an object -// based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}` -function stringInputToObject(color) { - - color = color.replace(trimLeft,'').replace(trimRight, '').toLowerCase(); - var named = false; - if (names[color]) { - color = names[color]; - named = true; - } - else if (color == 'transparent') { - return { r: 0, g: 0, b: 0, a: 0, format: "name" }; - } - - // Try to match string input using regular expressions. - // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360] - // Just return an object and let the conversion functions handle that. - // This way the result will be the same whether the tinycolor is initialized with string or object. - var match; - if ((match = matchers.rgb.exec(color))) { - return { r: match[1], g: match[2], b: match[3] }; - } - if ((match = matchers.rgba.exec(color))) { - return { r: match[1], g: match[2], b: match[3], a: match[4] }; - } - if ((match = matchers.hsl.exec(color))) { - return { h: match[1], s: match[2], l: match[3] }; - } - if ((match = matchers.hsla.exec(color))) { - return { h: match[1], s: match[2], l: match[3], a: match[4] }; - } - if ((match = matchers.hsv.exec(color))) { - return { h: match[1], s: match[2], v: match[3] }; - } - if ((match = matchers.hsva.exec(color))) { - return { h: match[1], s: match[2], v: match[3], a: match[4] }; - } - if ((match = matchers.hex8.exec(color))) { - return { - r: parseIntFromHex(match[1]), - g: parseIntFromHex(match[2]), - b: parseIntFromHex(match[3]), - a: convertHexToDecimal(match[4]), - format: named ? "name" : "hex8" - }; - } - if ((match = matchers.hex6.exec(color))) { - return { - r: parseIntFromHex(match[1]), - g: parseIntFromHex(match[2]), - b: parseIntFromHex(match[3]), - format: named ? "name" : "hex" - }; - } - if ((match = matchers.hex4.exec(color))) { - return { - r: parseIntFromHex(match[1] + '' + match[1]), - g: parseIntFromHex(match[2] + '' + match[2]), - b: parseIntFromHex(match[3] + '' + match[3]), - a: convertHexToDecimal(match[4] + '' + match[4]), - format: named ? "name" : "hex8" - }; - } - if ((match = matchers.hex3.exec(color))) { - return { - r: parseIntFromHex(match[1] + '' + match[1]), - g: parseIntFromHex(match[2] + '' + match[2]), - b: parseIntFromHex(match[3] + '' + match[3]), - format: named ? "name" : "hex" - }; - } - - return false; -} - -function validateWCAG2Parms(parms) { - // return valid WCAG2 parms for isReadable. - // If input parms are invalid, return {"level":"AA", "size":"small"} - var level, size; - parms = parms || {"level":"AA", "size":"small"}; - level = (parms.level || "AA").toUpperCase(); - size = (parms.size || "small").toLowerCase(); - if (level !== "AA" && level !== "AAA") { - level = "AA"; - } - if (size !== "small" && size !== "large") { - size = "small"; - } - return {"level":level, "size":size}; -} - -// Node: Export function -if (typeof module !== "undefined" && module.exports) { - module.exports = tinycolor; -} -// AMD/requirejs: Define the module -else if (typeof define === 'function' && define.amd) { - define(function () {return tinycolor;}); -} -// Browser: Expose to window -else { - window.tinycolor = tinycolor; -} - -})(Math); - - - - -String.prototype.hashCode = function(){ - // djb2 hash algorithm - var hash = 5381; - for (i = 0; i < this.length; i++) { - char = this.charCodeAt(i); - hash = ((hash << 5) + hash) + char; /* hash * 33 + c */ - } - return hash >>> 0; -}; - -var Color = tinycolor; - - -var Shuffle = window.shuffle; - -var shuffle = new Shuffle(document.querySelector('.tile-container'), { - group: shuffle.ALL_ITEMS, - itemSelector: '.tile', - gutterWidth: 16, - columnWidth: 188, - buffer: 1, - delimeter: ",", - useTransforms: false, -}); - -var filterTiles = function(tag) { - shuffle.filter(location.hash.slice(1)); -}; - -window.onhashchange = filterTiles; - -var getUrlParts = function(baseUrl) { - var urlParts = { - domain: "", - before: "", - after: "" - }; - var url = new URL(baseUrl); - var host = url.host; - urlParts.domain = host.replace(/^www\./i, ""); - - if (host.match(/^\d+\.\d+\.\d+\.\d+$/)) { - urlParts.domain = host; - return urlParts; - } else if (host.match(/^(\d+\.\d+\.\d+\.\d+)(:(\d+))?$/)) { - hostParts = host.match(/^(\d+\.\d+\.\d+\.\d+)(:(\d+))?$/); - urlParts.domain = hostParts[1]; - urlParts.after = hostParts[3]; - return urlParts; - } - - var hostParts = urlParts.domain.split("."); - var longestPartIndex = 0; - for (var i = 1; i < hostParts.length - 1; i++) { - if (hostParts[i].length > hostParts[longestPartIndex].length) { - longestPartIndex = i; - } - } - - urlParts.domain = hostParts[longestPartIndex]; - urlParts.before = hostParts.slice(0, longestPartIndex).join("."); - urlParts.after = hostParts.slice(longestPartIndex + 1).join("."); - - if(!urlParts.domain && url.pathname) { - urlParts.domain = url.pathname.split("/").filter(Boolean).pop(); - } - return urlParts; -}; - -var fitText = function(text, boxWidth, boxHeight) { - var resizer = document.createElement("div"); - resizer.style.visibility = "hidden"; - resizer.style.position = "absolute"; - document.body.appendChild(resizer); - - var size = 40; - - resizer.innerHTML = text; - resizer.style.fontSize = size; - while (resizer.offsetWidth > boxWidth) { - size = size - 1; - resizer.style.fontSize = size; - } - - var textInfo = { - size: size, - width: resizer.offsetWidth, - height: resizer.offsetHeight - }; - resizer.remove(); - return textInfo; -}; - - -var getTileColor = function(domain) { - var colorMap = [ - "#B42424", - "#C83D1D", - "#BB7231", - "#E06B00", - "#55931F", - "#1C941B", - "#189365", - "#189196", - "#2D85A4", - "#2B6C90", - "#205396", - "#39448F", - "#55338E", - "#683089", - "#963A97", - "#A43343", - "#982F2F", - "#D30000", - "#E54C29", - "#DA7E2C", - // "#F0C92C", - "#73B43A", - "#3AB43A", - "#3AB487", - "#3AB0B4", - "#47A6C7", - "#3A88B4", - "#3A6FB4", - "#3A4AB4", - "#673AB4", - "#863AB4", - "#C846C9", - "#C44A5B", - "#AA4444", - "#E84545", - "#FF6946", - "#EC9344", - // "#F4D34F", - // "#8BD34B", - // "#4AD449", - // "#6FDFB5", - // "#45D3D9", - // "#5CC4E8", - "#3CA4DF", - "#3A83E3", - "#4056E3", - "#9058F0", - "#B467E2", - "#DF7CDF", - "#E5576B", - "#D35A5A", - // "#FF9C44", - // "#F2B722", - // "#4DCC7B", - "#3DC53D", - "#2DBBB1", - "#5E95D5", - // "#41BBF5", - "#5E5BE7", - "#1B7EFF", - "#5F74FF", - "#8A45FF", - "#B856F3", - "#DD66DD" -]; - - return colorMap[domain.hashCode() % colorMap.length]; - -}; - -var renderImgTile = function(tile) { - tile.innerHTML = ""; - - var bgColor = tile.getAttribute("data-bg-color"); - if (!bgColor) { - bgColor = "rgba(255,255,255,.8)"; - } - bgColor = Color(bgColor); - bgColor.setAlpha(0.8); - tile.style.backgroundColor = bgColor; - - var img = new Image(); - img.src = tile.getAttribute("data-img"); - img.className = "logo"; - tile.appendChild(img); -}; - -var renderPlainTile = function(tile) { - var urlParts = getUrlParts(tile.getAttribute("data-url")); - tile.innerHTML = ""; - - var bgColor = tile.getAttribute("data-bg-color"); - if (!bgColor) { - bgColor = "rgba(255,255,255,.8)"; - } - bgColor = Color(bgColor); - bgColor.setAlpha(0.8); - tile.style.backgroundColor = bgColor; - - var txtColor = tile.getAttribute("data-txt-color"); - if (!txtColor) { - txtColor = getTileColor(urlParts.domain); - if (bgColor.isDark()) { - tile.style.color = "white"; - } - } - txtColor = Color(txtColor); - tile.style.color = txtColor; - - var boxWidth = 188, boxHeight = 120; - var margin = 8; - - var textInfo = fitText(urlParts.domain, boxWidth-margin*2, boxHeight); - - var domainDiv = document.createElement("div"); - domainDiv.style.fontSize = textInfo.size; - domainDiv.style.position = "absolute"; - tile.appendChild(domainDiv); - - var beforeDiv = document.createElement("div"); - beforeDiv.innerHTML = urlParts.before; - // original forumla is 7/18*size-10 - beforeDiv.style.top = 0.35*textInfo.size-10; - beforeDiv.className = "pre-domain"; - beforeDiv.style.textShadow = "-1px 0 "+bgColor+",0 1px "+bgColor+",1px 0 "+bgColor+",0 -1px "+bgColor; - - var afterDiv = document.createElement("div"); - afterDiv.innerHTML = urlParts.after; - afterDiv.style.top = textInfo.size-0.05*textInfo.size; - afterDiv.className = "post-domain"; - afterDiv.style.textShadow = "-1px 0 "+bgColor+",0 1px "+bgColor+",1px 0 "+bgColor+",0 -1px "+bgColor; - - - domainDiv.appendChild(beforeDiv); - domainDiv.append(urlParts.domain); - domainDiv.appendChild(afterDiv); - - var top = (boxHeight + margin)/2 - domainDiv.clientHeight/2; - var left = (boxWidth + margin)/2 + margin - domainDiv.clientWidth/2; - domainDiv.style.top = top; - domainDiv.style.left = left; - - // console.log(urlParts.domain+"="+urlParts.domain.hashCode().toString()); -}; - -var renderTiles = function() { - var tiles = document.getElementsByClassName("tile-box"); - for(var i = 0; i < tiles.length; i++) - { - try { - if (tiles.item(i).getAttribute("data-img")) { - renderImgTile(tiles.item(i)); - } else { - renderPlainTile(tiles.item(i)); - } - } - catch(err) { - console.log("err:"+err); - } - } -}; - -renderTiles(); - -var getBackgroundImages = function() { - var backgrounds = document.getElementsByTagName("body"); - var images = []; - var imgString = backgrounds[0].getAttribute("data-backgrounds"); - if (imgString) { - images = imgString.split(/[\s,]+/).filter(Boolean); - } - return images; -}; - -var preloadBackgrounds = function() { - var images = getBackgroundImages(); - for(var i = 0; i < images.length; i++) - { - // caches images, avoiding white flash between background replacements - new Image().src = images[i]; - } -}; - -var rotateBackground = function(count) { - if (count === undefined || count === null) { - count = 0; - } - - var images = getBackgroundImages(); - if (images.length > 0) { - count = (count+1) % images.length; - // console.log("rotating background to "+count); - - document.body.style.background = 'url("' + images[count] +'")'; - document.body.style.backgroundSize = "cover"; - if (images.length > 1) { - setTimeout(rotateBackground.bind(null, count), 30000); - } - } -}; -preloadBackgrounds(); -rotateBackground(); +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.shuffle=e()}(this,function(){"use strict";function t(t,e){if(A)return A.call(t,e);for(var i=t.parentNode.querySelectorAll(e),n=0;n=e?i():o=setTimeout(i,e-t)),s}}function n(){}function r(t){return parseFloat(t)||0}function s(t,e){var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:window.getComputedStyle(t,null),n=r(i[e]);return O||"width"!==e?O||"height"!==e||(n+=r(i.paddingTop)+r(i.paddingBottom)+r(i.borderTopWidth)+r(i.borderBottomWidth)):n+=r(i.paddingLeft)+r(i.paddingRight)+r(i.borderLeftWidth)+r(i.borderRightWidth),n}function o(t){for(var e=t.length;e;){e-=1;var i=Math.floor(Math.random()*(e+1)),n=t[i];t[i]=t[e],t[e]=n}return t}function a(t,e){var i=x(W,e),n=[].slice.call(t),r=!1;return t.length?i.randomize?o(t):("function"==typeof i.by&&t.sort(function(t,e){if(r)return 0;var n=i.by(t[i.key]),s=i.by(e[i.key]);return void 0===n&&void 0===s?(r=!0,0):ns||"sortLast"===n||"sortFirst"===s?1:0}),r?n:(i.reverse&&t.reverse(),t)):[]}function l(){return V+=1,P+V}function u(t){return!!q[t]&&(q[t].element.removeEventListener(P,q[t].listener),q[t]=null,!0)}function h(t,e){var i=l(),n=function(t){t.currentTarget===t.target&&(u(i),e(t))};return t.addEventListener(P,n),q[i]={element:t,listener:n},i}function f(t){return Math.max.apply(Math,t)}function c(t){return Math.min.apply(Math,t)}function d(t,e,i,n){var r=t/e;return Math.abs(Math.round(r)-r)=i-e&&t[n]<=i+e)return n;return 0}function p(t){for(var e=t.itemSize,i=t.positions,n=t.gridSize,r=t.total,s=t.threshold,o=t.buffer,a=d(e.width,n,r,s),l=g(i,a,r),u=m(l,o),h=new D(Math.round(n*u),Math.round(l[u])),f=l[u]+e.height,c=0;c-1}try{var y=new window.CustomEvent("test");if(y.preventDefault(),!0!==y.defaultPrevented)throw new Error("Could not prevent default")}catch(t){var _=function(t,e){var i,n;return e=e||{bubbles:!1,cancelable:!1,detail:void 0},i=document.createEvent("CustomEvent"),i.initCustomEvent(t,e.bubbles,e.cancelable,e.detail),n=i.preventDefault,i.preventDefault=function(){n.call(this);try{Object.defineProperty(this,"defaultPrevented",{get:function(){return!0}})}catch(t){this.defaultPrevented=!0}},i};_.prototype=window.Event.prototype,window.CustomEvent=_}var S=Element.prototype,A=S.matches||S.matchesSelector||S.webkitMatchesSelector||S.mozMatchesSelector||S.msMatchesSelector||S.oMatchesSelector,k=t,E="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},w=function(t,e){return e={exports:{}},t(e,e.exports),e.exports}(function(t){function e(t){for(var e=[],i=0;i1&&void 0!==arguments[1]?arguments[1]:{};F(this,t),this.options=x(t.options,i),this.useSizer=!1,this.lastSort={},this.group=t.ALL_ITEMS,this.lastFilter=t.ALL_ITEMS,this.isEnabled=!0,this.isDestroyed=!1,this.isInitialized=!1,this._transitions=[],this.isTransitioning=!1,this._queue=[];var n=this._getElementOption(e);if(!n)throw new TypeError("Shuffle needs to be initialized with an element.");this.element=n,this.id="shuffle_"+U,U+=1,this._init(),this.isInitialized=!0}return L(t,[{key:"_init",value:function(){this.items=this._getItems(),this.options.sizer=this._getElementOption(this.options.sizer),this.options.sizer&&(this.useSizer=!0),this.element.classList.add(t.Classes.BASE),this._initItems(),this._onResize=this._getResizeFunction(),window.addEventListener("resize",this._onResize);var e=window.getComputedStyle(this.element,null),i=t.getSize(this.element).width;this._validateStyles(e),this._setColumns(i),this.filter(this.options.group,this.options.initialSort),this.element.offsetWidth,this._setTransitions(),this.element.style.transition="height "+this.options.speed+"ms "+this.options.easing}},{key:"_getResizeFunction",value:function(){var t=this._handleResize.bind(this);return this.options.throttle?this.options.throttle(t,this.options.throttleTime):t}},{key:"_getElementOption",value:function(t){return"string"==typeof t?this.element.querySelector(t):t&&t.nodeType&&1===t.nodeType?t:t&&t.jquery?t[0]:null}},{key:"_validateStyles",value:function(t){"static"===t.position&&(this.element.style.position="relative"),"hidden"!==t.overflow&&(this.element.style.overflow="hidden")}},{key:"_filter",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.lastFilter,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.items,i=this._getFilteredSets(t,e);return this._toggleFilterClasses(i),this.lastFilter=t,"string"==typeof t&&(this.group=t),i}},{key:"_getFilteredSets",value:function(e,i){var n=this,r=[],s=[];return e===t.ALL_ITEMS?r=i:i.forEach(function(t){n._doesPassFilter(e,t.element)?r.push(t):s.push(t)}),{visible:r,hidden:s}}},{key:"_doesPassFilter",value:function(e,i){function n(t){return b(s,t)}if("function"==typeof e)return e.call(i,i,this);var r=i.getAttribute("data-"+t.FILTER_ATTRIBUTE_KEY),s=this.options.delimeter?r.split(this.options.delimeter):JSON.parse(r);return Array.isArray(e)?this.options.filterMode===t.FilterMode.ANY?e.some(n):e.every(n):b(s,e)}},{key:"_toggleFilterClasses",value:function(t){var e=t.visible,i=t.hidden;e.forEach(function(t){t.show()}),i.forEach(function(t){t.hide()})}},{key:"_initItems",value:function(){(arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.items).forEach(function(t){t.init()})}},{key:"_disposeItems",value:function(){(arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.items).forEach(function(t){t.dispose()})}},{key:"_updateItemCount",value:function(){this.visibleItems=this._getFilteredItems().length}},{key:"_setTransitions",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.items,e=this.options.speed,i=this.options.easing,n=this.options.useTransforms?"transform "+e+"ms "+i+", opacity "+e+"ms "+i:"top "+e+"ms "+i+", left "+e+"ms "+i+", opacity "+e+"ms "+i;t.forEach(function(t){t.element.style.transition=n})}},{key:"_getItems",value:function(){var t=this;return v(this.element.children).filter(function(e){return k(e,t.options.itemSelector)}).map(function(t){return new M(t)})}},{key:"_updateItemsOrder",value:function(){var t=this.element.children;this.items=a(this.items,{by:function(e){return Array.prototype.indexOf.call(t,e)}})}},{key:"_getFilteredItems",value:function(){return this.items.filter(function(t){return t.isVisible})}},{key:"_getConcealedItems",value:function(){return this.items.filter(function(t){return!t.isVisible})}},{key:"_getColumnSize",value:function(e,i){var n=void 0;return n="function"==typeof this.options.columnWidth?this.options.columnWidth(e):this.useSizer?t.getSize(this.options.sizer).width:this.options.columnWidth?this.options.columnWidth:this.items.length>0?t.getSize(this.items[0].element,!0).width:e,0===n&&(n=e),n+i}},{key:"_getGutterSize",value:function(t){return"function"==typeof this.options.gutterWidth?this.options.gutterWidth(t):this.useSizer?s(this.options.sizer,"marginLeft"):this.options.gutterWidth}},{key:"_setColumns",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:t.getSize(this.element).width,i=this._getGutterSize(e),n=this._getColumnSize(e,i),r=(e+i)/n;Math.abs(Math.round(r)-r)1&&void 0!==arguments[1]?arguments[1]:{};return!this.isDestroyed&&(e.shuffle=this,!this.element.dispatchEvent(new CustomEvent(t,{bubbles:!0,cancelable:!1,detail:e})))}},{key:"_resetCols",value:function(){var t=this.cols;for(this.positions=[];t;)t-=1,this.positions.push(0)}},{key:"_layout",value:function(e){var i=this,n=0;e.forEach(function(e){function r(){e.element.style.transitionDelay="",e.applyCss(M.Css.VISIBLE.after)}var s=e.point,o=e.scale,a=t.getSize(e.element,!0),l=i._getItemPosition(a);if(D.equals(s,l)&&o===M.Scale.VISIBLE)return e.applyCss(M.Css.VISIBLE.before),void r();e.point=l,e.scale=M.Scale.VISIBLE;var u=x(M.Css.VISIBLE.before);u.transitionDelay=i._getStaggerAmount(n)+"ms",i._queue.push({item:e,styles:u,callback:r}),n+=1})}},{key:"_getItemPosition",value:function(t){return p({itemSize:t,positions:this.positions,gridSize:this.colWidth,total:this.cols,threshold:this.options.columnThreshold,buffer:this.options.buffer})}},{key:"_shrink",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this._getConcealedItems(),i=0;e.forEach(function(e){function n(){e.applyCss(M.Css.HIDDEN.after)}if(e.scale===M.Scale.HIDDEN)return e.applyCss(M.Css.HIDDEN.before),void n();e.scale=M.Scale.HIDDEN;var r=x(M.Css.HIDDEN.before);r.transitionDelay=t._getStaggerAmount(i)+"ms",t._queue.push({item:e,styles:r,callback:n}),i+=1})}},{key:"_handleResize",value:function(){if(this.isEnabled&&!this.isDestroyed){t.getSize(this.element).width!==this.containerWidth&&this.update()}}},{key:"_getStylesForTransition",value:function(t){var e=t.item,i=t.styles;i.transitionDelay||(i.transitionDelay="0ms");var n=e.point.x,r=e.point.y;return this.options.useTransforms?i.transform="translate("+n+"px, "+r+"px) scale("+e.scale+")":(i.left=n+"px",i.top=r+"px"),i}},{key:"_whenTransitionDone",value:function(t,e,i){var n=h(t,function(t){e(),i(null,t)});this._transitions.push(n)}},{key:"_getTransitionFunction",value:function(t){var e=this;return function(i){t.item.applyCss(e._getStylesForTransition(t)),e._whenTransitionDone(t.item.element,t.callback,i)}}},{key:"_processQueue",value:function(){this.isTransitioning&&this._cancelMovement();var t=this.options.speed>0,e=this._queue.length>0;e&&t&&this.isInitialized?this._startTransitions(this._queue):e?(this._styleImmediately(this._queue),this._dispatchLayout()):this._dispatchLayout(),this._queue.length=0}},{key:"_startTransitions",value:function(t){var e=this;this.isTransitioning=!0;var i=t.map(function(t){return e._getTransitionFunction(t)});T(i,this._movementFinished.bind(this))}},{key:"_cancelMovement",value:function(){this._transitions.forEach(u),this._transitions.length=0,this.isTransitioning=!1}},{key:"_styleImmediately",value:function(e){var i=this;if(e.length){var n=e.map(function(t){return t.item.element});t._skipTransitions(n,function(){e.forEach(function(t){t.item.applyCss(i._getStylesForTransition(t)),t.callback()})})}}},{key:"_movementFinished",value:function(){this._transitions.length=0,this.isTransitioning=!1,this._dispatchLayout()}},{key:"_dispatchLayout",value:function(){this._dispatch(t.EventType.LAYOUT)}},{key:"filter",value:function(e,i){this.isEnabled&&((!e||e&&0===e.length)&&(e=t.ALL_ITEMS),this._filter(e),this._shrink(),this._updateItemCount(),this.sort(i))}},{key:"sort",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.lastSort;if(this.isEnabled){this._resetCols();var e=this._getFilteredItems();e=a(e,t),this._layout(e),this._processQueue(),this._setContainerSize(),this.lastSort=t}}},{key:"update",value:function(t){this.isEnabled&&(t||this._setColumns(),this.sort())}},{key:"layout",value:function(){this.update(!0)}},{key:"add",value:function(t){var e=w(t).map(function(t){return new M(t)});this._initItems(e),this._setTransitions(e),this.items=this.items.concat(e),this._updateItemsOrder(),this.filter(this.lastFilter)}},{key:"disable",value:function(){this.isEnabled=!1}},{key:"enable",value:function(t){this.isEnabled=!0,!1!==t&&this.update()}},{key:"remove",value:function(e){var i=this;if(e.length){var n=w(e),r=n.map(function(t){return i.getItemByElement(t)}).filter(function(t){return!!t}),s=function e(){i.element.removeEventListener(t.EventType.LAYOUT,e),i._disposeItems(r),n.forEach(function(t){t.parentNode.removeChild(t)}),i._dispatch(t.EventType.REMOVED,{collection:n})};this._toggleFilterClasses({visible:[],hidden:r}),this._shrink(r),this.sort(),this.items=this.items.filter(function(t){return!b(r,t)}),this._updateItemCount(),this.element.addEventListener(t.EventType.LAYOUT,s)}}},{key:"getItemByElement",value:function(t){for(var e=this.items.length-1;e>=0;e--)if(this.items[e].element===t)return this.items[e];return null}},{key:"destroy",value:function(){this._cancelMovement(),window.removeEventListener("resize",this._onResize),this.element.classList.remove("shuffle"),this.element.removeAttribute("style"),this._disposeItems(),this.items=null,this.options.sizer=null,this.element=null,this._transitions=null,this.isDestroyed=!0}}],[{key:"getSize",value:function(t,e){var i=window.getComputedStyle(t,null),n=s(t,"width",i),r=s(t,"height",i);if(e){var o=s(t,"marginLeft",i),a=s(t,"marginRight",i),l=s(t,"marginTop",i),u=s(t,"marginBottom",i);n+=o+a,r+=l+u}return{width:n,height:r}}},{key:"_skipTransitions",value:function(t,e){var i=t.map(function(t){var e=t.style,i=e.transitionDuration,n=e.transitionDelay;return e.transitionDuration="0ms",e.transitionDelay="0ms",{duration:i,delay:n}});e(),t[0].offsetWidth,t.forEach(function(t,e){t.style.transitionDuration=i[e].duration,t.style.transitionDelay=i[e].delay})}}]),t}();return j.ShuffleItem=M,j.ALL_ITEMS="all",j.FILTER_ATTRIBUTE_KEY="groups",j.EventType={LAYOUT:"shuffle:layout",REMOVED:"shuffle:removed"},j.Classes=z,j.FilterMode={ANY:"any",ALL:"all"},j.options={group:j.ALL_ITEMS,speed:250,easing:"ease",itemSelector:"*",sizer:null,gutterWidth:0,columnWidth:0,delimeter:null,buffer:0,columnThreshold:.01,initialSort:null,throttle:I,throttleTime:300,staggerAmount:15,staggerAmountMax:250,useTransforms:!0,filterMode:j.FilterMode.ANY},j.__Point=D,j.__sorter=a,j.__getColumnSpan=d,j.__getAvailablePositions=g,j.__getShortColumn=m,j}),function(t){function e(t,n){if(t=t||"",n=n||{},t instanceof e)return t;if(!(this instanceof e))return new e(t,n);var r=i(t);this._originalInput=t,this._r=r.r,this._g=r.g,this._b=r.b,this._a=r.a,this._roundA=W(100*this._a)/100,this._format=n.format||r.format,this._gradientType=n.gradientType,this._r<1&&(this._r=W(this._r)),this._g<1&&(this._g=W(this._g)),this._b<1&&(this._b=W(this._b)),this._ok=r.ok,this._tc_id=O++}function i(t){var e={r:0,g:0,b:0},i=1,r=null,o=null,l=null,u=!1,h=!1;return"string"==typeof t&&(t=M(t)),"object"==typeof t&&(B(t.r)&&B(t.g)&&B(t.b)?(e=n(t.r,t.g,t.b),u=!0,h="%"===String(t.r).substr(-1)?"prgb":"rgb"):B(t.h)&&B(t.s)&&B(t.v)?(r=L(t.s),o=L(t.v),e=a(t.h,r,o),u=!0,h="hsv"):B(t.h)&&B(t.s)&&B(t.l)&&(r=L(t.s),l=L(t.l),e=s(t.h,r,l),u=!0,h="hsl"),t.hasOwnProperty("a")&&(i=t.a)),i=E(i),{ok:u,format:t.format||h,r:q(255,P(e.r,0)),g:q(255,P(e.g,0)),b:q(255,P(e.b,0)),a:i}}function n(t,e,i){return{r:255*w(t,255),g:255*w(e,255),b:255*w(i,255)}}function r(t,e,i){t=w(t,255),e=w(e,255),i=w(i,255);var n,r,s=P(t,e,i),o=q(t,e,i),a=(s+o)/2;if(s==o)n=r=0;else{var l=s-o;switch(r=a>.5?l/(2-s-o):l/(s+o),s){case t:n=(e-i)/l+(e1&&(i-=1),i<1/6?t+6*(e-t)*i:i<.5?e:i<2/3?t+(e-t)*(2/3-i)*6:t}var r,s,o;if(t=w(t,360),e=w(e,100),i=w(i,100),0===e)r=s=o=i;else{var a=i<.5?i*(1+e):i+e-i*e,l=2*i-a;r=n(l,a,t+1/3),s=n(l,a,t),o=n(l,a,t-1/3)}return{r:255*r,g:255*s,b:255*o}}function o(t,e,i){t=w(t,255),e=w(e,255),i=w(i,255);var n,r,s=P(t,e,i),o=q(t,e,i),a=s,l=s-o;if(r=0===s?0:l/s,s==o)n=0;else{switch(s){case t:n=(e-i)/l+(e>1)+720)%360;--i;)r.h=(r.h+s)%360,o.push(e(r));return o}function k(t,i){i=i||6;for(var n=e(t).toHsv(),r=n.h,s=n.s,o=n.v,a=[],l=1/i;i--;)a.push(e({h:r,s:s,v:o})),o=(o+l)%1;return a}function E(t){return t=parseFloat(t),(isNaN(t)||t<0||t>1)&&(t=1),t}function w(e,i){I(e)&&(e="100%");var n=T(e);return e=q(i,P(0,parseFloat(e))),n&&(e=parseInt(e*i,10)/100),t.abs(e-i)<1e-6?1:e%i/parseFloat(i)}function x(t){return q(1,P(0,t))}function C(t){return parseInt(t,16)}function I(t){return"string"==typeof t&&-1!=t.indexOf(".")&&1===parseFloat(t)}function T(t){return"string"==typeof t&&-1!=t.indexOf("%")}function F(t){return 1==t.length?"0"+t:""+t}function L(t){return t<=1&&(t=100*t+"%"),t}function D(e){return t.round(255*parseFloat(e)).toString(16)}function z(t){return C(t)/255}function B(t){return!!Y.CSS_UNIT.exec(t)}function M(t){t=t.replace(R,"").replace(N,"").toLowerCase();var e=!1;if(U[t])t=U[t],e=!0;else if("transparent"==t)return{r:0,g:0,b:0,a:0,format:"name"};var i;return(i=Y.rgb.exec(t))?{r:i[1],g:i[2],b:i[3]}:(i=Y.rgba.exec(t))?{r:i[1],g:i[2],b:i[3],a:i[4]}:(i=Y.hsl.exec(t))?{h:i[1],s:i[2],l:i[3]}:(i=Y.hsla.exec(t))?{h:i[1],s:i[2],l:i[3],a:i[4]}:(i=Y.hsv.exec(t))?{h:i[1],s:i[2],v:i[3]}:(i=Y.hsva.exec(t))?{h:i[1],s:i[2],v:i[3],a:i[4]}:(i=Y.hex8.exec(t))?{r:C(i[1]),g:C(i[2]),b:C(i[3]),a:z(i[4]),format:e?"name":"hex8"}:(i=Y.hex6.exec(t))?{r:C(i[1]),g:C(i[2]),b:C(i[3]),format:e?"name":"hex"}:(i=Y.hex4.exec(t))?{r:C(i[1]+""+i[1]),g:C(i[2]+""+i[2]),b:C(i[3]+""+i[3]),a:z(i[4]+""+i[4]),format:e?"name":"hex8"}:!!(i=Y.hex3.exec(t))&&{r:C(i[1]+""+i[1]),g:C(i[2]+""+i[2]),b:C(i[3]+""+i[3]),format:e?"name":"hex"}}function H(t){var e,i;return t=t||{level:"AA",size:"small"},e=(t.level||"AA").toUpperCase(),i=(t.size||"small").toLowerCase(),"AA"!==e&&"AAA"!==e&&(e="AA"),"small"!==i&&"large"!==i&&(i="small"),{level:e,size:i}}var R=/^\s+/,N=/\s+$/,O=0,W=t.round,q=t.min,P=t.max,V=t.random;e.prototype={isDark:function(){return this.getBrightness()<128},isLight:function(){return!this.isDark()},isValid:function(){return this._ok},getOriginalInput:function(){return this._originalInput},getFormat:function(){return this._format},getAlpha:function(){return this._a},getBrightness:function(){var t=this.toRgb();return(299*t.r+587*t.g+114*t.b)/1e3},getLuminance:function(){var e,i,n,r,s,o,a=this.toRgb();return e=a.r/255,i=a.g/255,n=a.b/255,r=e<=.03928?e/12.92:t.pow((e+.055)/1.055,2.4),s=i<=.03928?i/12.92:t.pow((i+.055)/1.055,2.4),o=n<=.03928?n/12.92:t.pow((n+.055)/1.055,2.4),.2126*r+.7152*s+.0722*o},setAlpha:function(t){return this._a=E(t),this._roundA=W(100*this._a)/100,this},toHsv:function(){var t=o(this._r,this._g,this._b);return{h:360*t.h,s:t.s,v:t.v,a:this._a}},toHsvString:function(){var t=o(this._r,this._g,this._b),e=W(360*t.h),i=W(100*t.s),n=W(100*t.v);return 1==this._a?"hsv("+e+", "+i+"%, "+n+"%)":"hsva("+e+", "+i+"%, "+n+"%, "+this._roundA+")"},toHsl:function(){var t=r(this._r,this._g,this._b);return{h:360*t.h,s:t.s,l:t.l,a:this._a}},toHslString:function(){var t=r(this._r,this._g,this._b),e=W(360*t.h),i=W(100*t.s),n=W(100*t.l);return 1==this._a?"hsl("+e+", "+i+"%, "+n+"%)":"hsla("+e+", "+i+"%, "+n+"%, "+this._roundA+")"},toHex:function(t){return l(this._r,this._g,this._b,t)},toHexString:function(t){return"#"+this.toHex(t)},toHex8:function(t){return u(this._r,this._g,this._b,this._a,t)},toHex8String:function(t){return"#"+this.toHex8(t)},toRgb:function(){return{r:W(this._r),g:W(this._g),b:W(this._b),a:this._a}},toRgbString:function(){return 1==this._a?"rgb("+W(this._r)+", "+W(this._g)+", "+W(this._b)+")":"rgba("+W(this._r)+", "+W(this._g)+", "+W(this._b)+", "+this._roundA+")"},toPercentageRgb:function(){return{r:W(100*w(this._r,255))+"%",g:W(100*w(this._g,255))+"%",b:W(100*w(this._b,255))+"%",a:this._a}},toPercentageRgbString:function(){return 1==this._a?"rgb("+W(100*w(this._r,255))+"%, "+W(100*w(this._g,255))+"%, "+W(100*w(this._b,255))+"%)":"rgba("+W(100*w(this._r,255))+"%, "+W(100*w(this._g,255))+"%, "+W(100*w(this._b,255))+"%, "+this._roundA+")"},toName:function(){return 0===this._a?"transparent":!(this._a<1)&&(j[l(this._r,this._g,this._b,!0)]||!1)},toFilter:function(t){var i="#"+h(this._r,this._g,this._b,this._a),n=i,r=this._gradientType?"GradientType = 1, ":"";if(t){var s=e(t);n="#"+h(s._r,s._g,s._b,s._a)}return"progid:DXImageTransform.Microsoft.gradient("+r+"startColorstr="+i+",endColorstr="+n+")"},toString:function(t){var e=!!t;t=t||this._format;var i=!1,n=this._a<1&&this._a>=0;return e||!n||"hex"!==t&&"hex6"!==t&&"hex3"!==t&&"hex4"!==t&&"hex8"!==t&&"name"!==t?("rgb"===t&&(i=this.toRgbString()),"prgb"===t&&(i=this.toPercentageRgbString()),"hex"!==t&&"hex6"!==t||(i=this.toHexString()),"hex3"===t&&(i=this.toHexString(!0)),"hex4"===t&&(i=this.toHex8String(!0)),"hex8"===t&&(i=this.toHex8String()),"name"===t&&(i=this.toName()),"hsl"===t&&(i=this.toHslString()),"hsv"===t&&(i=this.toHsvString()),i||this.toHexString()):"name"===t&&0===this._a?this.toName():this.toRgbString()},clone:function(){return e(this.toString())},_applyModification:function(t,e){var i=t.apply(null,[this].concat([].slice.call(e)));return this._r=i._r,this._g=i._g,this._b=i._b,this.setAlpha(i._a),this},lighten:function(){return this._applyModification(g,arguments)},brighten:function(){return this._applyModification(m,arguments)},darken:function(){return this._applyModification(p,arguments)},desaturate:function(){return this._applyModification(f,arguments)},saturate:function(){return this._applyModification(c,arguments)},greyscale:function(){return this._applyModification(d,arguments)},spin:function(){return this._applyModification(v,arguments)},_applyCombination:function(t,e){return t.apply(null,[this].concat([].slice.call(e)))},analogous:function(){return this._applyCombination(A,arguments)},complement:function(){return this._applyCombination(b,arguments)},monochromatic:function(){return this._applyCombination(k,arguments)},splitcomplement:function(){return this._applyCombination(S,arguments)},triad:function(){return this._applyCombination(y,arguments)},tetrad:function(){return this._applyCombination(_,arguments)}},e.fromRatio=function(t,i){if("object"==typeof t){var n={};for(var r in t)t.hasOwnProperty(r)&&(n[r]="a"===r?t[r]:L(t[r]));t=n}return e(t,i)},e.equals=function(t,i){return!(!t||!i)&&e(t).toRgbString()==e(i).toRgbString()},e.random=function(){return e.fromRatio({r:V(),g:V(),b:V()})},e.mix=function(t,i,n){n=0===n?0:n||50;var r=e(t).toRgb(),s=e(i).toRgb(),o=n/100;return e({r:(s.r-r.r)*o+r.r,g:(s.g-r.g)*o+r.g,b:(s.b-r.b)*o+r.b,a:(s.a-r.a)*o+r.a})},e.readability=function(i,n){var r=e(i),s=e(n);return(t.max(r.getLuminance(),s.getLuminance())+.05)/(t.min(r.getLuminance(),s.getLuminance())+.05)},e.isReadable=function(t,i,n){var r,s,o=e.readability(t,i);switch(s=!1,r=H(n),r.level+r.size){case"AAsmall":case"AAAlarge":s=o>=4.5;break;case"AAlarge":s=o>=3;break;case"AAAsmall":s=o>=7}return s},e.mostReadable=function(t,i,n){var r,s,o,a,l=null,u=0;n=n||{},s=n.includeFallbackColors,o=n.level,a=n.size;for(var h=0;hu&&(u=r,l=e(i[h]));return e.isReadable(t,l,{level:o,size:a})||!s?l:(n.includeFallbackColors=!1,e.mostReadable(t,["#fff","#000"],n))};var U=e.names={aliceblue:"f0f8ff",antiquewhite:"faebd7",aqua:"0ff",aquamarine:"7fffd4",azure:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"000",blanchedalmond:"ffebcd",blue:"00f",blueviolet:"8a2be2",brown:"a52a2a",burlywood:"deb887",burntsienna:"ea7e5d",cadetblue:"5f9ea0",chartreuse:"7fff00",chocolate:"d2691e",coral:"ff7f50",cornflowerblue:"6495ed",cornsilk:"fff8dc",crimson:"dc143c",cyan:"0ff",darkblue:"00008b",darkcyan:"008b8b",darkgoldenrod:"b8860b",darkgray:"a9a9a9",darkgreen:"006400",darkgrey:"a9a9a9",darkkhaki:"bdb76b",darkmagenta:"8b008b",darkolivegreen:"556b2f",darkorange:"ff8c00",darkorchid:"9932cc",darkred:"8b0000",darksalmon:"e9967a",darkseagreen:"8fbc8f",darkslateblue:"483d8b",darkslategray:"2f4f4f",darkslategrey:"2f4f4f",darkturquoise:"00ced1",darkviolet:"9400d3",deeppink:"ff1493",deepskyblue:"00bfff",dimgray:"696969",dimgrey:"696969",dodgerblue:"1e90ff",firebrick:"b22222",floralwhite:"fffaf0",forestgreen:"228b22",fuchsia:"f0f",gainsboro:"dcdcdc",ghostwhite:"f8f8ff",gold:"ffd700",goldenrod:"daa520",gray:"808080",green:"008000",greenyellow:"adff2f",grey:"808080",honeydew:"f0fff0",hotpink:"ff69b4",indianred:"cd5c5c",indigo:"4b0082",ivory:"fffff0",khaki:"f0e68c",lavender:"e6e6fa",lavenderblush:"fff0f5",lawngreen:"7cfc00",lemonchiffon:"fffacd",lightblue:"add8e6",lightcoral:"f08080",lightcyan:"e0ffff",lightgoldenrodyellow:"fafad2",lightgray:"d3d3d3",lightgreen:"90ee90",lightgrey:"d3d3d3",lightpink:"ffb6c1",lightsalmon:"ffa07a",lightseagreen:"20b2aa",lightskyblue:"87cefa",lightslategray:"789",lightslategrey:"789",lightsteelblue:"b0c4de",lightyellow:"ffffe0",lime:"0f0",limegreen:"32cd32",linen:"faf0e6",magenta:"f0f",maroon:"800000",mediumaquamarine:"66cdaa",mediumblue:"0000cd",mediumorchid:"ba55d3",mediumpurple:"9370db",mediumseagreen:"3cb371",mediumslateblue:"7b68ee",mediumspringgreen:"00fa9a",mediumturquoise:"48d1cc",mediumvioletred:"c71585",midnightblue:"191970",mintcream:"f5fffa",mistyrose:"ffe4e1",moccasin:"ffe4b5",navajowhite:"ffdead",navy:"000080",oldlace:"fdf5e6",olive:"808000",olivedrab:"6b8e23",orange:"ffa500",orangered:"ff4500",orchid:"da70d6",palegoldenrod:"eee8aa",palegreen:"98fb98",paleturquoise:"afeeee",palevioletred:"db7093",papayawhip:"ffefd5",peachpuff:"ffdab9",peru:"cd853f",pink:"ffc0cb",plum:"dda0dd",powderblue:"b0e0e6",purple:"800080",rebeccapurple:"663399",red:"f00",rosybrown:"bc8f8f",royalblue:"4169e1",saddlebrown:"8b4513",salmon:"fa8072",sandybrown:"f4a460",seagreen:"2e8b57",seashell:"fff5ee",sienna:"a0522d",silver:"c0c0c0",skyblue:"87ceeb",slateblue:"6a5acd",slategray:"708090",slategrey:"708090",snow:"fffafa",springgreen:"00ff7f",steelblue:"4682b4",tan:"d2b48c",teal:"008080",thistle:"d8bfd8",tomato:"ff6347",turquoise:"40e0d0",violet:"ee82ee",wheat:"f5deb3",white:"fff",whitesmoke:"f5f5f5",yellow:"ff0",yellowgreen:"9acd32"},j=e.hexNames=function(t){var e={};for(var i in t)t.hasOwnProperty(i)&&(e[t[i]]=i);return e}(U),Y=function(){var t="(?:[-\\+]?\\d*\\.\\d+%?)|(?:[-\\+]?\\d+%?)",e="[\\s|\\(]+("+t+")[,|\\s]+("+t+")[,|\\s]+("+t+")\\s*\\)?",i="[\\s|\\(]+("+t+")[,|\\s]+("+t+")[,|\\s]+("+t+")[,|\\s]+("+t+")\\s*\\)?";return{CSS_UNIT:new RegExp(t),rgb:new RegExp("rgb"+e),rgba:new RegExp("rgba"+i),hsl:new RegExp("hsl"+e),hsla:new RegExp("hsla"+i),hsv:new RegExp("hsv"+e),hsva:new RegExp("hsva"+i),hex3:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex6:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,hex4:/^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,hex8:/^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/}}();"undefined"!=typeof module&&module.exports?module.exports=e:"function"==typeof define&&define.amd?define(function(){return e +}):window.tinycolor=e}(Math),String.prototype.hashCode=function(){var t=5381;for(i=0;i>>0};var Color=tinycolor,Shuffle=window.shuffle,shuffle=new Shuffle(document.querySelector(".tile-container"),{group:shuffle.ALL_ITEMS,itemSelector:".tile",gutterWidth:16,columnWidth:188,buffer:1,delimeter:",",useTransforms:!1}),filterTiles=function(t){shuffle.filter(location.hash.slice(1))};window.onhashchange=filterTiles;var getUrlParts=function(t){var e={domain:"",before:"",after:""},i=new URL(t),n=i.host;if(e.domain=n.replace(/^www\./i,""),n.match(/^\d+\.\d+\.\d+\.\d+$/))return e.domain=n,e;if(n.match(/^(\d+\.\d+\.\d+\.\d+)(:(\d+))?$/))return r=n.match(/^(\d+\.\d+\.\d+\.\d+)(:(\d+))?$/),e.domain=r[1],e.after=r[3],e;for(var r=e.domain.split("."),s=0,o=1;or[s].length&&(s=o);return e.domain=r[s],e.before=r.slice(0,s).join("."),e.after=r.slice(s+1).join("."),!e.domain&&i.pathname&&(e.domain=i.pathname.split("/").filter(Boolean).pop()),e},fitText=function(t,e,i){var n=document.createElement("div");n.style.visibility="hidden",n.style.position="absolute",document.body.appendChild(n);var r=40;for(n.innerHTML=t,n.style.fontSize=r;n.offsetWidth>e;)r-=1,n.style.fontSize=r;var s={size:r,width:n.offsetWidth,height:n.offsetHeight};return n.remove(),s},getTileColor=function(t){var e=["#B42424","#C83D1D","#BB7231","#E06B00","#55931F","#1C941B","#189365","#189196","#2D85A4","#2B6C90","#205396","#39448F","#55338E","#683089","#963A97","#A43343","#982F2F","#D30000","#E54C29","#DA7E2C","#73B43A","#3AB43A","#3AB487","#3AB0B4","#47A6C7","#3A88B4","#3A6FB4","#3A4AB4","#673AB4","#863AB4","#C846C9","#C44A5B","#AA4444","#E84545","#FF6946","#EC9344","#3CA4DF","#3A83E3","#4056E3","#9058F0","#B467E2","#DF7CDF","#E5576B","#D35A5A","#3DC53D","#2DBBB1","#5E95D5","#5E5BE7","#1B7EFF","#5F74FF","#8A45FF","#B856F3","#DD66DD"];return e[t.hashCode()%e.length]},renderImgTile=function(t){t.innerHTML="";var e=t.getAttribute("data-bg-color");e||(e="rgba(255,255,255,.8)"),e=Color(e),e.setAlpha(.8),t.style.backgroundColor=e;var i=new Image;i.src=t.getAttribute("data-img"),i.className="logo",t.appendChild(i)},renderPlainTile=function(t){var e=getUrlParts(t.getAttribute("data-url"));t.innerHTML="";var i=t.getAttribute("data-bg-color");i||(i="rgba(255,255,255,.8)"),i=Color(i),i.setAlpha(.8),t.style.backgroundColor=i;var n=t.getAttribute("data-txt-color");n||(n=getTileColor(e.domain),i.isDark()&&(t.style.color="white")),n=Color(n),t.style.color=n;var r=fitText(e.domain,172,120),s=document.createElement("div");s.style.fontSize=r.size,s.style.position="absolute",t.appendChild(s);var o=document.createElement("div");o.innerHTML=e.before,o.style.top=.35*r.size-10,o.className="pre-domain",o.style.textShadow="-1px 0 "+i+",0 1px "+i+",1px 0 "+i+",0 -1px "+i;var a=document.createElement("div");a.innerHTML=e.after,a.style.top=r.size-.05*r.size,a.className="post-domain",a.style.textShadow="-1px 0 "+i+",0 1px "+i+",1px 0 "+i+",0 -1px "+i,s.appendChild(o),s.append(e.domain),s.appendChild(a);var l=64-s.clientHeight/2,u=106-s.clientWidth/2;s.style.top=l,s.style.left=u},renderTiles=function(){for(var t=document.getElementsByClassName("tile-box"),e=0;e0&&(t=(t+1)%e.length,document.body.style.background='url("'+e[t]+'")',document.body.style.backgroundSize="cover",e.length>1&&setTimeout(rotateBackground.bind(null,t),3e4))};preloadBackgrounds(),rotateBackground(); \ No newline at end of file