| Current Path : /home/rtorresani/www/pub/static/frontend/Magento/economiasolidale/it_IT/js/bundle/ |
| Current File : //home/rtorresani/www/pub/static/frontend/Magento/economiasolidale/it_IT/js/bundle/bundle2.js |
require.config({"config": {
"jsbuild":{"knockoutjs/knockout.js":"/*!\n * Knockout JavaScript library v3.5.1\n * (c) The Knockout.js team - http://knockoutjs.com/\n * License: MIT (http://www.opensource.org/licenses/mit-license.php)\n */\n\n(function(){\n var DEBUG=true;\n (function(undefined){\n // (0, eval)('this') is a robust way of getting a reference to the global object\n // For details, see http://stackoverflow.com/questions/14119988/return-this-0-evalthis/14120023#14120023\n var window = this || (0, eval)('this'),\n document = window['document'],\n navigator = window['navigator'],\n jQueryInstance = window[\"jQuery\"],\n JSON = window[\"JSON\"];\n\n if (!jQueryInstance && typeof jQuery !== \"undefined\") {\n jQueryInstance = jQuery;\n }\n (function(factory) {\n // Support three module loading scenarios\n if (typeof define === 'function' && define['amd']) {\n // [1] AMD anonymous module\n define(['exports', 'require'], factory);\n } else if (typeof exports === 'object' && typeof module === 'object') {\n // [2] CommonJS/Node.js\n factory(module['exports'] || exports); // module.exports is for Node.js\n } else {\n // [3] No module loader (plain <script> tag) - put directly in global namespace\n factory(window['ko'] = {});\n }\n }(function(koExports, amdRequire){\n// Internally, all KO objects are attached to koExports (even the non-exported ones whose names will be minified by the closure compiler).\n// In the future, the following \"ko\" variable may be made distinct from \"koExports\" so that private objects are not externally reachable.\n var ko = typeof koExports !== 'undefined' ? koExports : {};\n// Google Closure Compiler helpers (used only to make the minified file smaller)\n ko.exportSymbol = function(koPath, object) {\n var tokens = koPath.split(\".\");\n\n // In the future, \"ko\" may become distinct from \"koExports\" (so that non-exported objects are not reachable)\n // At that point, \"target\" would be set to: (typeof koExports !== \"undefined\" ? koExports : ko)\n var target = ko;\n\n for (var i = 0; i < tokens.length - 1; i++)\n target = target[tokens[i]];\n target[tokens[tokens.length - 1]] = object;\n };\n ko.exportProperty = function(owner, publicName, object) {\n owner[publicName] = object;\n };\n ko.version = \"3.5.1\";\n\n ko.exportSymbol('version', ko.version);\n// For any options that may affect various areas of Knockout and aren't directly associated with data binding.\n ko.options = {\n 'deferUpdates': false,\n 'useOnlyNativeEvents': false,\n 'foreachHidesDestroyed': false\n };\n\n//ko.exportSymbol('options', ko.options); // 'options' isn't minified\n ko.utils = (function () {\n var hasOwnProperty = Object.prototype.hasOwnProperty;\n\n function objectForEach(obj, action) {\n for (var prop in obj) {\n if (hasOwnProperty.call(obj, prop)) {\n action(prop, obj[prop]);\n }\n }\n }\n\n function extend(target, source) {\n if (source) {\n for(var prop in source) {\n if(hasOwnProperty.call(source, prop)) {\n target[prop] = source[prop];\n }\n }\n }\n return target;\n }\n\n function setPrototypeOf(obj, proto) {\n obj.__proto__ = proto;\n return obj;\n }\n\n var canSetPrototype = ({ __proto__: [] } instanceof Array);\n var canUseSymbols = !DEBUG && typeof Symbol === 'function';\n\n // Represent the known event types in a compact way, then at runtime transform it into a hash with event name as key (for fast lookup)\n var knownEvents = {}, knownEventTypesByEventName = {};\n var keyEventTypeName = (navigator && /Firefox\\/2/i.test(navigator.userAgent)) ? 'KeyboardEvent' : 'UIEvents';\n knownEvents[keyEventTypeName] = ['keyup', 'keydown', 'keypress'];\n knownEvents['MouseEvents'] = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave'];\n objectForEach(knownEvents, function(eventType, knownEventsForType) {\n if (knownEventsForType.length) {\n for (var i = 0, j = knownEventsForType.length; i < j; i++)\n knownEventTypesByEventName[knownEventsForType[i]] = eventType;\n }\n });\n var eventsThatMustBeRegisteredUsingAttachEvent = { 'propertychange': true }; // Workaround for an IE9 issue - https://github.com/SteveSanderson/knockout/issues/406\n\n // Detect IE versions for bug workarounds (uses IE conditionals, not UA string, for robustness)\n // Note that, since IE 10 does not support conditional comments, the following logic only detects IE < 10.\n // Currently this is by design, since IE 10+ behaves correctly when treated as a standard browser.\n // If there is a future need to detect specific versions of IE10+, we will amend this.\n var ieVersion = document && (function() {\n var version = 3, div = document.createElement('div'), iElems = div.getElementsByTagName('i');\n\n // Keep constructing conditional HTML blocks until we hit one that resolves to an empty fragment\n while (\n div.innerHTML = '<!--[if gt IE ' + (++version) + ']><i></i><![endif]-->',\n iElems[0]\n ) {}\n return version > 4 ? version : undefined;\n }());\n var isIe6 = ieVersion === 6,\n isIe7 = ieVersion === 7;\n\n function isClickOnCheckableElement(element, eventType) {\n if ((ko.utils.tagNameLower(element) !== \"input\") || !element.type) return false;\n if (eventType.toLowerCase() != \"click\") return false;\n var inputType = element.type;\n return (inputType == \"checkbox\") || (inputType == \"radio\");\n }\n\n // For details on the pattern for changing node classes\n // see: https://github.com/knockout/knockout/issues/1597\n var cssClassNameRegex = /\\S+/g;\n\n var jQueryEventAttachName;\n\n function toggleDomNodeCssClass(node, classNames, shouldHaveClass) {\n var addOrRemoveFn;\n if (classNames) {\n if (typeof node.classList === 'object') {\n addOrRemoveFn = node.classList[shouldHaveClass ? 'add' : 'remove'];\n ko.utils.arrayForEach(classNames.match(cssClassNameRegex), function(className) {\n addOrRemoveFn.call(node.classList, className);\n });\n } else if (typeof node.className['baseVal'] === 'string') {\n // SVG tag .classNames is an SVGAnimatedString instance\n toggleObjectClassPropertyString(node.className, 'baseVal', classNames, shouldHaveClass);\n } else {\n // node.className ought to be a string.\n toggleObjectClassPropertyString(node, 'className', classNames, shouldHaveClass);\n }\n }\n }\n\n function toggleObjectClassPropertyString(obj, prop, classNames, shouldHaveClass) {\n // obj/prop is either a node/'className' or a SVGAnimatedString/'baseVal'.\n var currentClassNames = obj[prop].match(cssClassNameRegex) || [];\n ko.utils.arrayForEach(classNames.match(cssClassNameRegex), function(className) {\n ko.utils.addOrRemoveItem(currentClassNames, className, shouldHaveClass);\n });\n obj[prop] = currentClassNames.join(\" \");\n }\n\n return {\n fieldsIncludedWithJsonPost: ['authenticity_token', /^__RequestVerificationToken(_.*)?$/],\n\n arrayForEach: function (array, action, actionOwner) {\n for (var i = 0, j = array.length; i < j; i++) {\n action.call(actionOwner, array[i], i, array);\n }\n },\n\n arrayIndexOf: typeof Array.prototype.indexOf == \"function\"\n ? function (array, item) {\n return Array.prototype.indexOf.call(array, item);\n }\n : function (array, item) {\n for (var i = 0, j = array.length; i < j; i++) {\n if (array[i] === item)\n return i;\n }\n return -1;\n },\n\n arrayFirst: function (array, predicate, predicateOwner) {\n for (var i = 0, j = array.length; i < j; i++) {\n if (predicate.call(predicateOwner, array[i], i, array))\n return array[i];\n }\n return undefined;\n },\n\n arrayRemoveItem: function (array, itemToRemove) {\n var index = ko.utils.arrayIndexOf(array, itemToRemove);\n if (index > 0) {\n array.splice(index, 1);\n }\n else if (index === 0) {\n array.shift();\n }\n },\n\n arrayGetDistinctValues: function (array) {\n var result = [];\n if (array) {\n ko.utils.arrayForEach(array, function(item) {\n if (ko.utils.arrayIndexOf(result, item) < 0)\n result.push(item);\n });\n }\n return result;\n },\n\n arrayMap: function (array, mapping, mappingOwner) {\n var result = [];\n if (array) {\n for (var i = 0, j = array.length; i < j; i++)\n result.push(mapping.call(mappingOwner, array[i], i));\n }\n return result;\n },\n\n arrayFilter: function (array, predicate, predicateOwner) {\n var result = [];\n if (array) {\n for (var i = 0, j = array.length; i < j; i++)\n if (predicate.call(predicateOwner, array[i], i))\n result.push(array[i]);\n }\n return result;\n },\n\n arrayPushAll: function (array, valuesToPush) {\n if (valuesToPush instanceof Array)\n array.push.apply(array, valuesToPush);\n else\n for (var i = 0, j = valuesToPush.length; i < j; i++)\n array.push(valuesToPush[i]);\n return array;\n },\n\n addOrRemoveItem: function(array, value, included) {\n var existingEntryIndex = ko.utils.arrayIndexOf(ko.utils.peekObservable(array), value);\n if (existingEntryIndex < 0) {\n if (included)\n array.push(value);\n } else {\n if (!included)\n array.splice(existingEntryIndex, 1);\n }\n },\n\n canSetPrototype: canSetPrototype,\n\n extend: extend,\n\n setPrototypeOf: setPrototypeOf,\n\n setPrototypeOfOrExtend: canSetPrototype ? setPrototypeOf : extend,\n\n objectForEach: objectForEach,\n\n objectMap: function(source, mapping, mappingOwner) {\n if (!source)\n return source;\n var target = {};\n for (var prop in source) {\n if (hasOwnProperty.call(source, prop)) {\n target[prop] = mapping.call(mappingOwner, source[prop], prop, source);\n }\n }\n return target;\n },\n\n emptyDomNode: function (domNode) {\n while (domNode.firstChild) {\n ko.removeNode(domNode.firstChild);\n }\n },\n\n moveCleanedNodesToContainerElement: function(nodes) {\n // Ensure it's a real array, as we're about to reparent the nodes and\n // we don't want the underlying collection to change while we're doing that.\n var nodesArray = ko.utils.makeArray(nodes);\n var templateDocument = (nodesArray[0] && nodesArray[0].ownerDocument) || document;\n\n var container = templateDocument.createElement('div');\n for (var i = 0, j = nodesArray.length; i < j; i++) {\n container.appendChild(ko.cleanNode(nodesArray[i]));\n }\n return container;\n },\n\n cloneNodes: function (nodesArray, shouldCleanNodes) {\n for (var i = 0, j = nodesArray.length, newNodesArray = []; i < j; i++) {\n var clonedNode = nodesArray[i].cloneNode(true);\n newNodesArray.push(shouldCleanNodes ? ko.cleanNode(clonedNode) : clonedNode);\n }\n return newNodesArray;\n },\n\n setDomNodeChildren: function (domNode, childNodes) {\n ko.utils.emptyDomNode(domNode);\n if (childNodes) {\n for (var i = 0, j = childNodes.length; i < j; i++)\n domNode.appendChild(childNodes[i]);\n }\n },\n\n replaceDomNodes: function (nodeToReplaceOrNodeArray, newNodesArray) {\n var nodesToReplaceArray = nodeToReplaceOrNodeArray.nodeType ? [nodeToReplaceOrNodeArray] : nodeToReplaceOrNodeArray;\n if (nodesToReplaceArray.length > 0) {\n var insertionPoint = nodesToReplaceArray[0];\n var parent = insertionPoint.parentNode;\n for (var i = 0, j = newNodesArray.length; i < j; i++)\n parent.insertBefore(newNodesArray[i], insertionPoint);\n for (var i = 0, j = nodesToReplaceArray.length; i < j; i++) {\n ko.removeNode(nodesToReplaceArray[i]);\n }\n }\n },\n\n fixUpContinuousNodeArray: function(continuousNodeArray, parentNode) {\n // Before acting on a set of nodes that were previously outputted by a template function, we have to reconcile\n // them against what is in the DOM right now. It may be that some of the nodes have already been removed, or that\n // new nodes might have been inserted in the middle, for example by a binding. Also, there may previously have been\n // leading comment nodes (created by rewritten string-based templates) that have since been removed during binding.\n // So, this function translates the old \"map\" output array into its best guess of the set of current DOM nodes.\n //\n // Rules:\n // [A] Any leading nodes that have been removed should be ignored\n // These most likely correspond to memoization nodes that were already removed during binding\n // See https://github.com/knockout/knockout/pull/440\n // [B] Any trailing nodes that have been remove should be ignored\n // This prevents the code here from adding unrelated nodes to the array while processing rule [C]\n // See https://github.com/knockout/knockout/pull/1903\n // [C] We want to output a continuous series of nodes. So, ignore any nodes that have already been removed,\n // and include any nodes that have been inserted among the previous collection\n\n if (continuousNodeArray.length) {\n // The parent node can be a virtual element; so get the real parent node\n parentNode = (parentNode.nodeType === 8 && parentNode.parentNode) || parentNode;\n\n // Rule [A]\n while (continuousNodeArray.length && continuousNodeArray[0].parentNode !== parentNode)\n continuousNodeArray.splice(0, 1);\n\n // Rule [B]\n while (continuousNodeArray.length > 1 && continuousNodeArray[continuousNodeArray.length - 1].parentNode !== parentNode)\n continuousNodeArray.length--;\n\n // Rule [C]\n if (continuousNodeArray.length > 1) {\n var current = continuousNodeArray[0], last = continuousNodeArray[continuousNodeArray.length - 1];\n // Replace with the actual new continuous node set\n continuousNodeArray.length = 0;\n while (current !== last) {\n continuousNodeArray.push(current);\n current = current.nextSibling;\n }\n continuousNodeArray.push(last);\n }\n }\n return continuousNodeArray;\n },\n\n setOptionNodeSelectionState: function (optionNode, isSelected) {\n // IE6 sometimes throws \"unknown error\" if you try to write to .selected directly, whereas Firefox struggles with setAttribute. Pick one based on browser.\n if (ieVersion < 7)\n optionNode.setAttribute(\"selected\", isSelected);\n else\n optionNode.selected = isSelected;\n },\n\n stringTrim: function (string) {\n return string === null || string === undefined ? '' :\n string.trim ?\n string.trim() :\n string.toString().replace(/^[\\s\\xa0]+|[\\s\\xa0]+$/g, '');\n },\n\n stringStartsWith: function (string, startsWith) {\n string = string || \"\";\n if (startsWith.length > string.length)\n return false;\n return string.substring(0, startsWith.length) === startsWith;\n },\n\n domNodeIsContainedBy: function (node, containedByNode) {\n if (node === containedByNode)\n return true;\n if (node.nodeType === 11)\n return false; // Fixes issue #1162 - can't use node.contains for document fragments on IE8\n if (containedByNode.contains)\n return containedByNode.contains(node.nodeType !== 1 ? node.parentNode : node);\n if (containedByNode.compareDocumentPosition)\n return (containedByNode.compareDocumentPosition(node) & 16) == 16;\n while (node && node != containedByNode) {\n node = node.parentNode;\n }\n return !!node;\n },\n\n domNodeIsAttachedToDocument: function (node) {\n return ko.utils.domNodeIsContainedBy(node, node.ownerDocument.documentElement);\n },\n\n anyDomNodeIsAttachedToDocument: function(nodes) {\n return !!ko.utils.arrayFirst(nodes, ko.utils.domNodeIsAttachedToDocument);\n },\n\n tagNameLower: function(element) {\n // For HTML elements, tagName will always be upper case; for XHTML elements, it'll be lower case.\n // Possible future optimization: If we know it's an element from an XHTML document (not HTML),\n // we don't need to do the .toLowerCase() as it will always be lower case anyway.\n return element && element.tagName && element.tagName.toLowerCase();\n },\n\n catchFunctionErrors: function (delegate) {\n return ko['onError'] ? function () {\n try {\n return delegate.apply(this, arguments);\n } catch (e) {\n ko['onError'] && ko['onError'](e);\n throw e;\n }\n } : delegate;\n },\n\n setTimeout: function (handler, timeout) {\n return setTimeout(ko.utils.catchFunctionErrors(handler), timeout);\n },\n\n deferError: function (error) {\n setTimeout(function () {\n ko['onError'] && ko['onError'](error);\n throw error;\n }, 0);\n },\n\n registerEventHandler: function (element, eventType, handler) {\n var wrappedHandler = ko.utils.catchFunctionErrors(handler);\n\n var mustUseAttachEvent = eventsThatMustBeRegisteredUsingAttachEvent[eventType];\n if (!ko.options['useOnlyNativeEvents'] && !mustUseAttachEvent && jQueryInstance) {\n if (!jQueryEventAttachName) {\n jQueryEventAttachName = (typeof jQueryInstance(element)['on'] == 'function') ? 'on' : 'bind';\n }\n jQueryInstance(element)[jQueryEventAttachName](eventType, wrappedHandler);\n } else if (!mustUseAttachEvent && typeof element.addEventListener == \"function\")\n element.addEventListener(eventType, wrappedHandler, false);\n else if (typeof element.attachEvent != \"undefined\") {\n var attachEventHandler = function (event) { wrappedHandler.call(element, event); },\n attachEventName = \"on\" + eventType;\n element.attachEvent(attachEventName, attachEventHandler);\n\n // IE does not dispose attachEvent handlers automatically (unlike with addEventListener)\n // so to avoid leaks, we have to remove them manually. See bug #856\n ko.utils.domNodeDisposal.addDisposeCallback(element, function() {\n element.detachEvent(attachEventName, attachEventHandler);\n });\n } else\n throw new Error(\"Browser doesn't support addEventListener or attachEvent\");\n },\n\n triggerEvent: function (element, eventType) {\n if (!(element && element.nodeType))\n throw new Error(\"element must be a DOM node when calling triggerEvent\");\n\n // For click events on checkboxes and radio buttons, jQuery toggles the element checked state *after* the\n // event handler runs instead of *before*. (This was fixed in 1.9 for checkboxes but not for radio buttons.)\n // IE doesn't change the checked state when you trigger the click event using \"fireEvent\".\n // In both cases, we'll use the click method instead.\n var useClickWorkaround = isClickOnCheckableElement(element, eventType);\n\n if (!ko.options['useOnlyNativeEvents'] && jQueryInstance && !useClickWorkaround) {\n jQueryInstance(element)['trigger'](eventType);\n } else if (typeof document.createEvent == \"function\") {\n if (typeof element.dispatchEvent == \"function\") {\n var eventCategory = knownEventTypesByEventName[eventType] || \"HTMLEvents\";\n var event = document.createEvent(eventCategory);\n event.initEvent(eventType, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);\n element.dispatchEvent(event);\n }\n else\n throw new Error(\"The supplied element doesn't support dispatchEvent\");\n } else if (useClickWorkaround && element.click) {\n element.click();\n } else if (typeof element.fireEvent != \"undefined\") {\n element.fireEvent(\"on\" + eventType);\n } else {\n throw new Error(\"Browser doesn't support triggering events\");\n }\n },\n\n unwrapObservable: function (value) {\n return ko.isObservable(value) ? value() : value;\n },\n\n peekObservable: function (value) {\n return ko.isObservable(value) ? value.peek() : value;\n },\n\n toggleDomNodeCssClass: toggleDomNodeCssClass,\n\n setTextContent: function(element, textContent) {\n var value = ko.utils.unwrapObservable(textContent);\n if ((value === null) || (value === undefined))\n value = \"\";\n\n // We need there to be exactly one child: a text node.\n // If there are no children, more than one, or if it's not a text node,\n // we'll clear everything and create a single text node.\n var innerTextNode = ko.virtualElements.firstChild(element);\n if (!innerTextNode || innerTextNode.nodeType != 3 || ko.virtualElements.nextSibling(innerTextNode)) {\n ko.virtualElements.setDomNodeChildren(element, [element.ownerDocument.createTextNode(value)]);\n } else {\n innerTextNode.data = value;\n }\n\n ko.utils.forceRefresh(element);\n },\n\n setElementName: function(element, name) {\n element.name = name;\n\n // Workaround IE 6/7 issue\n // - https://github.com/SteveSanderson/knockout/issues/197\n // - http://www.matts411.com/post/setting_the_name_attribute_in_ie_dom/\n if (ieVersion <= 7) {\n try {\n var escapedName = element.name.replace(/[&<>'\"]/g, function(r){ return \"&#\" + r.charCodeAt(0) + \";\"; });\n element.mergeAttributes(document.createElement(\"<input name='\" + escapedName + \"'/>\"), false);\n }\n catch(e) {} // For IE9 with doc mode \"IE9 Standards\" and browser mode \"IE9 Compatibility View\"\n }\n },\n\n forceRefresh: function(node) {\n // Workaround for an IE9 rendering bug - https://github.com/SteveSanderson/knockout/issues/209\n if (ieVersion >= 9) {\n // For text nodes and comment nodes (most likely virtual elements), we will have to refresh the container\n var elem = node.nodeType == 1 ? node : node.parentNode;\n if (elem.style)\n elem.style.zoom = elem.style.zoom;\n }\n },\n\n ensureSelectElementIsRenderedCorrectly: function(selectElement) {\n // Workaround for IE9 rendering bug - it doesn't reliably display all the text in dynamically-added select boxes unless you force it to re-render by updating the width.\n // (See https://github.com/SteveSanderson/knockout/issues/312, http://stackoverflow.com/questions/5908494/select-only-shows-first-char-of-selected-option)\n // Also fixes IE7 and IE8 bug that causes selects to be zero width if enclosed by 'if' or 'with'. (See issue #839)\n if (ieVersion) {\n var originalWidth = selectElement.style.width;\n selectElement.style.width = 0;\n selectElement.style.width = originalWidth;\n }\n },\n\n range: function (min, max) {\n min = ko.utils.unwrapObservable(min);\n max = ko.utils.unwrapObservable(max);\n var result = [];\n for (var i = min; i <= max; i++)\n result.push(i);\n return result;\n },\n\n makeArray: function(arrayLikeObject) {\n var result = [];\n for (var i = 0, j = arrayLikeObject.length; i < j; i++) {\n result.push(arrayLikeObject[i]);\n };\n return result;\n },\n\n createSymbolOrString: function(identifier) {\n return canUseSymbols ? Symbol(identifier) : identifier;\n },\n\n isIe6 : isIe6,\n isIe7 : isIe7,\n ieVersion : ieVersion,\n\n getFormFields: function(form, fieldName) {\n var fields = ko.utils.makeArray(form.getElementsByTagName(\"input\")).concat(ko.utils.makeArray(form.getElementsByTagName(\"textarea\")));\n var isMatchingField = (typeof fieldName == 'string')\n ? function(field) { return field.name === fieldName }\n : function(field) { return fieldName.test(field.name) }; // Treat fieldName as regex or object containing predicate\n var matches = [];\n for (var i = fields.length - 1; i >= 0; i--) {\n if (isMatchingField(fields[i]))\n matches.push(fields[i]);\n };\n return matches;\n },\n\n parseJson: function (jsonString) {\n if (typeof jsonString == \"string\") {\n jsonString = ko.utils.stringTrim(jsonString);\n if (jsonString) {\n if (JSON && JSON.parse) // Use native parsing where available\n return JSON.parse(jsonString);\n return (new Function(\"return \" + jsonString))(); // Fallback on less safe parsing for older browsers\n }\n }\n return null;\n },\n\n stringifyJson: function (data, replacer, space) { // replacer and space are optional\n if (!JSON || !JSON.stringify)\n throw new Error(\"Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js\");\n return JSON.stringify(ko.utils.unwrapObservable(data), replacer, space);\n },\n\n postJson: function (urlOrForm, data, options) {\n options = options || {};\n var params = options['params'] || {};\n var includeFields = options['includeFields'] || this.fieldsIncludedWithJsonPost;\n var url = urlOrForm;\n\n // If we were given a form, use its 'action' URL and pick out any requested field values\n if((typeof urlOrForm == 'object') && (ko.utils.tagNameLower(urlOrForm) === \"form\")) {\n var originalForm = urlOrForm;\n url = originalForm.action;\n for (var i = includeFields.length - 1; i >= 0; i--) {\n var fields = ko.utils.getFormFields(originalForm, includeFields[i]);\n for (var j = fields.length - 1; j >= 0; j--)\n params[fields[j].name] = fields[j].value;\n }\n }\n\n data = ko.utils.unwrapObservable(data);\n var form = document.createElement(\"form\");\n form.style.display = \"none\";\n form.action = url;\n form.method = \"post\";\n for (var key in data) {\n // Since 'data' this is a model object, we include all properties including those inherited from its prototype\n var input = document.createElement(\"input\");\n input.type = \"hidden\";\n input.name = key;\n input.value = ko.utils.stringifyJson(ko.utils.unwrapObservable(data[key]));\n form.appendChild(input);\n }\n objectForEach(params, function(key, value) {\n var input = document.createElement(\"input\");\n input.type = \"hidden\";\n input.name = key;\n input.value = value;\n form.appendChild(input);\n });\n document.body.appendChild(form);\n options['submitter'] ? options['submitter'](form) : form.submit();\n setTimeout(function () { form.parentNode.removeChild(form); }, 0);\n }\n }\n }());\n\n ko.exportSymbol('utils', ko.utils);\n ko.exportSymbol('utils.arrayForEach', ko.utils.arrayForEach);\n ko.exportSymbol('utils.arrayFirst', ko.utils.arrayFirst);\n ko.exportSymbol('utils.arrayFilter', ko.utils.arrayFilter);\n ko.exportSymbol('utils.arrayGetDistinctValues', ko.utils.arrayGetDistinctValues);\n ko.exportSymbol('utils.arrayIndexOf', ko.utils.arrayIndexOf);\n ko.exportSymbol('utils.arrayMap', ko.utils.arrayMap);\n ko.exportSymbol('utils.arrayPushAll', ko.utils.arrayPushAll);\n ko.exportSymbol('utils.arrayRemoveItem', ko.utils.arrayRemoveItem);\n ko.exportSymbol('utils.cloneNodes', ko.utils.cloneNodes);\n ko.exportSymbol('utils.createSymbolOrString', ko.utils.createSymbolOrString);\n ko.exportSymbol('utils.extend', ko.utils.extend);\n ko.exportSymbol('utils.fieldsIncludedWithJsonPost', ko.utils.fieldsIncludedWithJsonPost);\n ko.exportSymbol('utils.getFormFields', ko.utils.getFormFields);\n ko.exportSymbol('utils.objectMap', ko.utils.objectMap);\n ko.exportSymbol('utils.peekObservable', ko.utils.peekObservable);\n ko.exportSymbol('utils.postJson', ko.utils.postJson);\n ko.exportSymbol('utils.parseJson', ko.utils.parseJson);\n ko.exportSymbol('utils.registerEventHandler', ko.utils.registerEventHandler);\n ko.exportSymbol('utils.stringifyJson', ko.utils.stringifyJson);\n ko.exportSymbol('utils.range', ko.utils.range);\n ko.exportSymbol('utils.toggleDomNodeCssClass', ko.utils.toggleDomNodeCssClass);\n ko.exportSymbol('utils.triggerEvent', ko.utils.triggerEvent);\n ko.exportSymbol('utils.unwrapObservable', ko.utils.unwrapObservable);\n ko.exportSymbol('utils.objectForEach', ko.utils.objectForEach);\n ko.exportSymbol('utils.addOrRemoveItem', ko.utils.addOrRemoveItem);\n ko.exportSymbol('utils.setTextContent', ko.utils.setTextContent);\n ko.exportSymbol('unwrap', ko.utils.unwrapObservable); // Convenient shorthand, because this is used so commonly\n\n if (!Function.prototype['bind']) {\n // Function.prototype.bind is a standard part of ECMAScript 5th Edition (December 2009, http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf)\n // In case the browser doesn't implement it natively, provide a JavaScript implementation. This implementation is based on the one in prototype.js\n Function.prototype['bind'] = function (object) {\n var originalFunction = this;\n if (arguments.length === 1) {\n return function () {\n return originalFunction.apply(object, arguments);\n };\n } else {\n var partialArgs = Array.prototype.slice.call(arguments, 1);\n return function () {\n var args = partialArgs.slice(0);\n args.push.apply(args, arguments);\n return originalFunction.apply(object, args);\n };\n }\n };\n }\n\n ko.utils.domData = new (function () {\n var uniqueId = 0;\n var dataStoreKeyExpandoPropertyName = \"__ko__\" + (new Date).getTime();\n var dataStore = {};\n\n var getDataForNode, clear;\n if (!ko.utils.ieVersion) {\n // We considered using WeakMap, but it has a problem in IE 11 and Edge that prevents using\n // it cross-window, so instead we just store the data directly on the node.\n // See https://github.com/knockout/knockout/issues/2141\n getDataForNode = function (node, createIfNotFound) {\n var dataForNode = node[dataStoreKeyExpandoPropertyName];\n if (!dataForNode && createIfNotFound) {\n dataForNode = node[dataStoreKeyExpandoPropertyName] = {};\n }\n return dataForNode;\n };\n clear = function (node) {\n if (node[dataStoreKeyExpandoPropertyName]) {\n delete node[dataStoreKeyExpandoPropertyName];\n return true; // Exposing \"did clean\" flag purely so specs can infer whether things have been cleaned up as intended\n }\n return false;\n };\n } else {\n // Old IE versions have memory issues if you store objects on the node, so we use a\n // separate data storage and link to it from the node using a string key.\n getDataForNode = function (node, createIfNotFound) {\n var dataStoreKey = node[dataStoreKeyExpandoPropertyName];\n var hasExistingDataStore = dataStoreKey && (dataStoreKey !== \"null\") && dataStore[dataStoreKey];\n if (!hasExistingDataStore) {\n if (!createIfNotFound)\n return undefined;\n dataStoreKey = node[dataStoreKeyExpandoPropertyName] = \"ko\" + uniqueId++;\n dataStore[dataStoreKey] = {};\n }\n return dataStore[dataStoreKey];\n };\n clear = function (node) {\n var dataStoreKey = node[dataStoreKeyExpandoPropertyName];\n if (dataStoreKey) {\n delete dataStore[dataStoreKey];\n node[dataStoreKeyExpandoPropertyName] = null;\n return true; // Exposing \"did clean\" flag purely so specs can infer whether things have been cleaned up as intended\n }\n return false;\n };\n }\n\n return {\n get: function (node, key) {\n var dataForNode = getDataForNode(node, false);\n return dataForNode && dataForNode[key];\n },\n set: function (node, key, value) {\n // Make sure we don't actually create a new domData key if we are actually deleting a value\n var dataForNode = getDataForNode(node, value !== undefined /* createIfNotFound */);\n dataForNode && (dataForNode[key] = value);\n },\n getOrSet: function (node, key, value) {\n var dataForNode = getDataForNode(node, true /* createIfNotFound */);\n return dataForNode[key] || (dataForNode[key] = value);\n },\n clear: clear,\n\n nextKey: function () {\n return (uniqueId++) + dataStoreKeyExpandoPropertyName;\n }\n };\n })();\n\n ko.exportSymbol('utils.domData', ko.utils.domData);\n ko.exportSymbol('utils.domData.clear', ko.utils.domData.clear); // Exporting only so specs can clear up after themselves fully\n\n ko.utils.domNodeDisposal = new (function () {\n var domDataKey = ko.utils.domData.nextKey();\n var cleanableNodeTypes = { 1: true, 8: true, 9: true }; // Element, Comment, Document\n var cleanableNodeTypesWithDescendants = { 1: true, 9: true }; // Element, Document\n\n function getDisposeCallbacksCollection(node, createIfNotFound) {\n var allDisposeCallbacks = ko.utils.domData.get(node, domDataKey);\n if ((allDisposeCallbacks === undefined) && createIfNotFound) {\n allDisposeCallbacks = [];\n ko.utils.domData.set(node, domDataKey, allDisposeCallbacks);\n }\n return allDisposeCallbacks;\n }\n function destroyCallbacksCollection(node) {\n ko.utils.domData.set(node, domDataKey, undefined);\n }\n\n function cleanSingleNode(node) {\n // Run all the dispose callbacks\n var callbacks = getDisposeCallbacksCollection(node, false);\n if (callbacks) {\n callbacks = callbacks.slice(0); // Clone, as the array may be modified during iteration (typically, callbacks will remove themselves)\n for (var i = 0; i < callbacks.length; i++)\n callbacks[i](node);\n }\n\n // Erase the DOM data\n ko.utils.domData.clear(node);\n\n // Perform cleanup needed by external libraries (currently only jQuery, but can be extended)\n ko.utils.domNodeDisposal[\"cleanExternalData\"](node);\n\n // Clear any immediate-child comment nodes, as these wouldn't have been found by\n // node.getElementsByTagName(\"*\") in cleanNode() (comment nodes aren't elements)\n if (cleanableNodeTypesWithDescendants[node.nodeType]) {\n cleanNodesInList(node.childNodes, true/*onlyComments*/);\n }\n }\n\n function cleanNodesInList(nodeList, onlyComments) {\n var cleanedNodes = [], lastCleanedNode;\n for (var i = 0; i < nodeList.length; i++) {\n if (!onlyComments || nodeList[i].nodeType === 8) {\n cleanSingleNode(cleanedNodes[cleanedNodes.length] = lastCleanedNode = nodeList[i]);\n if (nodeList[i] !== lastCleanedNode) {\n while (i-- && ko.utils.arrayIndexOf(cleanedNodes, nodeList[i]) == -1) {}\n }\n }\n }\n }\n\n return {\n addDisposeCallback : function(node, callback) {\n if (typeof callback != \"function\")\n throw new Error(\"Callback must be a function\");\n getDisposeCallbacksCollection(node, true).push(callback);\n },\n\n removeDisposeCallback : function(node, callback) {\n var callbacksCollection = getDisposeCallbacksCollection(node, false);\n if (callbacksCollection) {\n ko.utils.arrayRemoveItem(callbacksCollection, callback);\n if (callbacksCollection.length == 0)\n destroyCallbacksCollection(node);\n }\n },\n\n cleanNode : function(node) {\n ko.dependencyDetection.ignore(function () {\n // First clean this node, where applicable\n if (cleanableNodeTypes[node.nodeType]) {\n cleanSingleNode(node);\n\n // ... then its descendants, where applicable\n if (cleanableNodeTypesWithDescendants[node.nodeType]) {\n cleanNodesInList(node.getElementsByTagName(\"*\"));\n }\n }\n });\n\n return node;\n },\n\n removeNode : function(node) {\n ko.cleanNode(node);\n if (node.parentNode)\n node.parentNode.removeChild(node);\n },\n\n \"cleanExternalData\" : function (node) {\n // Special support for jQuery here because it's so commonly used.\n // Many jQuery plugins (including jquery.tmpl) store data using jQuery's equivalent of domData\n // so notify it to tear down any resources associated with the node & descendants here.\n if (jQueryInstance && (typeof jQueryInstance['cleanData'] == \"function\"))\n jQueryInstance['cleanData']([node]);\n }\n };\n })();\n ko.cleanNode = ko.utils.domNodeDisposal.cleanNode; // Shorthand name for convenience\n ko.removeNode = ko.utils.domNodeDisposal.removeNode; // Shorthand name for convenience\n ko.exportSymbol('cleanNode', ko.cleanNode);\n ko.exportSymbol('removeNode', ko.removeNode);\n ko.exportSymbol('utils.domNodeDisposal', ko.utils.domNodeDisposal);\n ko.exportSymbol('utils.domNodeDisposal.addDisposeCallback', ko.utils.domNodeDisposal.addDisposeCallback);\n ko.exportSymbol('utils.domNodeDisposal.removeDisposeCallback', ko.utils.domNodeDisposal.removeDisposeCallback);\n (function () {\n var none = [0, \"\", \"\"],\n table = [1, \"<table>\", \"</table>\"],\n tbody = [2, \"<table><tbody>\", \"</tbody></table>\"],\n tr = [3, \"<table><tbody><tr>\", \"</tr></tbody></table>\"],\n select = [1, \"<select multiple='multiple'>\", \"</select>\"],\n lookup = {\n 'thead': table,\n 'tbody': table,\n 'tfoot': table,\n 'tr': tbody,\n 'td': tr,\n 'th': tr,\n 'option': select,\n 'optgroup': select\n },\n\n // This is needed for old IE if you're *not* using either jQuery or innerShiv. Doesn't affect other cases.\n mayRequireCreateElementHack = ko.utils.ieVersion <= 8;\n\n function getWrap(tags) {\n var m = tags.match(/^(?:<!--.*?-->\\s*?)*?<([a-z]+)[\\s>]/);\n return (m && lookup[m[1]]) || none;\n }\n\n function simpleHtmlParse(html, documentContext) {\n documentContext || (documentContext = document);\n var windowContext = documentContext['parentWindow'] || documentContext['defaultView'] || window;\n\n // Based on jQuery's \"clean\" function, but only accounting for table-related elements.\n // If you have referenced jQuery, this won't be used anyway - KO will use jQuery's \"clean\" function directly\n\n // Note that there's still an issue in IE < 9 whereby it will discard comment nodes that are the first child of\n // a descendant node. For example: \"<div><!-- mycomment -->abc</div>\" will get parsed as \"<div>abc</div>\"\n // This won't affect anyone who has referenced jQuery, and there's always the workaround of inserting a dummy node\n // (possibly a text node) in front of the comment. So, KO does not attempt to workaround this IE issue automatically at present.\n\n // Trim whitespace, otherwise indexOf won't work as expected\n var tags = ko.utils.stringTrim(html).toLowerCase(), div = documentContext.createElement(\"div\"),\n wrap = getWrap(tags),\n depth = wrap[0];\n\n // Go to html and back, then peel off extra wrappers\n // Note that we always prefix with some dummy text, because otherwise, IE<9 will strip out leading comment nodes in descendants. Total madness.\n var markup = \"ignored<div>\" + wrap[1] + html + wrap[2] + \"</div>\";\n if (typeof windowContext['innerShiv'] == \"function\") {\n // Note that innerShiv is deprecated in favour of html5shiv. We should consider adding\n // support for html5shiv (except if no explicit support is needed, e.g., if html5shiv\n // somehow shims the native APIs so it just works anyway)\n div.appendChild(windowContext['innerShiv'](markup));\n } else {\n if (mayRequireCreateElementHack) {\n // The document.createElement('my-element') trick to enable custom elements in IE6-8\n // only works if we assign innerHTML on an element associated with that document.\n documentContext.body.appendChild(div);\n }\n\n div.innerHTML = markup;\n\n if (mayRequireCreateElementHack) {\n div.parentNode.removeChild(div);\n }\n }\n\n // Move to the right depth\n while (depth--)\n div = div.lastChild;\n\n return ko.utils.makeArray(div.lastChild.childNodes);\n }\n\n function jQueryHtmlParse(html, documentContext) {\n // jQuery's \"parseHTML\" function was introduced in jQuery 1.8.0 and is a documented public API.\n if (jQueryInstance['parseHTML']) {\n return jQueryInstance['parseHTML'](html, documentContext) || []; // Ensure we always return an array and never null\n } else {\n // For jQuery < 1.8.0, we fall back on the undocumented internal \"clean\" function.\n var elems = jQueryInstance['clean']([html], documentContext);\n\n // As of jQuery 1.7.1, jQuery parses the HTML by appending it to some dummy parent nodes held in an in-memory document fragment.\n // Unfortunately, it never clears the dummy parent nodes from the document fragment, so it leaks memory over time.\n // Fix this by finding the top-most dummy parent element, and detaching it from its owner fragment.\n if (elems && elems[0]) {\n // Find the top-most parent element that's a direct child of a document fragment\n var elem = elems[0];\n while (elem.parentNode && elem.parentNode.nodeType !== 11 /* i.e., DocumentFragment */)\n elem = elem.parentNode;\n // ... then detach it\n if (elem.parentNode)\n elem.parentNode.removeChild(elem);\n }\n\n return elems;\n }\n }\n\n ko.utils.parseHtmlFragment = function(html, documentContext) {\n return jQueryInstance ?\n jQueryHtmlParse(html, documentContext) : // As below, benefit from jQuery's optimisations where possible\n simpleHtmlParse(html, documentContext); // ... otherwise, this simple logic will do in most common cases.\n };\n\n ko.utils.parseHtmlForTemplateNodes = function(html, documentContext) {\n var nodes = ko.utils.parseHtmlFragment(html, documentContext);\n return (nodes.length && nodes[0].parentElement) || ko.utils.moveCleanedNodesToContainerElement(nodes);\n };\n\n ko.utils.setHtml = function(node, html) {\n ko.utils.emptyDomNode(node);\n\n // There's no legitimate reason to display a stringified observable without unwrapping it, so we'll unwrap it\n html = ko.utils.unwrapObservable(html);\n\n if ((html !== null) && (html !== undefined)) {\n if (typeof html != 'string')\n html = html.toString();\n\n // jQuery contains a lot of sophisticated code to parse arbitrary HTML fragments,\n // for example <tr> elements which are not normally allowed to exist on their own.\n // If you've referenced jQuery we'll use that rather than duplicating its code.\n if (jQueryInstance) {\n jQueryInstance(node)['html'](html);\n } else {\n // ... otherwise, use KO's own parsing logic.\n var parsedNodes = ko.utils.parseHtmlFragment(html, node.ownerDocument);\n for (var i = 0; i < parsedNodes.length; i++)\n node.appendChild(parsedNodes[i]);\n }\n }\n };\n })();\n\n ko.exportSymbol('utils.parseHtmlFragment', ko.utils.parseHtmlFragment);\n ko.exportSymbol('utils.setHtml', ko.utils.setHtml);\n\n ko.memoization = (function () {\n var memos = {};\n\n function randomMax8HexChars() {\n return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);\n }\n function generateRandomId() {\n return randomMax8HexChars() + randomMax8HexChars();\n }\n function findMemoNodes(rootNode, appendToArray) {\n if (!rootNode)\n return;\n if (rootNode.nodeType == 8) {\n var memoId = ko.memoization.parseMemoText(rootNode.nodeValue);\n if (memoId != null)\n appendToArray.push({ domNode: rootNode, memoId: memoId });\n } else if (rootNode.nodeType == 1) {\n for (var i = 0, childNodes = rootNode.childNodes, j = childNodes.length; i < j; i++)\n findMemoNodes(childNodes[i], appendToArray);\n }\n }\n\n return {\n memoize: function (callback) {\n if (typeof callback != \"function\")\n throw new Error(\"You can only pass a function to ko.memoization.memoize()\");\n var memoId = generateRandomId();\n memos[memoId] = callback;\n return \"<!--[ko_memo:\" + memoId + \"]-->\";\n },\n\n unmemoize: function (memoId, callbackParams) {\n var callback = memos[memoId];\n if (callback === undefined)\n throw new Error(\"Couldn't find any memo with ID \" + memoId + \". Perhaps it's already been unmemoized.\");\n try {\n callback.apply(null, callbackParams || []);\n return true;\n }\n finally { delete memos[memoId]; }\n },\n\n unmemoizeDomNodeAndDescendants: function (domNode, extraCallbackParamsArray) {\n var memos = [];\n findMemoNodes(domNode, memos);\n for (var i = 0, j = memos.length; i < j; i++) {\n var node = memos[i].domNode;\n var combinedParams = [node];\n if (extraCallbackParamsArray)\n ko.utils.arrayPushAll(combinedParams, extraCallbackParamsArray);\n ko.memoization.unmemoize(memos[i].memoId, combinedParams);\n node.nodeValue = \"\"; // Neuter this node so we don't try to unmemoize it again\n if (node.parentNode)\n node.parentNode.removeChild(node); // If possible, erase it totally (not always possible - someone else might just hold a reference to it then call unmemoizeDomNodeAndDescendants again)\n }\n },\n\n parseMemoText: function (memoText) {\n var match = memoText.match(/^\\[ko_memo\\:(.*?)\\]$/);\n return match ? match[1] : null;\n }\n };\n })();\n\n ko.exportSymbol('memoization', ko.memoization);\n ko.exportSymbol('memoization.memoize', ko.memoization.memoize);\n ko.exportSymbol('memoization.unmemoize', ko.memoization.unmemoize);\n ko.exportSymbol('memoization.parseMemoText', ko.memoization.parseMemoText);\n ko.exportSymbol('memoization.unmemoizeDomNodeAndDescendants', ko.memoization.unmemoizeDomNodeAndDescendants);\n ko.tasks = (function () {\n var scheduler,\n taskQueue = [],\n taskQueueLength = 0,\n nextHandle = 1,\n nextIndexToProcess = 0;\n\n if (window['MutationObserver']) {\n // Chrome 27+, Firefox 14+, IE 11+, Opera 15+, Safari 6.1+\n // From https://github.com/petkaantonov/bluebird * Copyright (c) 2014 Petka Antonov * License: MIT\n scheduler = (function (callback) {\n var div = document.createElement(\"div\");\n new MutationObserver(callback).observe(div, {attributes: true});\n return function () { div.classList.toggle(\"foo\"); };\n })(scheduledProcess);\n } else if (document && \"onreadystatechange\" in document.createElement(\"script\")) {\n // IE 6-10\n // From https://github.com/YuzuJS/setImmediate * Copyright (c) 2012 Barnesandnoble.com, llc, Donavon West, and Domenic Denicola * License: MIT\n scheduler = function (callback) {\n var script = document.createElement(\"script\");\n script.onreadystatechange = function () {\n script.onreadystatechange = null;\n document.documentElement.removeChild(script);\n script = null;\n callback();\n };\n document.documentElement.appendChild(script);\n };\n } else {\n scheduler = function (callback) {\n setTimeout(callback, 0);\n };\n }\n\n function processTasks() {\n if (taskQueueLength) {\n // Each mark represents the end of a logical group of tasks and the number of these groups is\n // limited to prevent unchecked recursion.\n var mark = taskQueueLength, countMarks = 0;\n\n // nextIndexToProcess keeps track of where we are in the queue; processTasks can be called recursively without issue\n for (var task; nextIndexToProcess < taskQueueLength; ) {\n if (task = taskQueue[nextIndexToProcess++]) {\n if (nextIndexToProcess > mark) {\n if (++countMarks >= 5000) {\n nextIndexToProcess = taskQueueLength; // skip all tasks remaining in the queue since any of them could be causing the recursion\n ko.utils.deferError(Error(\"'Too much recursion' after processing \" + countMarks + \" task groups.\"));\n break;\n }\n mark = taskQueueLength;\n }\n try {\n task();\n } catch (ex) {\n ko.utils.deferError(ex);\n }\n }\n }\n }\n }\n\n function scheduledProcess() {\n processTasks();\n\n // Reset the queue\n nextIndexToProcess = taskQueueLength = taskQueue.length = 0;\n }\n\n function scheduleTaskProcessing() {\n ko.tasks['scheduler'](scheduledProcess);\n }\n\n var tasks = {\n 'scheduler': scheduler, // Allow overriding the scheduler\n\n schedule: function (func) {\n if (!taskQueueLength) {\n scheduleTaskProcessing();\n }\n\n taskQueue[taskQueueLength++] = func;\n return nextHandle++;\n },\n\n cancel: function (handle) {\n var index = handle - (nextHandle - taskQueueLength);\n if (index >= nextIndexToProcess && index < taskQueueLength) {\n taskQueue[index] = null;\n }\n },\n\n // For testing only: reset the queue and return the previous queue length\n 'resetForTesting': function () {\n var length = taskQueueLength - nextIndexToProcess;\n nextIndexToProcess = taskQueueLength = taskQueue.length = 0;\n return length;\n },\n\n runEarly: processTasks\n };\n\n return tasks;\n })();\n\n ko.exportSymbol('tasks', ko.tasks);\n ko.exportSymbol('tasks.schedule', ko.tasks.schedule);\n//ko.exportSymbol('tasks.cancel', ko.tasks.cancel); \"cancel\" isn't minified\n ko.exportSymbol('tasks.runEarly', ko.tasks.runEarly);\n ko.extenders = {\n 'throttle': function(target, timeout) {\n // Throttling means two things:\n\n // (1) For dependent observables, we throttle *evaluations* so that, no matter how fast its dependencies\n // notify updates, the target doesn't re-evaluate (and hence doesn't notify) faster than a certain rate\n target['throttleEvaluation'] = timeout;\n\n // (2) For writable targets (observables, or writable dependent observables), we throttle *writes*\n // so the target cannot change value synchronously or faster than a certain rate\n var writeTimeoutInstance = null;\n return ko.dependentObservable({\n 'read': target,\n 'write': function(value) {\n clearTimeout(writeTimeoutInstance);\n writeTimeoutInstance = ko.utils.setTimeout(function() {\n target(value);\n }, timeout);\n }\n });\n },\n\n 'rateLimit': function(target, options) {\n var timeout, method, limitFunction;\n\n if (typeof options == 'number') {\n timeout = options;\n } else {\n timeout = options['timeout'];\n method = options['method'];\n }\n\n // rateLimit supersedes deferred updates\n target._deferUpdates = false;\n\n limitFunction = typeof method == 'function' ? method : method == 'notifyWhenChangesStop' ? debounce : throttle;\n target.limit(function(callback) {\n return limitFunction(callback, timeout, options);\n });\n },\n\n 'deferred': function(target, options) {\n if (options !== true) {\n throw new Error('The \\'deferred\\' extender only accepts the value \\'true\\', because it is not supported to turn deferral off once enabled.')\n }\n\n if (!target._deferUpdates) {\n target._deferUpdates = true;\n target.limit(function (callback) {\n var handle,\n ignoreUpdates = false;\n return function () {\n if (!ignoreUpdates) {\n ko.tasks.cancel(handle);\n handle = ko.tasks.schedule(callback);\n\n try {\n ignoreUpdates = true;\n target['notifySubscribers'](undefined, 'dirty');\n } finally {\n ignoreUpdates = false;\n }\n }\n };\n });\n }\n },\n\n 'notify': function(target, notifyWhen) {\n target[\"equalityComparer\"] = notifyWhen == \"always\" ?\n null : // null equalityComparer means to always notify\n valuesArePrimitiveAndEqual;\n }\n };\n\n var primitiveTypes = { 'undefined':1, 'boolean':1, 'number':1, 'string':1 };\n function valuesArePrimitiveAndEqual(a, b) {\n var oldValueIsPrimitive = (a === null) || (typeof(a) in primitiveTypes);\n return oldValueIsPrimitive ? (a === b) : false;\n }\n\n function throttle(callback, timeout) {\n var timeoutInstance;\n return function () {\n if (!timeoutInstance) {\n timeoutInstance = ko.utils.setTimeout(function () {\n timeoutInstance = undefined;\n callback();\n }, timeout);\n }\n };\n }\n\n function debounce(callback, timeout) {\n var timeoutInstance;\n return function () {\n clearTimeout(timeoutInstance);\n timeoutInstance = ko.utils.setTimeout(callback, timeout);\n };\n }\n\n function applyExtenders(requestedExtenders) {\n var target = this;\n if (requestedExtenders) {\n ko.utils.objectForEach(requestedExtenders, function(key, value) {\n var extenderHandler = ko.extenders[key];\n if (typeof extenderHandler == 'function') {\n target = extenderHandler(target, value) || target;\n }\n });\n }\n return target;\n }\n\n ko.exportSymbol('extenders', ko.extenders);\n\n ko.subscription = function (target, callback, disposeCallback) {\n this._target = target;\n this._callback = callback;\n this._disposeCallback = disposeCallback;\n this._isDisposed = false;\n this._node = null;\n this._domNodeDisposalCallback = null;\n ko.exportProperty(this, 'dispose', this.dispose);\n ko.exportProperty(this, 'disposeWhenNodeIsRemoved', this.disposeWhenNodeIsRemoved);\n };\n ko.subscription.prototype.dispose = function () {\n var self = this;\n if (!self._isDisposed) {\n if (self._domNodeDisposalCallback) {\n ko.utils.domNodeDisposal.removeDisposeCallback(self._node, self._domNodeDisposalCallback);\n }\n self._isDisposed = true;\n self._disposeCallback();\n\n self._target = self._callback = self._disposeCallback = self._node = self._domNodeDisposalCallback = null;\n }\n };\n ko.subscription.prototype.disposeWhenNodeIsRemoved = function (node) {\n this._node = node;\n ko.utils.domNodeDisposal.addDisposeCallback(node, this._domNodeDisposalCallback = this.dispose.bind(this));\n };\n\n ko.subscribable = function () {\n ko.utils.setPrototypeOfOrExtend(this, ko_subscribable_fn);\n ko_subscribable_fn.init(this);\n }\n\n var defaultEvent = \"change\";\n\n// Moved out of \"limit\" to avoid the extra closure\n function limitNotifySubscribers(value, event) {\n if (!event || event === defaultEvent) {\n this._limitChange(value);\n } else if (event === 'beforeChange') {\n this._limitBeforeChange(value);\n } else {\n this._origNotifySubscribers(value, event);\n }\n }\n\n var ko_subscribable_fn = {\n init: function(instance) {\n instance._subscriptions = { \"change\": [] };\n instance._versionNumber = 1;\n },\n\n subscribe: function (callback, callbackTarget, event) {\n var self = this;\n\n event = event || defaultEvent;\n var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback;\n\n var subscription = new ko.subscription(self, boundCallback, function () {\n ko.utils.arrayRemoveItem(self._subscriptions[event], subscription);\n if (self.afterSubscriptionRemove)\n self.afterSubscriptionRemove(event);\n });\n\n if (self.beforeSubscriptionAdd)\n self.beforeSubscriptionAdd(event);\n\n if (!self._subscriptions[event])\n self._subscriptions[event] = [];\n self._subscriptions[event].push(subscription);\n\n return subscription;\n },\n\n \"notifySubscribers\": function (valueToNotify, event) {\n event = event || defaultEvent;\n if (event === defaultEvent) {\n this.updateVersion();\n }\n if (this.hasSubscriptionsForEvent(event)) {\n var subs = event === defaultEvent && this._changeSubscriptions || this._subscriptions[event].slice(0);\n try {\n ko.dependencyDetection.begin(); // Begin suppressing dependency detection (by setting the top frame to undefined)\n for (var i = 0, subscription; subscription = subs[i]; ++i) {\n // In case a subscription was disposed during the arrayForEach cycle, check\n // for isDisposed on each subscription before invoking its callback\n if (!subscription._isDisposed)\n subscription._callback(valueToNotify);\n }\n } finally {\n ko.dependencyDetection.end(); // End suppressing dependency detection\n }\n }\n },\n\n getVersion: function () {\n return this._versionNumber;\n },\n\n hasChanged: function (versionToCheck) {\n return this.getVersion() !== versionToCheck;\n },\n\n updateVersion: function () {\n ++this._versionNumber;\n },\n\n limit: function(limitFunction) {\n var self = this, selfIsObservable = ko.isObservable(self),\n ignoreBeforeChange, notifyNextChange, previousValue, pendingValue, didUpdate,\n beforeChange = 'beforeChange';\n\n if (!self._origNotifySubscribers) {\n self._origNotifySubscribers = self[\"notifySubscribers\"];\n self[\"notifySubscribers\"] = limitNotifySubscribers;\n }\n\n var finish = limitFunction(function() {\n self._notificationIsPending = false;\n\n // If an observable provided a reference to itself, access it to get the latest value.\n // This allows computed observables to delay calculating their value until needed.\n if (selfIsObservable && pendingValue === self) {\n pendingValue = self._evalIfChanged ? self._evalIfChanged() : self();\n }\n var shouldNotify = notifyNextChange || (didUpdate && self.isDifferent(previousValue, pendingValue));\n\n didUpdate = notifyNextChange = ignoreBeforeChange = false;\n\n if (shouldNotify) {\n self._origNotifySubscribers(previousValue = pendingValue);\n }\n });\n\n self._limitChange = function(value, isDirty) {\n if (!isDirty || !self._notificationIsPending) {\n didUpdate = !isDirty;\n }\n self._changeSubscriptions = self._subscriptions[defaultEvent].slice(0);\n self._notificationIsPending = ignoreBeforeChange = true;\n pendingValue = value;\n finish();\n };\n self._limitBeforeChange = function(value) {\n if (!ignoreBeforeChange) {\n previousValue = value;\n self._origNotifySubscribers(value, beforeChange);\n }\n };\n self._recordUpdate = function() {\n didUpdate = true;\n };\n self._notifyNextChangeIfValueIsDifferent = function() {\n if (self.isDifferent(previousValue, self.peek(true /*evaluate*/))) {\n notifyNextChange = true;\n }\n };\n },\n\n hasSubscriptionsForEvent: function(event) {\n return this._subscriptions[event] && this._subscriptions[event].length;\n },\n\n getSubscriptionsCount: function (event) {\n if (event) {\n return this._subscriptions[event] && this._subscriptions[event].length || 0;\n } else {\n var total = 0;\n ko.utils.objectForEach(this._subscriptions, function(eventName, subscriptions) {\n if (eventName !== 'dirty')\n total += subscriptions.length;\n });\n return total;\n }\n },\n\n isDifferent: function(oldValue, newValue) {\n return !this['equalityComparer'] || !this['equalityComparer'](oldValue, newValue);\n },\n\n toString: function() {\n return '[object Object]'\n },\n\n extend: applyExtenders\n };\n\n ko.exportProperty(ko_subscribable_fn, 'init', ko_subscribable_fn.init);\n ko.exportProperty(ko_subscribable_fn, 'subscribe', ko_subscribable_fn.subscribe);\n ko.exportProperty(ko_subscribable_fn, 'extend', ko_subscribable_fn.extend);\n ko.exportProperty(ko_subscribable_fn, 'getSubscriptionsCount', ko_subscribable_fn.getSubscriptionsCount);\n\n// For browsers that support proto assignment, we overwrite the prototype of each\n// observable instance. Since observables are functions, we need Function.prototype\n// to still be in the prototype chain.\n if (ko.utils.canSetPrototype) {\n ko.utils.setPrototypeOf(ko_subscribable_fn, Function.prototype);\n }\n\n ko.subscribable['fn'] = ko_subscribable_fn;\n\n\n ko.isSubscribable = function (instance) {\n return instance != null && typeof instance.subscribe == \"function\" && typeof instance[\"notifySubscribers\"] == \"function\";\n };\n\n ko.exportSymbol('subscribable', ko.subscribable);\n ko.exportSymbol('isSubscribable', ko.isSubscribable);\n\n ko.computedContext = ko.dependencyDetection = (function () {\n var outerFrames = [],\n currentFrame,\n lastId = 0;\n\n // Return a unique ID that can be assigned to an observable for dependency tracking.\n // Theoretically, you could eventually overflow the number storage size, resulting\n // in duplicate IDs. But in JavaScript, the largest exact integral value is 2^53\n // or 9,007,199,254,740,992. If you created 1,000,000 IDs per second, it would\n // take over 285 years to reach that number.\n // Reference http://blog.vjeux.com/2010/javascript/javascript-max_int-number-limits.html\n function getId() {\n return ++lastId;\n }\n\n function begin(options) {\n outerFrames.push(currentFrame);\n currentFrame = options;\n }\n\n function end() {\n currentFrame = outerFrames.pop();\n }\n\n return {\n begin: begin,\n\n end: end,\n\n registerDependency: function (subscribable) {\n if (currentFrame) {\n if (!ko.isSubscribable(subscribable))\n throw new Error(\"Only subscribable things can act as dependencies\");\n currentFrame.callback.call(currentFrame.callbackTarget, subscribable, subscribable._id || (subscribable._id = getId()));\n }\n },\n\n ignore: function (callback, callbackTarget, callbackArgs) {\n try {\n begin();\n return callback.apply(callbackTarget, callbackArgs || []);\n } finally {\n end();\n }\n },\n\n getDependenciesCount: function () {\n if (currentFrame)\n return currentFrame.computed.getDependenciesCount();\n },\n\n getDependencies: function () {\n if (currentFrame)\n return currentFrame.computed.getDependencies();\n },\n\n isInitial: function() {\n if (currentFrame)\n return currentFrame.isInitial;\n },\n\n computed: function() {\n if (currentFrame)\n return currentFrame.computed;\n }\n };\n })();\n\n ko.exportSymbol('computedContext', ko.computedContext);\n ko.exportSymbol('computedContext.getDependenciesCount', ko.computedContext.getDependenciesCount);\n ko.exportSymbol('computedContext.getDependencies', ko.computedContext.getDependencies);\n ko.exportSymbol('computedContext.isInitial', ko.computedContext.isInitial);\n ko.exportSymbol('computedContext.registerDependency', ko.computedContext.registerDependency);\n\n ko.exportSymbol('ignoreDependencies', ko.ignoreDependencies = ko.dependencyDetection.ignore);\n var observableLatestValue = ko.utils.createSymbolOrString('_latestValue');\n\n ko.observable = function (initialValue) {\n function observable() {\n if (arguments.length > 0) {\n // Write\n\n // Ignore writes if the value hasn't changed\n if (observable.isDifferent(observable[observableLatestValue], arguments[0])) {\n observable.valueWillMutate();\n observable[observableLatestValue] = arguments[0];\n observable.valueHasMutated();\n }\n return this; // Permits chained assignments\n }\n else {\n // Read\n ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a \"read\" operation\n return observable[observableLatestValue];\n }\n }\n\n observable[observableLatestValue] = initialValue;\n\n // Inherit from 'subscribable'\n if (!ko.utils.canSetPrototype) {\n // 'subscribable' won't be on the prototype chain unless we put it there directly\n ko.utils.extend(observable, ko.subscribable['fn']);\n }\n ko.subscribable['fn'].init(observable);\n\n // Inherit from 'observable'\n ko.utils.setPrototypeOfOrExtend(observable, observableFn);\n\n if (ko.options['deferUpdates']) {\n ko.extenders['deferred'](observable, true);\n }\n\n return observable;\n }\n\n// Define prototype for observables\n var observableFn = {\n 'equalityComparer': valuesArePrimitiveAndEqual,\n peek: function() { return this[observableLatestValue]; },\n valueHasMutated: function () {\n this['notifySubscribers'](this[observableLatestValue], 'spectate');\n this['notifySubscribers'](this[observableLatestValue]);\n },\n valueWillMutate: function () { this['notifySubscribers'](this[observableLatestValue], 'beforeChange'); }\n };\n\n// Note that for browsers that don't support proto assignment, the\n// inheritance chain is created manually in the ko.observable constructor\n if (ko.utils.canSetPrototype) {\n ko.utils.setPrototypeOf(observableFn, ko.subscribable['fn']);\n }\n\n var protoProperty = ko.observable.protoProperty = '__ko_proto__';\n observableFn[protoProperty] = ko.observable;\n\n ko.isObservable = function (instance) {\n var proto = typeof instance == 'function' && instance[protoProperty];\n if (proto && proto !== observableFn[protoProperty] && proto !== ko.computed['fn'][protoProperty]) {\n throw Error(\"Invalid object that looks like an observable; possibly from another Knockout instance\");\n }\n return !!proto;\n };\n\n ko.isWriteableObservable = function (instance) {\n return (typeof instance == 'function' && (\n (instance[protoProperty] === observableFn[protoProperty]) || // Observable\n (instance[protoProperty] === ko.computed['fn'][protoProperty] && instance.hasWriteFunction))); // Writable computed observable\n };\n\n ko.exportSymbol('observable', ko.observable);\n ko.exportSymbol('isObservable', ko.isObservable);\n ko.exportSymbol('isWriteableObservable', ko.isWriteableObservable);\n ko.exportSymbol('isWritableObservable', ko.isWriteableObservable);\n ko.exportSymbol('observable.fn', observableFn);\n ko.exportProperty(observableFn, 'peek', observableFn.peek);\n ko.exportProperty(observableFn, 'valueHasMutated', observableFn.valueHasMutated);\n ko.exportProperty(observableFn, 'valueWillMutate', observableFn.valueWillMutate);\n ko.observableArray = function (initialValues) {\n initialValues = initialValues || [];\n\n if (typeof initialValues != 'object' || !('length' in initialValues))\n throw new Error(\"The argument passed when initializing an observable array must be an array, or null, or undefined.\");\n\n var result = ko.observable(initialValues);\n ko.utils.setPrototypeOfOrExtend(result, ko.observableArray['fn']);\n return result.extend({'trackArrayChanges':true});\n };\n\n ko.observableArray['fn'] = {\n 'remove': function (valueOrPredicate) {\n var underlyingArray = this.peek();\n var removedValues = [];\n var predicate = typeof valueOrPredicate == \"function\" && !ko.isObservable(valueOrPredicate) ? valueOrPredicate : function (value) { return value === valueOrPredicate; };\n for (var i = 0; i < underlyingArray.length; i++) {\n var value = underlyingArray[i];\n if (predicate(value)) {\n if (removedValues.length === 0) {\n this.valueWillMutate();\n }\n if (underlyingArray[i] !== value) {\n throw Error(\"Array modified during remove; cannot remove item\");\n }\n removedValues.push(value);\n underlyingArray.splice(i, 1);\n i--;\n }\n }\n if (removedValues.length) {\n this.valueHasMutated();\n }\n return removedValues;\n },\n\n 'removeAll': function (arrayOfValues) {\n // If you passed zero args, we remove everything\n if (arrayOfValues === undefined) {\n var underlyingArray = this.peek();\n var allValues = underlyingArray.slice(0);\n this.valueWillMutate();\n underlyingArray.splice(0, underlyingArray.length);\n this.valueHasMutated();\n return allValues;\n }\n // If you passed an arg, we interpret it as an array of entries to remove\n if (!arrayOfValues)\n return [];\n return this['remove'](function (value) {\n return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;\n });\n },\n\n 'destroy': function (valueOrPredicate) {\n var underlyingArray = this.peek();\n var predicate = typeof valueOrPredicate == \"function\" && !ko.isObservable(valueOrPredicate) ? valueOrPredicate : function (value) { return value === valueOrPredicate; };\n this.valueWillMutate();\n for (var i = underlyingArray.length - 1; i >= 0; i--) {\n var value = underlyingArray[i];\n if (predicate(value))\n value[\"_destroy\"] = true;\n }\n this.valueHasMutated();\n },\n\n 'destroyAll': function (arrayOfValues) {\n // If you passed zero args, we destroy everything\n if (arrayOfValues === undefined)\n return this['destroy'](function() { return true });\n\n // If you passed an arg, we interpret it as an array of entries to destroy\n if (!arrayOfValues)\n return [];\n return this['destroy'](function (value) {\n return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;\n });\n },\n\n 'indexOf': function (item) {\n var underlyingArray = this();\n return ko.utils.arrayIndexOf(underlyingArray, item);\n },\n\n 'replace': function(oldItem, newItem) {\n var index = this['indexOf'](oldItem);\n if (index >= 0) {\n this.valueWillMutate();\n this.peek()[index] = newItem;\n this.valueHasMutated();\n }\n },\n\n 'sorted': function (compareFunction) {\n var arrayCopy = this().slice(0);\n return compareFunction ? arrayCopy.sort(compareFunction) : arrayCopy.sort();\n },\n\n 'reversed': function () {\n return this().slice(0).reverse();\n }\n };\n\n// Note that for browsers that don't support proto assignment, the\n// inheritance chain is created manually in the ko.observableArray constructor\n if (ko.utils.canSetPrototype) {\n ko.utils.setPrototypeOf(ko.observableArray['fn'], ko.observable['fn']);\n }\n\n// Populate ko.observableArray.fn with read/write functions from native arrays\n// Important: Do not add any additional functions here that may reasonably be used to *read* data from the array\n// because we'll eval them without causing subscriptions, so ko.computed output could end up getting stale\n ko.utils.arrayForEach([\"pop\", \"push\", \"reverse\", \"shift\", \"sort\", \"splice\", \"unshift\"], function (methodName) {\n ko.observableArray['fn'][methodName] = function () {\n // Use \"peek\" to avoid creating a subscription in any computed that we're executing in the context of\n // (for consistency with mutating regular observables)\n var underlyingArray = this.peek();\n this.valueWillMutate();\n this.cacheDiffForKnownOperation(underlyingArray, methodName, arguments);\n var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);\n this.valueHasMutated();\n // The native sort and reverse methods return a reference to the array, but it makes more sense to return the observable array instead.\n return methodCallResult === underlyingArray ? this : methodCallResult;\n };\n });\n\n// Populate ko.observableArray.fn with read-only functions from native arrays\n ko.utils.arrayForEach([\"slice\"], function (methodName) {\n ko.observableArray['fn'][methodName] = function () {\n var underlyingArray = this();\n return underlyingArray[methodName].apply(underlyingArray, arguments);\n };\n });\n\n ko.isObservableArray = function (instance) {\n return ko.isObservable(instance)\n && typeof instance[\"remove\"] == \"function\"\n && typeof instance[\"push\"] == \"function\";\n };\n\n ko.exportSymbol('observableArray', ko.observableArray);\n ko.exportSymbol('isObservableArray', ko.isObservableArray);\n var arrayChangeEventName = 'arrayChange';\n ko.extenders['trackArrayChanges'] = function(target, options) {\n // Use the provided options--each call to trackArrayChanges overwrites the previously set options\n target.compareArrayOptions = {};\n if (options && typeof options == \"object\") {\n ko.utils.extend(target.compareArrayOptions, options);\n }\n target.compareArrayOptions['sparse'] = true;\n\n // Only modify the target observable once\n if (target.cacheDiffForKnownOperation) {\n return;\n }\n var trackingChanges = false,\n cachedDiff = null,\n changeSubscription,\n spectateSubscription,\n pendingChanges = 0,\n previousContents,\n underlyingBeforeSubscriptionAddFunction = target.beforeSubscriptionAdd,\n underlyingAfterSubscriptionRemoveFunction = target.afterSubscriptionRemove;\n\n // Watch \"subscribe\" calls, and for array change events, ensure change tracking is enabled\n target.beforeSubscriptionAdd = function (event) {\n if (underlyingBeforeSubscriptionAddFunction) {\n underlyingBeforeSubscriptionAddFunction.call(target, event);\n }\n if (event === arrayChangeEventName) {\n trackChanges();\n }\n };\n // Watch \"dispose\" calls, and for array change events, ensure change tracking is disabled when all are disposed\n target.afterSubscriptionRemove = function (event) {\n if (underlyingAfterSubscriptionRemoveFunction) {\n underlyingAfterSubscriptionRemoveFunction.call(target, event);\n }\n if (event === arrayChangeEventName && !target.hasSubscriptionsForEvent(arrayChangeEventName)) {\n if (changeSubscription) {\n changeSubscription.dispose();\n }\n if (spectateSubscription) {\n spectateSubscription.dispose();\n }\n spectateSubscription = changeSubscription = null;\n trackingChanges = false;\n previousContents = undefined;\n }\n };\n\n function trackChanges() {\n if (trackingChanges) {\n // Whenever there's a new subscription and there are pending notifications, make sure all previous\n // subscriptions are notified of the change so that all subscriptions are in sync.\n notifyChanges();\n return;\n }\n\n trackingChanges = true;\n\n // Track how many times the array actually changed value\n spectateSubscription = target.subscribe(function () {\n ++pendingChanges;\n }, null, \"spectate\");\n\n // Each time the array changes value, capture a clone so that on the next\n // change it's possible to produce a diff\n previousContents = [].concat(target.peek() || []);\n cachedDiff = null;\n changeSubscription = target.subscribe(notifyChanges);\n\n function notifyChanges() {\n if (pendingChanges) {\n // Make a copy of the current contents and ensure it's an array\n var currentContents = [].concat(target.peek() || []), changes;\n\n // Compute the diff and issue notifications, but only if someone is listening\n if (target.hasSubscriptionsForEvent(arrayChangeEventName)) {\n changes = getChanges(previousContents, currentContents);\n }\n\n // Eliminate references to the old, removed items, so they can be GCed\n previousContents = currentContents;\n cachedDiff = null;\n pendingChanges = 0;\n\n if (changes && changes.length) {\n target['notifySubscribers'](changes, arrayChangeEventName);\n }\n }\n }\n }\n\n function getChanges(previousContents, currentContents) {\n // We try to re-use cached diffs.\n // The scenarios where pendingChanges > 1 are when using rate limiting or deferred updates,\n // which without this check would not be compatible with arrayChange notifications. Normally,\n // notifications are issued immediately so we wouldn't be queueing up more than one.\n if (!cachedDiff || pendingChanges > 1) {\n cachedDiff = ko.utils.compareArrays(previousContents, currentContents, target.compareArrayOptions);\n }\n\n return cachedDiff;\n }\n\n target.cacheDiffForKnownOperation = function(rawArray, operationName, args) {\n // Only run if we're currently tracking changes for this observable array\n // and there aren't any pending deferred notifications.\n if (!trackingChanges || pendingChanges) {\n return;\n }\n var diff = [],\n arrayLength = rawArray.length,\n argsLength = args.length,\n offset = 0;\n\n function pushDiff(status, value, index) {\n return diff[diff.length] = { 'status': status, 'value': value, 'index': index };\n }\n switch (operationName) {\n case 'push':\n offset = arrayLength;\n case 'unshift':\n for (var index = 0; index < argsLength; index++) {\n pushDiff('added', args[index], offset + index);\n }\n break;\n\n case 'pop':\n offset = arrayLength - 1;\n case 'shift':\n if (arrayLength) {\n pushDiff('deleted', rawArray[offset], offset);\n }\n break;\n\n case 'splice':\n // Negative start index means 'from end of array'. After that we clamp to [0...arrayLength].\n // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice\n var startIndex = Math.min(Math.max(0, args[0] < 0 ? arrayLength + args[0] : args[0]), arrayLength),\n endDeleteIndex = argsLength === 1 ? arrayLength : Math.min(startIndex + (args[1] || 0), arrayLength),\n endAddIndex = startIndex + argsLength - 2,\n endIndex = Math.max(endDeleteIndex, endAddIndex),\n additions = [], deletions = [];\n for (var index = startIndex, argsIndex = 2; index < endIndex; ++index, ++argsIndex) {\n if (index < endDeleteIndex)\n deletions.push(pushDiff('deleted', rawArray[index], index));\n if (index < endAddIndex)\n additions.push(pushDiff('added', args[argsIndex], index));\n }\n ko.utils.findMovesInArrayComparison(deletions, additions);\n break;\n\n default:\n return;\n }\n cachedDiff = diff;\n };\n };\n var computedState = ko.utils.createSymbolOrString('_state');\n\n ko.computed = ko.dependentObservable = function (evaluatorFunctionOrOptions, evaluatorFunctionTarget, options) {\n if (typeof evaluatorFunctionOrOptions === \"object\") {\n // Single-parameter syntax - everything is on this \"options\" param\n options = evaluatorFunctionOrOptions;\n } else {\n // Multi-parameter syntax - construct the options according to the params passed\n options = options || {};\n if (evaluatorFunctionOrOptions) {\n options[\"read\"] = evaluatorFunctionOrOptions;\n }\n }\n if (typeof options[\"read\"] != \"function\")\n throw Error(\"Pass a function that returns the value of the ko.computed\");\n\n var writeFunction = options[\"write\"];\n var state = {\n latestValue: undefined,\n isStale: true,\n isDirty: true,\n isBeingEvaluated: false,\n suppressDisposalUntilDisposeWhenReturnsFalse: false,\n isDisposed: false,\n pure: false,\n isSleeping: false,\n readFunction: options[\"read\"],\n evaluatorFunctionTarget: evaluatorFunctionTarget || options[\"owner\"],\n disposeWhenNodeIsRemoved: options[\"disposeWhenNodeIsRemoved\"] || options.disposeWhenNodeIsRemoved || null,\n disposeWhen: options[\"disposeWhen\"] || options.disposeWhen,\n domNodeDisposalCallback: null,\n dependencyTracking: {},\n dependenciesCount: 0,\n evaluationTimeoutInstance: null\n };\n\n function computedObservable() {\n if (arguments.length > 0) {\n if (typeof writeFunction === \"function\") {\n // Writing a value\n writeFunction.apply(state.evaluatorFunctionTarget, arguments);\n } else {\n throw new Error(\"Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.\");\n }\n return this; // Permits chained assignments\n } else {\n // Reading the value\n if (!state.isDisposed) {\n ko.dependencyDetection.registerDependency(computedObservable);\n }\n if (state.isDirty || (state.isSleeping && computedObservable.haveDependenciesChanged())) {\n computedObservable.evaluateImmediate();\n }\n return state.latestValue;\n }\n }\n\n computedObservable[computedState] = state;\n computedObservable.hasWriteFunction = typeof writeFunction === \"function\";\n\n // Inherit from 'subscribable'\n if (!ko.utils.canSetPrototype) {\n // 'subscribable' won't be on the prototype chain unless we put it there directly\n ko.utils.extend(computedObservable, ko.subscribable['fn']);\n }\n ko.subscribable['fn'].init(computedObservable);\n\n // Inherit from 'computed'\n ko.utils.setPrototypeOfOrExtend(computedObservable, computedFn);\n\n if (options['pure']) {\n state.pure = true;\n state.isSleeping = true; // Starts off sleeping; will awake on the first subscription\n ko.utils.extend(computedObservable, pureComputedOverrides);\n } else if (options['deferEvaluation']) {\n ko.utils.extend(computedObservable, deferEvaluationOverrides);\n }\n\n if (ko.options['deferUpdates']) {\n ko.extenders['deferred'](computedObservable, true);\n }\n\n if (DEBUG) {\n // #1731 - Aid debugging by exposing the computed's options\n computedObservable[\"_options\"] = options;\n }\n\n if (state.disposeWhenNodeIsRemoved) {\n // Since this computed is associated with a DOM node, and we don't want to dispose the computed\n // until the DOM node is *removed* from the document (as opposed to never having been in the document),\n // we'll prevent disposal until \"disposeWhen\" first returns false.\n state.suppressDisposalUntilDisposeWhenReturnsFalse = true;\n\n // disposeWhenNodeIsRemoved: true can be used to opt into the \"only dispose after first false result\"\n // behaviour even if there's no specific node to watch. In that case, clear the option so we don't try\n // to watch for a non-node's disposal. This technique is intended for KO's internal use only and shouldn't\n // be documented or used by application code, as it's likely to change in a future version of KO.\n if (!state.disposeWhenNodeIsRemoved.nodeType) {\n state.disposeWhenNodeIsRemoved = null;\n }\n }\n\n // Evaluate, unless sleeping or deferEvaluation is true\n if (!state.isSleeping && !options['deferEvaluation']) {\n computedObservable.evaluateImmediate();\n }\n\n // Attach a DOM node disposal callback so that the computed will be proactively disposed as soon as the node is\n // removed using ko.removeNode. But skip if isActive is false (there will never be any dependencies to dispose).\n if (state.disposeWhenNodeIsRemoved && computedObservable.isActive()) {\n ko.utils.domNodeDisposal.addDisposeCallback(state.disposeWhenNodeIsRemoved, state.domNodeDisposalCallback = function () {\n computedObservable.dispose();\n });\n }\n\n return computedObservable;\n };\n\n// Utility function that disposes a given dependencyTracking entry\n function computedDisposeDependencyCallback(id, entryToDispose) {\n if (entryToDispose !== null && entryToDispose.dispose) {\n entryToDispose.dispose();\n }\n }\n\n// This function gets called each time a dependency is detected while evaluating a computed.\n// It's factored out as a shared function to avoid creating unnecessary function instances during evaluation.\n function computedBeginDependencyDetectionCallback(subscribable, id) {\n var computedObservable = this.computedObservable,\n state = computedObservable[computedState];\n if (!state.isDisposed) {\n if (this.disposalCount && this.disposalCandidates[id]) {\n // Don't want to dispose this subscription, as it's still being used\n computedObservable.addDependencyTracking(id, subscribable, this.disposalCandidates[id]);\n this.disposalCandidates[id] = null; // No need to actually delete the property - disposalCandidates is a transient object anyway\n --this.disposalCount;\n } else if (!state.dependencyTracking[id]) {\n // Brand new subscription - add it\n computedObservable.addDependencyTracking(id, subscribable, state.isSleeping ? { _target: subscribable } : computedObservable.subscribeToDependency(subscribable));\n }\n // If the observable we've accessed has a pending notification, ensure we get notified of the actual final value (bypass equality checks)\n if (subscribable._notificationIsPending) {\n subscribable._notifyNextChangeIfValueIsDifferent();\n }\n }\n }\n\n var computedFn = {\n \"equalityComparer\": valuesArePrimitiveAndEqual,\n getDependenciesCount: function () {\n return this[computedState].dependenciesCount;\n },\n getDependencies: function () {\n var dependencyTracking = this[computedState].dependencyTracking, dependentObservables = [];\n\n ko.utils.objectForEach(dependencyTracking, function (id, dependency) {\n dependentObservables[dependency._order] = dependency._target;\n });\n\n return dependentObservables;\n },\n hasAncestorDependency: function (obs) {\n if (!this[computedState].dependenciesCount) {\n return false;\n }\n var dependencies = this.getDependencies();\n if (ko.utils.arrayIndexOf(dependencies, obs) !== -1) {\n return true;\n }\n return !!ko.utils.arrayFirst(dependencies, function (dep) {\n return dep.hasAncestorDependency && dep.hasAncestorDependency(obs);\n });\n },\n addDependencyTracking: function (id, target, trackingObj) {\n if (this[computedState].pure && target === this) {\n throw Error(\"A 'pure' computed must not be called recursively\");\n }\n\n this[computedState].dependencyTracking[id] = trackingObj;\n trackingObj._order = this[computedState].dependenciesCount++;\n trackingObj._version = target.getVersion();\n },\n haveDependenciesChanged: function () {\n var id, dependency, dependencyTracking = this[computedState].dependencyTracking;\n for (id in dependencyTracking) {\n if (Object.prototype.hasOwnProperty.call(dependencyTracking, id)) {\n dependency = dependencyTracking[id];\n if ((this._evalDelayed && dependency._target._notificationIsPending) || dependency._target.hasChanged(dependency._version)) {\n return true;\n }\n }\n }\n },\n markDirty: function () {\n // Process \"dirty\" events if we can handle delayed notifications\n if (this._evalDelayed && !this[computedState].isBeingEvaluated) {\n this._evalDelayed(false /*isChange*/);\n }\n },\n isActive: function () {\n var state = this[computedState];\n return state.isDirty || state.dependenciesCount > 0;\n },\n respondToChange: function () {\n // Ignore \"change\" events if we've already scheduled a delayed notification\n if (!this._notificationIsPending) {\n this.evaluatePossiblyAsync();\n } else if (this[computedState].isDirty) {\n this[computedState].isStale = true;\n }\n },\n subscribeToDependency: function (target) {\n if (target._deferUpdates) {\n var dirtySub = target.subscribe(this.markDirty, this, 'dirty'),\n changeSub = target.subscribe(this.respondToChange, this);\n return {\n _target: target,\n dispose: function () {\n dirtySub.dispose();\n changeSub.dispose();\n }\n };\n } else {\n return target.subscribe(this.evaluatePossiblyAsync, this);\n }\n },\n evaluatePossiblyAsync: function () {\n var computedObservable = this,\n throttleEvaluationTimeout = computedObservable['throttleEvaluation'];\n if (throttleEvaluationTimeout && throttleEvaluationTimeout >= 0) {\n clearTimeout(this[computedState].evaluationTimeoutInstance);\n this[computedState].evaluationTimeoutInstance = ko.utils.setTimeout(function () {\n computedObservable.evaluateImmediate(true /*notifyChange*/);\n }, throttleEvaluationTimeout);\n } else if (computedObservable._evalDelayed) {\n computedObservable._evalDelayed(true /*isChange*/);\n } else {\n computedObservable.evaluateImmediate(true /*notifyChange*/);\n }\n },\n evaluateImmediate: function (notifyChange) {\n var computedObservable = this,\n state = computedObservable[computedState],\n disposeWhen = state.disposeWhen,\n changed = false;\n\n if (state.isBeingEvaluated) {\n // If the evaluation of a ko.computed causes side effects, it's possible that it will trigger its own re-evaluation.\n // This is not desirable (it's hard for a developer to realise a chain of dependencies might cause this, and they almost\n // certainly didn't intend infinite re-evaluations). So, for predictability, we simply prevent ko.computeds from causing\n // their own re-evaluation. Further discussion at https://github.com/SteveSanderson/knockout/pull/387\n return;\n }\n\n // Do not evaluate (and possibly capture new dependencies) if disposed\n if (state.isDisposed) {\n return;\n }\n\n if (state.disposeWhenNodeIsRemoved && !ko.utils.domNodeIsAttachedToDocument(state.disposeWhenNodeIsRemoved) || disposeWhen && disposeWhen()) {\n // See comment above about suppressDisposalUntilDisposeWhenReturnsFalse\n if (!state.suppressDisposalUntilDisposeWhenReturnsFalse) {\n computedObservable.dispose();\n return;\n }\n } else {\n // It just did return false, so we can stop suppressing now\n state.suppressDisposalUntilDisposeWhenReturnsFalse = false;\n }\n\n state.isBeingEvaluated = true;\n try {\n changed = this.evaluateImmediate_CallReadWithDependencyDetection(notifyChange);\n } finally {\n state.isBeingEvaluated = false;\n }\n\n return changed;\n },\n evaluateImmediate_CallReadWithDependencyDetection: function (notifyChange) {\n // This function is really just part of the evaluateImmediate logic. You would never call it from anywhere else.\n // Factoring it out into a separate function means it can be independent of the try/catch block in evaluateImmediate,\n // which contributes to saving about 40% off the CPU overhead of computed evaluation (on V8 at least).\n\n var computedObservable = this,\n state = computedObservable[computedState],\n changed = false;\n\n // Initially, we assume that none of the subscriptions are still being used (i.e., all are candidates for disposal).\n // Then, during evaluation, we cross off any that are in fact still being used.\n var isInitial = state.pure ? undefined : !state.dependenciesCount, // If we're evaluating when there are no previous dependencies, it must be the first time\n dependencyDetectionContext = {\n computedObservable: computedObservable,\n disposalCandidates: state.dependencyTracking,\n disposalCount: state.dependenciesCount\n };\n\n ko.dependencyDetection.begin({\n callbackTarget: dependencyDetectionContext,\n callback: computedBeginDependencyDetectionCallback,\n computed: computedObservable,\n isInitial: isInitial\n });\n\n state.dependencyTracking = {};\n state.dependenciesCount = 0;\n\n var newValue = this.evaluateImmediate_CallReadThenEndDependencyDetection(state, dependencyDetectionContext);\n\n if (!state.dependenciesCount) {\n computedObservable.dispose();\n changed = true; // When evaluation causes a disposal, make sure all dependent computeds get notified so they'll see the new state\n } else {\n changed = computedObservable.isDifferent(state.latestValue, newValue);\n }\n\n if (changed) {\n if (!state.isSleeping) {\n computedObservable[\"notifySubscribers\"](state.latestValue, \"beforeChange\");\n } else {\n computedObservable.updateVersion();\n }\n\n state.latestValue = newValue;\n if (DEBUG) computedObservable._latestValue = newValue;\n\n computedObservable[\"notifySubscribers\"](state.latestValue, \"spectate\");\n\n if (!state.isSleeping && notifyChange) {\n computedObservable[\"notifySubscribers\"](state.latestValue);\n }\n if (computedObservable._recordUpdate) {\n computedObservable._recordUpdate();\n }\n }\n\n if (isInitial) {\n computedObservable[\"notifySubscribers\"](state.latestValue, \"awake\");\n }\n\n return changed;\n },\n evaluateImmediate_CallReadThenEndDependencyDetection: function (state, dependencyDetectionContext) {\n // This function is really part of the evaluateImmediate_CallReadWithDependencyDetection logic.\n // You'd never call it from anywhere else. Factoring it out means that evaluateImmediate_CallReadWithDependencyDetection\n // can be independent of try/finally blocks, which contributes to saving about 40% off the CPU\n // overhead of computed evaluation (on V8 at least).\n\n try {\n var readFunction = state.readFunction;\n return state.evaluatorFunctionTarget ? readFunction.call(state.evaluatorFunctionTarget) : readFunction();\n } finally {\n ko.dependencyDetection.end();\n\n // For each subscription no longer being used, remove it from the active subscriptions list and dispose it\n if (dependencyDetectionContext.disposalCount && !state.isSleeping) {\n ko.utils.objectForEach(dependencyDetectionContext.disposalCandidates, computedDisposeDependencyCallback);\n }\n\n state.isStale = state.isDirty = false;\n }\n },\n peek: function (evaluate) {\n // By default, peek won't re-evaluate, except while the computed is sleeping or to get the initial value when \"deferEvaluation\" is set.\n // Pass in true to evaluate if needed.\n var state = this[computedState];\n if ((state.isDirty && (evaluate || !state.dependenciesCount)) || (state.isSleeping && this.haveDependenciesChanged())) {\n this.evaluateImmediate();\n }\n return state.latestValue;\n },\n limit: function (limitFunction) {\n // Override the limit function with one that delays evaluation as well\n ko.subscribable['fn'].limit.call(this, limitFunction);\n this._evalIfChanged = function () {\n if (!this[computedState].isSleeping) {\n if (this[computedState].isStale) {\n this.evaluateImmediate();\n } else {\n this[computedState].isDirty = false;\n }\n }\n return this[computedState].latestValue;\n };\n this._evalDelayed = function (isChange) {\n this._limitBeforeChange(this[computedState].latestValue);\n\n // Mark as dirty\n this[computedState].isDirty = true;\n if (isChange) {\n this[computedState].isStale = true;\n }\n\n // Pass the observable to the \"limit\" code, which will evaluate it when\n // it's time to do the notification.\n this._limitChange(this, !isChange /* isDirty */);\n };\n },\n dispose: function () {\n var state = this[computedState];\n if (!state.isSleeping && state.dependencyTracking) {\n ko.utils.objectForEach(state.dependencyTracking, function (id, dependency) {\n if (dependency.dispose)\n dependency.dispose();\n });\n }\n if (state.disposeWhenNodeIsRemoved && state.domNodeDisposalCallback) {\n ko.utils.domNodeDisposal.removeDisposeCallback(state.disposeWhenNodeIsRemoved, state.domNodeDisposalCallback);\n }\n state.dependencyTracking = undefined;\n state.dependenciesCount = 0;\n state.isDisposed = true;\n state.isStale = false;\n state.isDirty = false;\n state.isSleeping = false;\n state.disposeWhenNodeIsRemoved = undefined;\n state.disposeWhen = undefined;\n state.readFunction = undefined;\n if (!this.hasWriteFunction) {\n state.evaluatorFunctionTarget = undefined;\n }\n }\n };\n\n var pureComputedOverrides = {\n beforeSubscriptionAdd: function (event) {\n // If asleep, wake up the computed by subscribing to any dependencies.\n var computedObservable = this,\n state = computedObservable[computedState];\n if (!state.isDisposed && state.isSleeping && event == 'change') {\n state.isSleeping = false;\n if (state.isStale || computedObservable.haveDependenciesChanged()) {\n state.dependencyTracking = null;\n state.dependenciesCount = 0;\n if (computedObservable.evaluateImmediate()) {\n computedObservable.updateVersion();\n }\n } else {\n // First put the dependencies in order\n var dependenciesOrder = [];\n ko.utils.objectForEach(state.dependencyTracking, function (id, dependency) {\n dependenciesOrder[dependency._order] = id;\n });\n // Next, subscribe to each one\n ko.utils.arrayForEach(dependenciesOrder, function (id, order) {\n var dependency = state.dependencyTracking[id],\n subscription = computedObservable.subscribeToDependency(dependency._target);\n subscription._order = order;\n subscription._version = dependency._version;\n state.dependencyTracking[id] = subscription;\n });\n // Waking dependencies may have triggered effects\n if (computedObservable.haveDependenciesChanged()) {\n if (computedObservable.evaluateImmediate()) {\n computedObservable.updateVersion();\n }\n }\n }\n\n if (!state.isDisposed) { // test since evaluating could trigger disposal\n computedObservable[\"notifySubscribers\"](state.latestValue, \"awake\");\n }\n }\n },\n afterSubscriptionRemove: function (event) {\n var state = this[computedState];\n if (!state.isDisposed && event == 'change' && !this.hasSubscriptionsForEvent('change')) {\n ko.utils.objectForEach(state.dependencyTracking, function (id, dependency) {\n if (dependency.dispose) {\n state.dependencyTracking[id] = {\n _target: dependency._target,\n _order: dependency._order,\n _version: dependency._version\n };\n dependency.dispose();\n }\n });\n state.isSleeping = true;\n this[\"notifySubscribers\"](undefined, \"asleep\");\n }\n },\n getVersion: function () {\n // Because a pure computed is not automatically updated while it is sleeping, we can't\n // simply return the version number. Instead, we check if any of the dependencies have\n // changed and conditionally re-evaluate the computed observable.\n var state = this[computedState];\n if (state.isSleeping && (state.isStale || this.haveDependenciesChanged())) {\n this.evaluateImmediate();\n }\n return ko.subscribable['fn'].getVersion.call(this);\n }\n };\n\n var deferEvaluationOverrides = {\n beforeSubscriptionAdd: function (event) {\n // This will force a computed with deferEvaluation to evaluate when the first subscription is registered.\n if (event == 'change' || event == 'beforeChange') {\n this.peek();\n }\n }\n };\n\n// Note that for browsers that don't support proto assignment, the\n// inheritance chain is created manually in the ko.computed constructor\n if (ko.utils.canSetPrototype) {\n ko.utils.setPrototypeOf(computedFn, ko.subscribable['fn']);\n }\n\n// Set the proto values for ko.computed\n var protoProp = ko.observable.protoProperty; // == \"__ko_proto__\"\n computedFn[protoProp] = ko.computed;\n\n ko.isComputed = function (instance) {\n return (typeof instance == 'function' && instance[protoProp] === computedFn[protoProp]);\n };\n\n ko.isPureComputed = function (instance) {\n return ko.isComputed(instance) && instance[computedState] && instance[computedState].pure;\n };\n\n ko.exportSymbol('computed', ko.computed);\n ko.exportSymbol('dependentObservable', ko.computed); // export ko.dependentObservable for backwards compatibility (1.x)\n ko.exportSymbol('isComputed', ko.isComputed);\n ko.exportSymbol('isPureComputed', ko.isPureComputed);\n ko.exportSymbol('computed.fn', computedFn);\n ko.exportProperty(computedFn, 'peek', computedFn.peek);\n ko.exportProperty(computedFn, 'dispose', computedFn.dispose);\n ko.exportProperty(computedFn, 'isActive', computedFn.isActive);\n ko.exportProperty(computedFn, 'getDependenciesCount', computedFn.getDependenciesCount);\n ko.exportProperty(computedFn, 'getDependencies', computedFn.getDependencies);\n\n ko.pureComputed = function (evaluatorFunctionOrOptions, evaluatorFunctionTarget) {\n if (typeof evaluatorFunctionOrOptions === 'function') {\n return ko.computed(evaluatorFunctionOrOptions, evaluatorFunctionTarget, {'pure':true});\n } else {\n evaluatorFunctionOrOptions = ko.utils.extend({}, evaluatorFunctionOrOptions); // make a copy of the parameter object\n evaluatorFunctionOrOptions['pure'] = true;\n return ko.computed(evaluatorFunctionOrOptions, evaluatorFunctionTarget);\n }\n }\n ko.exportSymbol('pureComputed', ko.pureComputed);\n\n (function() {\n var maxNestedObservableDepth = 10; // Escape the (unlikely) pathological case where an observable's current value is itself (or similar reference cycle)\n\n ko.toJS = function(rootObject) {\n if (arguments.length == 0)\n throw new Error(\"When calling ko.toJS, pass the object you want to convert.\");\n\n // We just unwrap everything at every level in the object graph\n return mapJsObjectGraph(rootObject, function(valueToMap) {\n // Loop because an observable's value might in turn be another observable wrapper\n for (var i = 0; ko.isObservable(valueToMap) && (i < maxNestedObservableDepth); i++)\n valueToMap = valueToMap();\n return valueToMap;\n });\n };\n\n ko.toJSON = function(rootObject, replacer, space) { // replacer and space are optional\n var plainJavaScriptObject = ko.toJS(rootObject);\n return ko.utils.stringifyJson(plainJavaScriptObject, replacer, space);\n };\n\n function mapJsObjectGraph(rootObject, mapInputCallback, visitedObjects) {\n visitedObjects = visitedObjects || new objectLookup();\n\n rootObject = mapInputCallback(rootObject);\n var canHaveProperties = (typeof rootObject == \"object\") && (rootObject !== null) && (rootObject !== undefined) && (!(rootObject instanceof RegExp)) && (!(rootObject instanceof Date)) && (!(rootObject instanceof String)) && (!(rootObject instanceof Number)) && (!(rootObject instanceof Boolean));\n if (!canHaveProperties)\n return rootObject;\n\n var outputProperties = rootObject instanceof Array ? [] : {};\n visitedObjects.save(rootObject, outputProperties);\n\n visitPropertiesOrArrayEntries(rootObject, function(indexer) {\n var propertyValue = mapInputCallback(rootObject[indexer]);\n\n switch (typeof propertyValue) {\n case \"boolean\":\n case \"number\":\n case \"string\":\n case \"function\":\n outputProperties[indexer] = propertyValue;\n break;\n case \"object\":\n case \"undefined\":\n var previouslyMappedValue = visitedObjects.get(propertyValue);\n outputProperties[indexer] = (previouslyMappedValue !== undefined)\n ? previouslyMappedValue\n : mapJsObjectGraph(propertyValue, mapInputCallback, visitedObjects);\n break;\n }\n });\n\n return outputProperties;\n }\n\n function visitPropertiesOrArrayEntries(rootObject, visitorCallback) {\n if (rootObject instanceof Array) {\n for (var i = 0; i < rootObject.length; i++)\n visitorCallback(i);\n\n // For arrays, also respect toJSON property for custom mappings (fixes #278)\n if (typeof rootObject['toJSON'] == 'function')\n visitorCallback('toJSON');\n } else {\n for (var propertyName in rootObject) {\n visitorCallback(propertyName);\n }\n }\n };\n\n function objectLookup() {\n this.keys = [];\n this.values = [];\n };\n\n objectLookup.prototype = {\n constructor: objectLookup,\n save: function(key, value) {\n var existingIndex = ko.utils.arrayIndexOf(this.keys, key);\n if (existingIndex >= 0)\n this.values[existingIndex] = value;\n else {\n this.keys.push(key);\n this.values.push(value);\n }\n },\n get: function(key) {\n var existingIndex = ko.utils.arrayIndexOf(this.keys, key);\n return (existingIndex >= 0) ? this.values[existingIndex] : undefined;\n }\n };\n })();\n\n ko.exportSymbol('toJS', ko.toJS);\n ko.exportSymbol('toJSON', ko.toJSON);\n ko.when = function(predicate, callback, context) {\n function kowhen (resolve) {\n var observable = ko.pureComputed(predicate, context).extend({notify:'always'});\n var subscription = observable.subscribe(function(value) {\n if (value) {\n subscription.dispose();\n resolve(value);\n }\n });\n // In case the initial value is true, process it right away\n observable['notifySubscribers'](observable.peek());\n\n return subscription;\n }\n if (typeof Promise === \"function\" && !callback) {\n return new Promise(kowhen);\n } else {\n return kowhen(callback.bind(context));\n }\n };\n\n ko.exportSymbol('when', ko.when);\n (function () {\n var hasDomDataExpandoProperty = '__ko__hasDomDataOptionValue__';\n\n // Normally, SELECT elements and their OPTIONs can only take value of type 'string' (because the values\n // are stored on DOM attributes). ko.selectExtensions provides a way for SELECTs/OPTIONs to have values\n // that are arbitrary objects. This is very convenient when implementing things like cascading dropdowns.\n ko.selectExtensions = {\n readValue : function(element) {\n switch (ko.utils.tagNameLower(element)) {\n case 'option':\n if (element[hasDomDataExpandoProperty] === true)\n return ko.utils.domData.get(element, ko.bindingHandlers.options.optionValueDomDataKey);\n return ko.utils.ieVersion <= 7\n ? (element.getAttributeNode('value') && element.getAttributeNode('value').specified ? element.value : element.text)\n : element.value;\n case 'select':\n return element.selectedIndex >= 0 ? ko.selectExtensions.readValue(element.options[element.selectedIndex]) : undefined;\n default:\n return element.value;\n }\n },\n\n writeValue: function(element, value, allowUnset) {\n switch (ko.utils.tagNameLower(element)) {\n case 'option':\n if (typeof value === \"string\") {\n ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, undefined);\n if (hasDomDataExpandoProperty in element) { // IE <= 8 throws errors if you delete non-existent properties from a DOM node\n delete element[hasDomDataExpandoProperty];\n }\n element.value = value;\n }\n else {\n // Store arbitrary object using DomData\n ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, value);\n element[hasDomDataExpandoProperty] = true;\n\n // Special treatment of numbers is just for backward compatibility. KO 1.2.1 wrote numerical values to element.value.\n element.value = typeof value === \"number\" ? value : \"\";\n }\n break;\n case 'select':\n if (value === \"\" || value === null) // A blank string or null value will select the caption\n value = undefined;\n var selection = -1;\n for (var i = 0, n = element.options.length, optionValue; i < n; ++i) {\n optionValue = ko.selectExtensions.readValue(element.options[i]);\n // Include special check to handle selecting a caption with a blank string value\n if (optionValue == value || (optionValue === \"\" && value === undefined)) {\n selection = i;\n break;\n }\n }\n if (allowUnset || selection >= 0 || (value === undefined && element.size > 1)) {\n element.selectedIndex = selection;\n if (ko.utils.ieVersion === 6) {\n // Workaround for IE6 bug: It won't reliably apply values to SELECT nodes during the same execution thread\n // right after you've changed the set of OPTION nodes on it. So for that node type, we'll schedule a second thread\n // to apply the value as well.\n ko.utils.setTimeout(function () {\n element.selectedIndex = selection;\n }, 0);\n }\n }\n break;\n default:\n if ((value === null) || (value === undefined))\n value = \"\";\n element.value = value;\n break;\n }\n }\n };\n })();\n\n ko.exportSymbol('selectExtensions', ko.selectExtensions);\n ko.exportSymbol('selectExtensions.readValue', ko.selectExtensions.readValue);\n ko.exportSymbol('selectExtensions.writeValue', ko.selectExtensions.writeValue);\n ko.expressionRewriting = (function () {\n var javaScriptReservedWords = [\"true\", \"false\", \"null\", \"undefined\"];\n\n // Matches something that can be assigned to--either an isolated identifier or something ending with a property accessor\n // This is designed to be simple and avoid false negatives, but could produce false positives (e.g., a+b.c).\n // This also will not properly handle nested brackets (e.g., obj1[obj2['prop']]; see #911).\n var javaScriptAssignmentTarget = /^(?:[$_a-z][$\\w]*|(.+)(\\.\\s*[$_a-z][$\\w]*|\\[.+\\]))$/i;\n\n function getWriteableValue(expression) {\n if (ko.utils.arrayIndexOf(javaScriptReservedWords, expression) >= 0)\n return false;\n var match = expression.match(javaScriptAssignmentTarget);\n return match === null ? false : match[1] ? ('Object(' + match[1] + ')' + match[2]) : expression;\n }\n\n // The following regular expressions will be used to split an object-literal string into tokens\n\n var specials = ',\"\\'`{}()/:[\\\\]', // These characters have special meaning to the parser and must not appear in the middle of a token, except as part of a string.\n // Create the actual regular expression by or-ing the following regex strings. The order is important.\n bindingToken = RegExp([\n // These match strings, either with double quotes, single quotes, or backticks\n '\"(?:\\\\\\\\.|[^\"])*\"',\n \"'(?:\\\\\\\\.|[^'])*'\",\n \"`(?:\\\\\\\\.|[^`])*`\",\n // Match C style comments\n \"/\\\\*(?:[^*]|\\\\*+[^*/])*\\\\*+/\",\n // Match C++ style comments\n \"//.*\\n\",\n // Match a regular expression (text enclosed by slashes), but will also match sets of divisions\n // as a regular expression (this is handled by the parsing loop below).\n '/(?:\\\\\\\\.|[^/])+/\\w*',\n // Match text (at least two characters) that does not contain any of the above special characters,\n // although some of the special characters are allowed to start it (all but the colon and comma).\n // The text can contain spaces, but leading or trailing spaces are skipped.\n '[^\\\\s:,/][^' + specials + ']*[^\\\\s' + specials + ']',\n // Match any non-space character not matched already. This will match colons and commas, since they're\n // not matched by \"everyThingElse\", but will also match any other single character that wasn't already\n // matched (for example: in \"a: 1, b: 2\", each of the non-space characters will be matched by oneNotSpace).\n '[^\\\\s]'\n ].join('|'), 'g'),\n\n // Match end of previous token to determine whether a slash is a division or regex.\n divisionLookBehind = /[\\])\"'A-Za-z0-9_$]+$/,\n keywordRegexLookBehind = {'in':1,'return':1,'typeof':1};\n\n function parseObjectLiteral(objectLiteralString) {\n // Trim leading and trailing spaces from the string\n var str = ko.utils.stringTrim(objectLiteralString);\n\n // Trim braces '{' surrounding the whole object literal\n if (str.charCodeAt(0) === 123) str = str.slice(1, -1);\n\n // Add a newline to correctly match a C++ style comment at the end of the string and\n // add a comma so that we don't need a separate code block to deal with the last item\n str += \"\\n,\";\n\n // Split into tokens\n var result = [], toks = str.match(bindingToken), key, values = [], depth = 0;\n\n if (toks.length > 1) {\n for (var i = 0, tok; tok = toks[i]; ++i) {\n var c = tok.charCodeAt(0);\n // A comma signals the end of a key/value pair if depth is zero\n if (c === 44) { // \",\"\n if (depth <= 0) {\n result.push((key && values.length) ? {key: key, value: values.join('')} : {'unknown': key || values.join('')});\n key = depth = 0;\n values = [];\n continue;\n }\n // Simply skip the colon that separates the name and value\n } else if (c === 58) { // \":\"\n if (!depth && !key && values.length === 1) {\n key = values.pop();\n continue;\n }\n // Comments: skip them\n } else if (c === 47 && tok.length > 1 && (tok.charCodeAt(1) === 47 || tok.charCodeAt(1) === 42)) { // \"//\" or \"/*\"\n continue;\n // A set of slashes is initially matched as a regular expression, but could be division\n } else if (c === 47 && i && tok.length > 1) { // \"/\"\n // Look at the end of the previous token to determine if the slash is actually division\n var match = toks[i-1].match(divisionLookBehind);\n if (match && !keywordRegexLookBehind[match[0]]) {\n // The slash is actually a division punctuator; re-parse the remainder of the string (not including the slash)\n str = str.substr(str.indexOf(tok) + 1);\n toks = str.match(bindingToken);\n i = -1;\n // Continue with just the slash\n tok = '/';\n }\n // Increment depth for parentheses, braces, and brackets so that interior commas are ignored\n } else if (c === 40 || c === 123 || c === 91) { // '(', '{', '['\n ++depth;\n } else if (c === 41 || c === 125 || c === 93) { // ')', '}', ']'\n --depth;\n // The key will be the first token; if it's a string, trim the quotes\n } else if (!key && !values.length && (c === 34 || c === 39)) { // '\"', \"'\"\n tok = tok.slice(1, -1);\n }\n values.push(tok);\n }\n if (depth > 0) {\n throw Error(\"Unbalanced parentheses, braces, or brackets\");\n }\n }\n return result;\n }\n\n // Two-way bindings include a write function that allow the handler to update the value even if it's not an observable.\n var twoWayBindings = {};\n\n function preProcessBindings(bindingsStringOrKeyValueArray, bindingOptions) {\n bindingOptions = bindingOptions || {};\n\n function processKeyValue(key, val) {\n var writableVal;\n function callPreprocessHook(obj) {\n return (obj && obj['preprocess']) ? (val = obj['preprocess'](val, key, processKeyValue)) : true;\n }\n if (!bindingParams) {\n if (!callPreprocessHook(ko['getBindingHandler'](key)))\n return;\n\n if (twoWayBindings[key] && (writableVal = getWriteableValue(val))) {\n // For two-way bindings, provide a write method in case the value\n // isn't a writable observable.\n var writeKey = typeof twoWayBindings[key] == 'string' ? twoWayBindings[key] : key;\n propertyAccessorResultStrings.push(\"'\" + writeKey + \"':function(_z){\" + writableVal + \"=_z}\");\n }\n }\n // Values are wrapped in a function so that each value can be accessed independently\n if (makeValueAccessors) {\n val = 'function(){return ' + val + ' }';\n }\n resultStrings.push(\"'\" + key + \"':\" + val);\n }\n\n var resultStrings = [],\n propertyAccessorResultStrings = [],\n makeValueAccessors = bindingOptions['valueAccessors'],\n bindingParams = bindingOptions['bindingParams'],\n keyValueArray = typeof bindingsStringOrKeyValueArray === \"string\" ?\n parseObjectLiteral(bindingsStringOrKeyValueArray) : bindingsStringOrKeyValueArray;\n\n ko.utils.arrayForEach(keyValueArray, function(keyValue) {\n processKeyValue(keyValue.key || keyValue['unknown'], keyValue.value);\n });\n\n if (propertyAccessorResultStrings.length)\n processKeyValue('_ko_property_writers', \"{\" + propertyAccessorResultStrings.join(\",\") + \" }\");\n\n return resultStrings.join(\",\");\n }\n\n return {\n bindingRewriteValidators: [],\n\n twoWayBindings: twoWayBindings,\n\n parseObjectLiteral: parseObjectLiteral,\n\n preProcessBindings: preProcessBindings,\n\n keyValueArrayContainsKey: function(keyValueArray, key) {\n for (var i = 0; i < keyValueArray.length; i++)\n if (keyValueArray[i]['key'] == key)\n return true;\n return false;\n },\n\n // Internal, private KO utility for updating model properties from within bindings\n // property: If the property being updated is (or might be) an observable, pass it here\n // If it turns out to be a writable observable, it will be written to directly\n // allBindings: An object with a get method to retrieve bindings in the current execution context.\n // This will be searched for a '_ko_property_writers' property in case you're writing to a non-observable\n // key: The key identifying the property to be written. Example: for { hasFocus: myValue }, write to 'myValue' by specifying the key 'hasFocus'\n // value: The value to be written\n // checkIfDifferent: If true, and if the property being written is a writable observable, the value will only be written if\n // it is !== existing value on that writable observable\n writeValueToProperty: function(property, allBindings, key, value, checkIfDifferent) {\n if (!property || !ko.isObservable(property)) {\n var propWriters = allBindings.get('_ko_property_writers');\n if (propWriters && propWriters[key])\n propWriters[key](value);\n } else if (ko.isWriteableObservable(property) && (!checkIfDifferent || property.peek() !== value)) {\n property(value);\n }\n }\n };\n })();\n\n ko.exportSymbol('expressionRewriting', ko.expressionRewriting);\n ko.exportSymbol('expressionRewriting.bindingRewriteValidators', ko.expressionRewriting.bindingRewriteValidators);\n ko.exportSymbol('expressionRewriting.parseObjectLiteral', ko.expressionRewriting.parseObjectLiteral);\n ko.exportSymbol('expressionRewriting.preProcessBindings', ko.expressionRewriting.preProcessBindings);\n\n// Making bindings explicitly declare themselves as \"two way\" isn't ideal in the long term (it would be better if\n// all bindings could use an official 'property writer' API without needing to declare that they might). However,\n// since this is not, and has never been, a public API (_ko_property_writers was never documented), it's acceptable\n// as an internal implementation detail in the short term.\n// For those developers who rely on _ko_property_writers in their custom bindings, we expose _twoWayBindings as an\n// undocumented feature that makes it relatively easy to upgrade to KO 3.0. However, this is still not an official\n// public API, and we reserve the right to remove it at any time if we create a real public property writers API.\n ko.exportSymbol('expressionRewriting._twoWayBindings', ko.expressionRewriting.twoWayBindings);\n\n// For backward compatibility, define the following aliases. (Previously, these function names were misleading because\n// they referred to JSON specifically, even though they actually work with arbitrary JavaScript object literal expressions.)\n ko.exportSymbol('jsonExpressionRewriting', ko.expressionRewriting);\n ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.expressionRewriting.preProcessBindings);\n (function() {\n // \"Virtual elements\" is an abstraction on top of the usual DOM API which understands the notion that comment nodes\n // may be used to represent hierarchy (in addition to the DOM's natural hierarchy).\n // If you call the DOM-manipulating functions on ko.virtualElements, you will be able to read and write the state\n // of that virtual hierarchy\n //\n // The point of all this is to support containerless templates (e.g., <!-- ko foreach:someCollection -->blah<!-- /ko -->)\n // without having to scatter special cases all over the binding and templating code.\n\n // IE 9 cannot reliably read the \"nodeValue\" property of a comment node (see https://github.com/SteveSanderson/knockout/issues/186)\n // but it does give them a nonstandard alternative property called \"text\" that it can read reliably. Other browsers don't have that property.\n // So, use node.text where available, and node.nodeValue elsewhere\n var commentNodesHaveTextProperty = document && document.createComment(\"test\").text === \"<!--test-->\";\n\n var startCommentRegex = commentNodesHaveTextProperty ? /^<!--\\s*ko(?:\\s+([\\s\\S]+))?\\s*-->$/ : /^\\s*ko(?:\\s+([\\s\\S]+))?\\s*$/;\n var endCommentRegex = commentNodesHaveTextProperty ? /^<!--\\s*\\/ko\\s*-->$/ : /^\\s*\\/ko\\s*$/;\n var htmlTagsWithOptionallyClosingChildren = { 'ul': true, 'ol': true };\n\n function isStartComment(node) {\n return (node.nodeType == 8) && startCommentRegex.test(commentNodesHaveTextProperty ? node.text : node.nodeValue);\n }\n\n function isEndComment(node) {\n return (node.nodeType == 8) && endCommentRegex.test(commentNodesHaveTextProperty ? node.text : node.nodeValue);\n }\n\n function isUnmatchedEndComment(node) {\n return isEndComment(node) && !(ko.utils.domData.get(node, matchedEndCommentDataKey));\n }\n\n var matchedEndCommentDataKey = \"__ko_matchedEndComment__\"\n\n function getVirtualChildren(startComment, allowUnbalanced) {\n var currentNode = startComment;\n var depth = 1;\n var children = [];\n while (currentNode = currentNode.nextSibling) {\n if (isEndComment(currentNode)) {\n ko.utils.domData.set(currentNode, matchedEndCommentDataKey, true);\n depth--;\n if (depth === 0)\n return children;\n }\n\n children.push(currentNode);\n\n if (isStartComment(currentNode))\n depth++;\n }\n if (!allowUnbalanced)\n throw new Error(\"Cannot find closing comment tag to match: \" + startComment.nodeValue);\n return null;\n }\n\n function getMatchingEndComment(startComment, allowUnbalanced) {\n var allVirtualChildren = getVirtualChildren(startComment, allowUnbalanced);\n if (allVirtualChildren) {\n if (allVirtualChildren.length > 0)\n return allVirtualChildren[allVirtualChildren.length - 1].nextSibling;\n return startComment.nextSibling;\n } else\n return null; // Must have no matching end comment, and allowUnbalanced is true\n }\n\n function getUnbalancedChildTags(node) {\n // e.g., from <div>OK</div><!-- ko blah --><span>Another</span>, returns: <!-- ko blah --><span>Another</span>\n // from <div>OK</div><!-- /ko --><!-- /ko -->, returns: <!-- /ko --><!-- /ko -->\n var childNode = node.firstChild, captureRemaining = null;\n if (childNode) {\n do {\n if (captureRemaining) // We already hit an unbalanced node and are now just scooping up all subsequent nodes\n captureRemaining.push(childNode);\n else if (isStartComment(childNode)) {\n var matchingEndComment = getMatchingEndComment(childNode, /* allowUnbalanced: */ true);\n if (matchingEndComment) // It's a balanced tag, so skip immediately to the end of this virtual set\n childNode = matchingEndComment;\n else\n captureRemaining = [childNode]; // It's unbalanced, so start capturing from this point\n } else if (isEndComment(childNode)) {\n captureRemaining = [childNode]; // It's unbalanced (if it wasn't, we'd have skipped over it already), so start capturing\n }\n } while (childNode = childNode.nextSibling);\n }\n return captureRemaining;\n }\n\n ko.virtualElements = {\n allowedBindings: {},\n\n childNodes: function(node) {\n return isStartComment(node) ? getVirtualChildren(node) : node.childNodes;\n },\n\n emptyNode: function(node) {\n if (!isStartComment(node))\n ko.utils.emptyDomNode(node);\n else {\n var virtualChildren = ko.virtualElements.childNodes(node);\n for (var i = 0, j = virtualChildren.length; i < j; i++)\n ko.removeNode(virtualChildren[i]);\n }\n },\n\n setDomNodeChildren: function(node, childNodes) {\n if (!isStartComment(node))\n ko.utils.setDomNodeChildren(node, childNodes);\n else {\n ko.virtualElements.emptyNode(node);\n var endCommentNode = node.nextSibling; // Must be the next sibling, as we just emptied the children\n for (var i = 0, j = childNodes.length; i < j; i++)\n endCommentNode.parentNode.insertBefore(childNodes[i], endCommentNode);\n }\n },\n\n prepend: function(containerNode, nodeToPrepend) {\n var insertBeforeNode;\n\n if (isStartComment(containerNode)) {\n // Start comments must always have a parent and at least one following sibling (the end comment)\n insertBeforeNode = containerNode.nextSibling;\n containerNode = containerNode.parentNode;\n } else {\n insertBeforeNode = containerNode.firstChild;\n }\n\n if (!insertBeforeNode) {\n containerNode.appendChild(nodeToPrepend);\n } else if (nodeToPrepend !== insertBeforeNode) { // IE will sometimes crash if you try to insert a node before itself\n containerNode.insertBefore(nodeToPrepend, insertBeforeNode);\n }\n },\n\n insertAfter: function(containerNode, nodeToInsert, insertAfterNode) {\n if (!insertAfterNode) {\n ko.virtualElements.prepend(containerNode, nodeToInsert);\n } else {\n // Children of start comments must always have a parent and at least one following sibling (the end comment)\n var insertBeforeNode = insertAfterNode.nextSibling;\n\n if (isStartComment(containerNode)) {\n containerNode = containerNode.parentNode;\n }\n\n if (!insertBeforeNode) {\n containerNode.appendChild(nodeToInsert);\n } else if (nodeToInsert !== insertBeforeNode) { // IE will sometimes crash if you try to insert a node before itself\n containerNode.insertBefore(nodeToInsert, insertBeforeNode);\n }\n }\n },\n\n firstChild: function(node) {\n if (!isStartComment(node)) {\n if (node.firstChild && isEndComment(node.firstChild)) {\n throw new Error(\"Found invalid end comment, as the first child of \" + node);\n }\n return node.firstChild;\n } else if (!node.nextSibling || isEndComment(node.nextSibling)) {\n return null;\n } else {\n return node.nextSibling;\n }\n },\n\n nextSibling: function(node) {\n if (isStartComment(node)) {\n node = getMatchingEndComment(node);\n }\n\n if (node.nextSibling && isEndComment(node.nextSibling)) {\n if (isUnmatchedEndComment(node.nextSibling)) {\n throw Error(\"Found end comment without a matching opening comment, as child of \" + node);\n } else {\n return null;\n }\n } else {\n return node.nextSibling;\n }\n },\n\n hasBindingValue: isStartComment,\n\n virtualNodeBindingValue: function(node) {\n var regexMatch = (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(startCommentRegex);\n return regexMatch ? regexMatch[1] : null;\n },\n\n normaliseVirtualElementDomStructure: function(elementVerified) {\n // Workaround for https://github.com/SteveSanderson/knockout/issues/155\n // (IE <= 8 or IE 9 quirks mode parses your HTML weirdly, treating closing </li> tags as if they don't exist, thereby moving comment nodes\n // that are direct descendants of <ul> into the preceding <li>)\n if (!htmlTagsWithOptionallyClosingChildren[ko.utils.tagNameLower(elementVerified)])\n return;\n\n // Scan immediate children to see if they contain unbalanced comment tags. If they do, those comment tags\n // must be intended to appear *after* that child, so move them there.\n var childNode = elementVerified.firstChild;\n if (childNode) {\n do {\n if (childNode.nodeType === 1) {\n var unbalancedTags = getUnbalancedChildTags(childNode);\n if (unbalancedTags) {\n // Fix up the DOM by moving the unbalanced tags to where they most likely were intended to be placed - *after* the child\n var nodeToInsertBefore = childNode.nextSibling;\n for (var i = 0; i < unbalancedTags.length; i++) {\n if (nodeToInsertBefore)\n elementVerified.insertBefore(unbalancedTags[i], nodeToInsertBefore);\n else\n elementVerified.appendChild(unbalancedTags[i]);\n }\n }\n }\n } while (childNode = childNode.nextSibling);\n }\n }\n };\n })();\n ko.exportSymbol('virtualElements', ko.virtualElements);\n ko.exportSymbol('virtualElements.allowedBindings', ko.virtualElements.allowedBindings);\n ko.exportSymbol('virtualElements.emptyNode', ko.virtualElements.emptyNode);\n//ko.exportSymbol('virtualElements.firstChild', ko.virtualElements.firstChild); // firstChild is not minified\n ko.exportSymbol('virtualElements.insertAfter', ko.virtualElements.insertAfter);\n//ko.exportSymbol('virtualElements.nextSibling', ko.virtualElements.nextSibling); // nextSibling is not minified\n ko.exportSymbol('virtualElements.prepend', ko.virtualElements.prepend);\n ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomNodeChildren);\n (function() {\n var defaultBindingAttributeName = \"data-bind\";\n\n ko.bindingProvider = function() {\n this.bindingCache = {};\n };\n\n ko.utils.extend(ko.bindingProvider.prototype, {\n 'nodeHasBindings': function(node) {\n switch (node.nodeType) {\n case 1: // Element\n return node.getAttribute(defaultBindingAttributeName) != null\n || ko.components['getComponentNameForNode'](node);\n case 8: // Comment node\n return ko.virtualElements.hasBindingValue(node);\n default: return false;\n }\n },\n\n 'getBindings': function(node, bindingContext) {\n var bindingsString = this['getBindingsString'](node, bindingContext),\n parsedBindings = bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node) : null;\n return ko.components.addBindingsForCustomElement(parsedBindings, node, bindingContext, /* valueAccessors */ false);\n },\n\n 'getBindingAccessors': function(node, bindingContext) {\n var bindingsString = this['getBindingsString'](node, bindingContext),\n parsedBindings = bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node, { 'valueAccessors': true }) : null;\n return ko.components.addBindingsForCustomElement(parsedBindings, node, bindingContext, /* valueAccessors */ true);\n },\n\n // The following function is only used internally by this default provider.\n // It's not part of the interface definition for a general binding provider.\n 'getBindingsString': function(node, bindingContext) {\n switch (node.nodeType) {\n case 1: return node.getAttribute(defaultBindingAttributeName); // Element\n case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node\n default: return null;\n }\n },\n\n // The following function is only used internally by this default provider.\n // It's not part of the interface definition for a general binding provider.\n 'parseBindingsString': function(bindingsString, bindingContext, node, options) {\n try {\n var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, this.bindingCache, options);\n return bindingFunction(bindingContext, node);\n } catch (ex) {\n ex.message = \"Unable to parse bindings.\\nBindings value: \" + bindingsString + \"\\nMessage: \" + ex.message;\n throw ex;\n }\n }\n });\n\n ko.bindingProvider['instance'] = new ko.bindingProvider();\n\n function createBindingsStringEvaluatorViaCache(bindingsString, cache, options) {\n var cacheKey = bindingsString + (options && options['valueAccessors'] || '');\n return cache[cacheKey]\n || (cache[cacheKey] = createBindingsStringEvaluator(bindingsString, options));\n }\n\n function createBindingsStringEvaluator(bindingsString, options) {\n // Build the source for a function that evaluates \"expression\"\n // For each scope variable, add an extra level of \"with\" nesting\n // Example result: with(sc1) { with(sc0) { return (expression) } }\n var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString, options),\n functionBody = \"with($context){with($data||{}){return{\" + rewrittenBindings + \"}}}\";\n return new Function(\"$context\", \"$element\", functionBody);\n }\n })();\n\n ko.exportSymbol('bindingProvider', ko.bindingProvider);\n (function () {\n // Hide or don't minify context properties, see https://github.com/knockout/knockout/issues/2294\n var contextSubscribable = ko.utils.createSymbolOrString('_subscribable');\n var contextAncestorBindingInfo = ko.utils.createSymbolOrString('_ancestorBindingInfo');\n var contextDataDependency = ko.utils.createSymbolOrString('_dataDependency');\n\n ko.bindingHandlers = {};\n\n // The following element types will not be recursed into during binding.\n var bindingDoesNotRecurseIntoElementTypes = {\n // Don't want bindings that operate on text nodes to mutate <script> and <textarea> contents,\n // because it's unexpected and a potential XSS issue.\n // Also bindings should not operate on <template> elements since this breaks in Internet Explorer\n // and because such elements' contents are always intended to be bound in a different context\n // from where they appear in the document.\n 'script': true,\n 'textarea': true,\n 'template': true\n };\n\n // Use an overridable method for retrieving binding handlers so that plugins may support dynamically created handlers\n ko['getBindingHandler'] = function(bindingKey) {\n return ko.bindingHandlers[bindingKey];\n };\n\n var inheritParentVm = {};\n\n // The ko.bindingContext constructor is only called directly to create the root context. For child\n // contexts, use bindingContext.createChildContext or bindingContext.extend.\n ko.bindingContext = function(dataItemOrAccessor, parentContext, dataItemAlias, extendCallback, options) {\n\n // The binding context object includes static properties for the current, parent, and root view models.\n // If a view model is actually stored in an observable, the corresponding binding context object, and\n // any child contexts, must be updated when the view model is changed.\n function updateContext() {\n // Most of the time, the context will directly get a view model object, but if a function is given,\n // we call the function to retrieve the view model. If the function accesses any observables or returns\n // an observable, the dependency is tracked, and those observables can later cause the binding\n // context to be updated.\n var dataItemOrObservable = isFunc ? realDataItemOrAccessor() : realDataItemOrAccessor,\n dataItem = ko.utils.unwrapObservable(dataItemOrObservable);\n\n if (parentContext) {\n // Copy $root and any custom properties from the parent context\n ko.utils.extend(self, parentContext);\n\n // Copy Symbol properties\n if (contextAncestorBindingInfo in parentContext) {\n self[contextAncestorBindingInfo] = parentContext[contextAncestorBindingInfo];\n }\n } else {\n self['$parents'] = [];\n self['$root'] = dataItem;\n\n // Export 'ko' in the binding context so it will be available in bindings and templates\n // even if 'ko' isn't exported as a global, such as when using an AMD loader.\n // See https://github.com/SteveSanderson/knockout/issues/490\n self['ko'] = ko;\n }\n\n self[contextSubscribable] = subscribable;\n\n if (shouldInheritData) {\n dataItem = self['$data'];\n } else {\n self['$rawData'] = dataItemOrObservable;\n self['$data'] = dataItem;\n }\n\n if (dataItemAlias)\n self[dataItemAlias] = dataItem;\n\n // The extendCallback function is provided when creating a child context or extending a context.\n // It handles the specific actions needed to finish setting up the binding context. Actions in this\n // function could also add dependencies to this binding context.\n if (extendCallback)\n extendCallback(self, parentContext, dataItem);\n\n // When a \"parent\" context is given and we don't already have a dependency on its context, register a dependency on it.\n // Thus whenever the parent context is updated, this context will also be updated.\n if (parentContext && parentContext[contextSubscribable] && !ko.computedContext.computed().hasAncestorDependency(parentContext[contextSubscribable])) {\n parentContext[contextSubscribable]();\n }\n\n if (dataDependency) {\n self[contextDataDependency] = dataDependency;\n }\n\n return self['$data'];\n }\n\n var self = this,\n shouldInheritData = dataItemOrAccessor === inheritParentVm,\n realDataItemOrAccessor = shouldInheritData ? undefined : dataItemOrAccessor,\n isFunc = typeof(realDataItemOrAccessor) == \"function\" && !ko.isObservable(realDataItemOrAccessor),\n nodes,\n subscribable,\n dataDependency = options && options['dataDependency'];\n\n if (options && options['exportDependencies']) {\n // The \"exportDependencies\" option means that the calling code will track any dependencies and re-create\n // the binding context when they change.\n updateContext();\n } else {\n subscribable = ko.pureComputed(updateContext);\n subscribable.peek();\n\n // At this point, the binding context has been initialized, and the \"subscribable\" computed observable is\n // subscribed to any observables that were accessed in the process. If there is nothing to track, the\n // computed will be inactive, and we can safely throw it away. If it's active, the computed is stored in\n // the context object.\n if (subscribable.isActive()) {\n // Always notify because even if the model ($data) hasn't changed, other context properties might have changed\n subscribable['equalityComparer'] = null;\n } else {\n self[contextSubscribable] = undefined;\n }\n }\n }\n\n // Extend the binding context hierarchy with a new view model object. If the parent context is watching\n // any observables, the new child context will automatically get a dependency on the parent context.\n // But this does not mean that the $data value of the child context will also get updated. If the child\n // view model also depends on the parent view model, you must provide a function that returns the correct\n // view model on each update.\n ko.bindingContext.prototype['createChildContext'] = function (dataItemOrAccessor, dataItemAlias, extendCallback, options) {\n if (!options && dataItemAlias && typeof dataItemAlias == \"object\") {\n options = dataItemAlias;\n dataItemAlias = options['as'];\n extendCallback = options['extend'];\n }\n\n if (dataItemAlias && options && options['noChildContext']) {\n var isFunc = typeof(dataItemOrAccessor) == \"function\" && !ko.isObservable(dataItemOrAccessor);\n return new ko.bindingContext(inheritParentVm, this, null, function (self) {\n if (extendCallback)\n extendCallback(self);\n self[dataItemAlias] = isFunc ? dataItemOrAccessor() : dataItemOrAccessor;\n }, options);\n }\n\n return new ko.bindingContext(dataItemOrAccessor, this, dataItemAlias, function (self, parentContext) {\n // Extend the context hierarchy by setting the appropriate pointers\n self['$parentContext'] = parentContext;\n self['$parent'] = parentContext['$data'];\n self['$parents'] = (parentContext['$parents'] || []).slice(0);\n self['$parents'].unshift(self['$parent']);\n if (extendCallback)\n extendCallback(self);\n }, options);\n };\n\n // Extend the binding context with new custom properties. This doesn't change the context hierarchy.\n // Similarly to \"child\" contexts, provide a function here to make sure that the correct values are set\n // when an observable view model is updated.\n ko.bindingContext.prototype['extend'] = function(properties, options) {\n return new ko.bindingContext(inheritParentVm, this, null, function(self, parentContext) {\n ko.utils.extend(self, typeof(properties) == \"function\" ? properties(self) : properties);\n }, options);\n };\n\n var boundElementDomDataKey = ko.utils.domData.nextKey();\n\n function asyncContextDispose(node) {\n var bindingInfo = ko.utils.domData.get(node, boundElementDomDataKey),\n asyncContext = bindingInfo && bindingInfo.asyncContext;\n if (asyncContext) {\n bindingInfo.asyncContext = null;\n asyncContext.notifyAncestor();\n }\n }\n function AsyncCompleteContext(node, bindingInfo, ancestorBindingInfo) {\n this.node = node;\n this.bindingInfo = bindingInfo;\n this.asyncDescendants = [];\n this.childrenComplete = false;\n\n if (!bindingInfo.asyncContext) {\n ko.utils.domNodeDisposal.addDisposeCallback(node, asyncContextDispose);\n }\n\n if (ancestorBindingInfo && ancestorBindingInfo.asyncContext) {\n ancestorBindingInfo.asyncContext.asyncDescendants.push(node);\n this.ancestorBindingInfo = ancestorBindingInfo;\n }\n }\n AsyncCompleteContext.prototype.notifyAncestor = function () {\n if (this.ancestorBindingInfo && this.ancestorBindingInfo.asyncContext) {\n this.ancestorBindingInfo.asyncContext.descendantComplete(this.node);\n }\n };\n AsyncCompleteContext.prototype.descendantComplete = function (node) {\n ko.utils.arrayRemoveItem(this.asyncDescendants, node);\n if (!this.asyncDescendants.length && this.childrenComplete) {\n this.completeChildren();\n }\n };\n AsyncCompleteContext.prototype.completeChildren = function () {\n this.childrenComplete = true;\n if (this.bindingInfo.asyncContext && !this.asyncDescendants.length) {\n this.bindingInfo.asyncContext = null;\n ko.utils.domNodeDisposal.removeDisposeCallback(this.node, asyncContextDispose);\n ko.bindingEvent.notify(this.node, ko.bindingEvent.descendantsComplete);\n this.notifyAncestor();\n }\n };\n\n ko.bindingEvent = {\n childrenComplete: \"childrenComplete\",\n descendantsComplete : \"descendantsComplete\",\n\n subscribe: function (node, event, callback, context, options) {\n var bindingInfo = ko.utils.domData.getOrSet(node, boundElementDomDataKey, {});\n if (!bindingInfo.eventSubscribable) {\n bindingInfo.eventSubscribable = new ko.subscribable;\n }\n if (options && options['notifyImmediately'] && bindingInfo.notifiedEvents[event]) {\n ko.dependencyDetection.ignore(callback, context, [node]);\n }\n return bindingInfo.eventSubscribable.subscribe(callback, context, event);\n },\n\n notify: function (node, event) {\n var bindingInfo = ko.utils.domData.get(node, boundElementDomDataKey);\n if (bindingInfo) {\n bindingInfo.notifiedEvents[event] = true;\n if (bindingInfo.eventSubscribable) {\n bindingInfo.eventSubscribable['notifySubscribers'](node, event);\n }\n if (event == ko.bindingEvent.childrenComplete) {\n if (bindingInfo.asyncContext) {\n bindingInfo.asyncContext.completeChildren();\n } else if (bindingInfo.asyncContext === undefined && bindingInfo.eventSubscribable && bindingInfo.eventSubscribable.hasSubscriptionsForEvent(ko.bindingEvent.descendantsComplete)) {\n // It's currently an error to register a descendantsComplete handler for a node that was never registered as completing asynchronously.\n // That's because without the asyncContext, we don't have a way to know that all descendants have completed.\n throw new Error(\"descendantsComplete event not supported for bindings on this node\");\n }\n }\n }\n },\n\n startPossiblyAsyncContentBinding: function (node, bindingContext) {\n var bindingInfo = ko.utils.domData.getOrSet(node, boundElementDomDataKey, {});\n\n if (!bindingInfo.asyncContext) {\n bindingInfo.asyncContext = new AsyncCompleteContext(node, bindingInfo, bindingContext[contextAncestorBindingInfo]);\n }\n\n // If the provided context was already extended with this node's binding info, just return the extended context\n if (bindingContext[contextAncestorBindingInfo] == bindingInfo) {\n return bindingContext;\n }\n\n return bindingContext['extend'](function (ctx) {\n ctx[contextAncestorBindingInfo] = bindingInfo;\n });\n }\n };\n\n // Returns the valueAccessor function for a binding value\n function makeValueAccessor(value) {\n return function() {\n return value;\n };\n }\n\n // Returns the value of a valueAccessor function\n function evaluateValueAccessor(valueAccessor) {\n return valueAccessor();\n }\n\n // Given a function that returns bindings, create and return a new object that contains\n // binding value-accessors functions. Each accessor function calls the original function\n // so that it always gets the latest value and all dependencies are captured. This is used\n // by ko.applyBindingsToNode and getBindingsAndMakeAccessors.\n function makeAccessorsFromFunction(callback) {\n return ko.utils.objectMap(ko.dependencyDetection.ignore(callback), function(value, key) {\n return function() {\n return callback()[key];\n };\n });\n }\n\n // Given a bindings function or object, create and return a new object that contains\n // binding value-accessors functions. This is used by ko.applyBindingsToNode.\n function makeBindingAccessors(bindings, context, node) {\n if (typeof bindings === 'function') {\n return makeAccessorsFromFunction(bindings.bind(null, context, node));\n } else {\n return ko.utils.objectMap(bindings, makeValueAccessor);\n }\n }\n\n // This function is used if the binding provider doesn't include a getBindingAccessors function.\n // It must be called with 'this' set to the provider instance.\n function getBindingsAndMakeAccessors(node, context) {\n return makeAccessorsFromFunction(this['getBindings'].bind(this, node, context));\n }\n\n function validateThatBindingIsAllowedForVirtualElements(bindingName) {\n var validator = ko.virtualElements.allowedBindings[bindingName];\n if (!validator)\n throw new Error(\"The binding '\" + bindingName + \"' cannot be used with virtual elements\")\n }\n\n function applyBindingsToDescendantsInternal(bindingContext, elementOrVirtualElement) {\n var nextInQueue = ko.virtualElements.firstChild(elementOrVirtualElement);\n\n if (nextInQueue) {\n var currentChild,\n provider = ko.bindingProvider['instance'],\n preprocessNode = provider['preprocessNode'];\n\n // Preprocessing allows a binding provider to mutate a node before bindings are applied to it. For example it's\n // possible to insert new siblings after it, and/or replace the node with a different one. This can be used to\n // implement custom binding syntaxes, such as {{ value }} for string interpolation, or custom element types that\n // trigger insertion of <template> contents at that point in the document.\n if (preprocessNode) {\n while (currentChild = nextInQueue) {\n nextInQueue = ko.virtualElements.nextSibling(currentChild);\n preprocessNode.call(provider, currentChild);\n }\n // Reset nextInQueue for the next loop\n nextInQueue = ko.virtualElements.firstChild(elementOrVirtualElement);\n }\n\n while (currentChild = nextInQueue) {\n // Keep a record of the next child *before* applying bindings, in case the binding removes the current child from its position\n nextInQueue = ko.virtualElements.nextSibling(currentChild);\n applyBindingsToNodeAndDescendantsInternal(bindingContext, currentChild);\n }\n }\n ko.bindingEvent.notify(elementOrVirtualElement, ko.bindingEvent.childrenComplete);\n }\n\n function applyBindingsToNodeAndDescendantsInternal(bindingContext, nodeVerified) {\n var bindingContextForDescendants = bindingContext;\n\n var isElement = (nodeVerified.nodeType === 1);\n if (isElement) // Workaround IE <= 8 HTML parsing weirdness\n ko.virtualElements.normaliseVirtualElementDomStructure(nodeVerified);\n\n // Perf optimisation: Apply bindings only if...\n // (1) We need to store the binding info for the node (all element nodes)\n // (2) It might have bindings (e.g., it has a data-bind attribute, or it's a marker for a containerless template)\n var shouldApplyBindings = isElement || ko.bindingProvider['instance']['nodeHasBindings'](nodeVerified);\n if (shouldApplyBindings)\n bindingContextForDescendants = applyBindingsToNodeInternal(nodeVerified, null, bindingContext)['bindingContextForDescendants'];\n\n if (bindingContextForDescendants && !bindingDoesNotRecurseIntoElementTypes[ko.utils.tagNameLower(nodeVerified)]) {\n applyBindingsToDescendantsInternal(bindingContextForDescendants, nodeVerified);\n }\n }\n\n function topologicalSortBindings(bindings) {\n // Depth-first sort\n var result = [], // The list of key/handler pairs that we will return\n bindingsConsidered = {}, // A temporary record of which bindings are already in 'result'\n cyclicDependencyStack = []; // Keeps track of a depth-search so that, if there's a cycle, we know which bindings caused it\n ko.utils.objectForEach(bindings, function pushBinding(bindingKey) {\n if (!bindingsConsidered[bindingKey]) {\n var binding = ko['getBindingHandler'](bindingKey);\n if (binding) {\n // First add dependencies (if any) of the current binding\n if (binding['after']) {\n cyclicDependencyStack.push(bindingKey);\n ko.utils.arrayForEach(binding['after'], function(bindingDependencyKey) {\n if (bindings[bindingDependencyKey]) {\n if (ko.utils.arrayIndexOf(cyclicDependencyStack, bindingDependencyKey) !== -1) {\n throw Error(\"Cannot combine the following bindings, because they have a cyclic dependency: \" + cyclicDependencyStack.join(\", \"));\n } else {\n pushBinding(bindingDependencyKey);\n }\n }\n });\n cyclicDependencyStack.length--;\n }\n // Next add the current binding\n result.push({ key: bindingKey, handler: binding });\n }\n bindingsConsidered[bindingKey] = true;\n }\n });\n\n return result;\n }\n\n function applyBindingsToNodeInternal(node, sourceBindings, bindingContext) {\n var bindingInfo = ko.utils.domData.getOrSet(node, boundElementDomDataKey, {});\n\n // Prevent multiple applyBindings calls for the same node, except when a binding value is specified\n var alreadyBound = bindingInfo.alreadyBound;\n if (!sourceBindings) {\n if (alreadyBound) {\n throw Error(\"You cannot apply bindings multiple times to the same element.\");\n }\n bindingInfo.alreadyBound = true;\n }\n if (!alreadyBound) {\n bindingInfo.context = bindingContext;\n }\n if (!bindingInfo.notifiedEvents) {\n bindingInfo.notifiedEvents = {};\n }\n\n // Use bindings if given, otherwise fall back on asking the bindings provider to give us some bindings\n var bindings;\n if (sourceBindings && typeof sourceBindings !== 'function') {\n bindings = sourceBindings;\n } else {\n var provider = ko.bindingProvider['instance'],\n getBindings = provider['getBindingAccessors'] || getBindingsAndMakeAccessors;\n\n // Get the binding from the provider within a computed observable so that we can update the bindings whenever\n // the binding context is updated or if the binding provider accesses observables.\n var bindingsUpdater = ko.dependentObservable(\n function() {\n bindings = sourceBindings ? sourceBindings(bindingContext, node) : getBindings.call(provider, node, bindingContext);\n // Register a dependency on the binding context to support observable view models.\n if (bindings) {\n if (bindingContext[contextSubscribable]) {\n bindingContext[contextSubscribable]();\n }\n if (bindingContext[contextDataDependency]) {\n bindingContext[contextDataDependency]();\n }\n }\n return bindings;\n },\n null, { disposeWhenNodeIsRemoved: node }\n );\n\n if (!bindings || !bindingsUpdater.isActive())\n bindingsUpdater = null;\n }\n\n var contextToExtend = bindingContext;\n var bindingHandlerThatControlsDescendantBindings;\n if (bindings) {\n // Return the value accessor for a given binding. When bindings are static (won't be updated because of a binding\n // context update), just return the value accessor from the binding. Otherwise, return a function that always gets\n // the latest binding value and registers a dependency on the binding updater.\n var getValueAccessor = bindingsUpdater\n ? function(bindingKey) {\n return function() {\n return evaluateValueAccessor(bindingsUpdater()[bindingKey]);\n };\n } : function(bindingKey) {\n return bindings[bindingKey];\n };\n\n // Use of allBindings as a function is maintained for backwards compatibility, but its use is deprecated\n function allBindings() {\n return ko.utils.objectMap(bindingsUpdater ? bindingsUpdater() : bindings, evaluateValueAccessor);\n }\n // The following is the 3.x allBindings API\n allBindings['get'] = function(key) {\n return bindings[key] && evaluateValueAccessor(getValueAccessor(key));\n };\n allBindings['has'] = function(key) {\n return key in bindings;\n };\n\n if (ko.bindingEvent.childrenComplete in bindings) {\n ko.bindingEvent.subscribe(node, ko.bindingEvent.childrenComplete, function () {\n var callback = evaluateValueAccessor(bindings[ko.bindingEvent.childrenComplete]);\n if (callback) {\n var nodes = ko.virtualElements.childNodes(node);\n if (nodes.length) {\n callback(nodes, ko.dataFor(nodes[0]));\n }\n }\n });\n }\n\n if (ko.bindingEvent.descendantsComplete in bindings) {\n contextToExtend = ko.bindingEvent.startPossiblyAsyncContentBinding(node, bindingContext);\n ko.bindingEvent.subscribe(node, ko.bindingEvent.descendantsComplete, function () {\n var callback = evaluateValueAccessor(bindings[ko.bindingEvent.descendantsComplete]);\n if (callback && ko.virtualElements.firstChild(node)) {\n callback(node);\n }\n });\n }\n\n // First put the bindings into the right order\n var orderedBindings = topologicalSortBindings(bindings);\n\n // Go through the sorted bindings, calling init and update for each\n ko.utils.arrayForEach(orderedBindings, function(bindingKeyAndHandler) {\n // Note that topologicalSortBindings has already filtered out any nonexistent binding handlers,\n // so bindingKeyAndHandler.handler will always be nonnull.\n var handlerInitFn = bindingKeyAndHandler.handler[\"init\"],\n handlerUpdateFn = bindingKeyAndHandler.handler[\"update\"],\n bindingKey = bindingKeyAndHandler.key;\n\n if (node.nodeType === 8) {\n validateThatBindingIsAllowedForVirtualElements(bindingKey);\n }\n\n try {\n // Run init, ignoring any dependencies\n if (typeof handlerInitFn == \"function\") {\n ko.dependencyDetection.ignore(function() {\n var initResult = handlerInitFn(node, getValueAccessor(bindingKey), allBindings, contextToExtend['$data'], contextToExtend);\n\n // If this binding handler claims to control descendant bindings, make a note of this\n if (initResult && initResult['controlsDescendantBindings']) {\n if (bindingHandlerThatControlsDescendantBindings !== undefined)\n throw new Error(\"Multiple bindings (\" + bindingHandlerThatControlsDescendantBindings + \" and \" + bindingKey + \") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.\");\n bindingHandlerThatControlsDescendantBindings = bindingKey;\n }\n });\n }\n\n // Run update in its own computed wrapper\n if (typeof handlerUpdateFn == \"function\") {\n ko.dependentObservable(\n function() {\n handlerUpdateFn(node, getValueAccessor(bindingKey), allBindings, contextToExtend['$data'], contextToExtend);\n },\n null,\n { disposeWhenNodeIsRemoved: node }\n );\n }\n } catch (ex) {\n ex.message = \"Unable to process binding \\\"\" + bindingKey + \": \" + bindings[bindingKey] + \"\\\"\\nMessage: \" + ex.message;\n throw ex;\n }\n });\n }\n\n var shouldBindDescendants = bindingHandlerThatControlsDescendantBindings === undefined;\n return {\n 'shouldBindDescendants': shouldBindDescendants,\n 'bindingContextForDescendants': shouldBindDescendants && contextToExtend\n };\n };\n\n ko.storedBindingContextForNode = function (node) {\n var bindingInfo = ko.utils.domData.get(node, boundElementDomDataKey);\n return bindingInfo && bindingInfo.context;\n }\n\n function getBindingContext(viewModelOrBindingContext, extendContextCallback) {\n return viewModelOrBindingContext && (viewModelOrBindingContext instanceof ko.bindingContext)\n ? viewModelOrBindingContext\n : new ko.bindingContext(viewModelOrBindingContext, undefined, undefined, extendContextCallback);\n }\n\n ko.applyBindingAccessorsToNode = function (node, bindings, viewModelOrBindingContext) {\n if (node.nodeType === 1) // If it's an element, workaround IE <= 8 HTML parsing weirdness\n ko.virtualElements.normaliseVirtualElementDomStructure(node);\n return applyBindingsToNodeInternal(node, bindings, getBindingContext(viewModelOrBindingContext));\n };\n\n ko.applyBindingsToNode = function (node, bindings, viewModelOrBindingContext) {\n var context = getBindingContext(viewModelOrBindingContext);\n return ko.applyBindingAccessorsToNode(node, makeBindingAccessors(bindings, context, node), context);\n };\n\n ko.applyBindingsToDescendants = function(viewModelOrBindingContext, rootNode) {\n if (rootNode.nodeType === 1 || rootNode.nodeType === 8)\n applyBindingsToDescendantsInternal(getBindingContext(viewModelOrBindingContext), rootNode);\n };\n\n ko.applyBindings = function (viewModelOrBindingContext, rootNode, extendContextCallback) {\n // If jQuery is loaded after Knockout, we won't initially have access to it. So save it here.\n if (!jQueryInstance && window['jQuery']) {\n jQueryInstance = window['jQuery'];\n }\n\n if (arguments.length < 2) {\n rootNode = document.body;\n if (!rootNode) {\n throw Error(\"ko.applyBindings: could not find document.body; has the document been loaded?\");\n }\n } else if (!rootNode || (rootNode.nodeType !== 1 && rootNode.nodeType !== 8)) {\n throw Error(\"ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node\");\n }\n\n applyBindingsToNodeAndDescendantsInternal(getBindingContext(viewModelOrBindingContext, extendContextCallback), rootNode);\n };\n\n // Retrieving binding context from arbitrary nodes\n ko.contextFor = function(node) {\n // We can only do something meaningful for elements and comment nodes (in particular, not text nodes, as IE can't store domdata for them)\n if (node && (node.nodeType === 1 || node.nodeType === 8)) {\n return ko.storedBindingContextForNode(node);\n }\n return undefined;\n };\n ko.dataFor = function(node) {\n var context = ko.contextFor(node);\n return context ? context['$data'] : undefined;\n };\n\n ko.exportSymbol('bindingHandlers', ko.bindingHandlers);\n ko.exportSymbol('bindingEvent', ko.bindingEvent);\n ko.exportSymbol('bindingEvent.subscribe', ko.bindingEvent.subscribe);\n ko.exportSymbol('bindingEvent.startPossiblyAsyncContentBinding', ko.bindingEvent.startPossiblyAsyncContentBinding);\n ko.exportSymbol('applyBindings', ko.applyBindings);\n ko.exportSymbol('applyBindingsToDescendants', ko.applyBindingsToDescendants);\n ko.exportSymbol('applyBindingAccessorsToNode', ko.applyBindingAccessorsToNode);\n ko.exportSymbol('applyBindingsToNode', ko.applyBindingsToNode);\n ko.exportSymbol('contextFor', ko.contextFor);\n ko.exportSymbol('dataFor', ko.dataFor);\n })();\n (function(undefined) {\n var loadingSubscribablesCache = {}, // Tracks component loads that are currently in flight\n loadedDefinitionsCache = {}; // Tracks component loads that have already completed\n\n ko.components = {\n get: function(componentName, callback) {\n var cachedDefinition = getObjectOwnProperty(loadedDefinitionsCache, componentName);\n if (cachedDefinition) {\n // It's already loaded and cached. Reuse the same definition object.\n // Note that for API consistency, even cache hits complete asynchronously by default.\n // You can bypass this by putting synchronous:true on your component config.\n if (cachedDefinition.isSynchronousComponent) {\n ko.dependencyDetection.ignore(function() { // See comment in loaderRegistryBehaviors.js for reasoning\n callback(cachedDefinition.definition);\n });\n } else {\n ko.tasks.schedule(function() { callback(cachedDefinition.definition); });\n }\n } else {\n // Join the loading process that is already underway, or start a new one.\n loadComponentAndNotify(componentName, callback);\n }\n },\n\n clearCachedDefinition: function(componentName) {\n delete loadedDefinitionsCache[componentName];\n },\n\n _getFirstResultFromLoaders: getFirstResultFromLoaders\n };\n\n function getObjectOwnProperty(obj, propName) {\n return Object.prototype.hasOwnProperty.call(obj, propName) ? obj[propName] : undefined;\n }\n\n function loadComponentAndNotify(componentName, callback) {\n var subscribable = getObjectOwnProperty(loadingSubscribablesCache, componentName),\n completedAsync;\n if (!subscribable) {\n // It's not started loading yet. Start loading, and when it's done, move it to loadedDefinitionsCache.\n subscribable = loadingSubscribablesCache[componentName] = new ko.subscribable();\n subscribable.subscribe(callback);\n\n beginLoadingComponent(componentName, function(definition, config) {\n var isSynchronousComponent = !!(config && config['synchronous']);\n loadedDefinitionsCache[componentName] = { definition: definition, isSynchronousComponent: isSynchronousComponent };\n delete loadingSubscribablesCache[componentName];\n\n // For API consistency, all loads complete asynchronously. However we want to avoid\n // adding an extra task schedule if it's unnecessary (i.e., the completion is already\n // async).\n //\n // You can bypass the 'always asynchronous' feature by putting the synchronous:true\n // flag on your component configuration when you register it.\n if (completedAsync || isSynchronousComponent) {\n // Note that notifySubscribers ignores any dependencies read within the callback.\n // See comment in loaderRegistryBehaviors.js for reasoning\n subscribable['notifySubscribers'](definition);\n } else {\n ko.tasks.schedule(function() {\n subscribable['notifySubscribers'](definition);\n });\n }\n });\n completedAsync = true;\n } else {\n subscribable.subscribe(callback);\n }\n }\n\n function beginLoadingComponent(componentName, callback) {\n getFirstResultFromLoaders('getConfig', [componentName], function(config) {\n if (config) {\n // We have a config, so now load its definition\n getFirstResultFromLoaders('loadComponent', [componentName, config], function(definition) {\n callback(definition, config);\n });\n } else {\n // The component has no config - it's unknown to all the loaders.\n // Note that this is not an error (e.g., a module loading error) - that would abort the\n // process and this callback would not run. For this callback to run, all loaders must\n // have confirmed they don't know about this component.\n callback(null, null);\n }\n });\n }\n\n function getFirstResultFromLoaders(methodName, argsExceptCallback, callback, candidateLoaders) {\n // On the first call in the stack, start with the full set of loaders\n if (!candidateLoaders) {\n candidateLoaders = ko.components['loaders'].slice(0); // Use a copy, because we'll be mutating this array\n }\n\n // Try the next candidate\n var currentCandidateLoader = candidateLoaders.shift();\n if (currentCandidateLoader) {\n var methodInstance = currentCandidateLoader[methodName];\n if (methodInstance) {\n var wasAborted = false,\n synchronousReturnValue = methodInstance.apply(currentCandidateLoader, argsExceptCallback.concat(function(result) {\n if (wasAborted) {\n callback(null);\n } else if (result !== null) {\n // This candidate returned a value. Use it.\n callback(result);\n } else {\n // Try the next candidate\n getFirstResultFromLoaders(methodName, argsExceptCallback, callback, candidateLoaders);\n }\n }));\n\n // Currently, loaders may not return anything synchronously. This leaves open the possibility\n // that we'll extend the API to support synchronous return values in the future. It won't be\n // a breaking change, because currently no loader is allowed to return anything except undefined.\n if (synchronousReturnValue !== undefined) {\n wasAborted = true;\n\n // Method to suppress exceptions will remain undocumented. This is only to keep\n // KO's specs running tidily, since we can observe the loading got aborted without\n // having exceptions cluttering up the console too.\n if (!currentCandidateLoader['suppressLoaderExceptions']) {\n throw new Error('Component loaders must supply values by invoking the callback, not by returning values synchronously.');\n }\n }\n } else {\n // This candidate doesn't have the relevant handler. Synchronously move on to the next one.\n getFirstResultFromLoaders(methodName, argsExceptCallback, callback, candidateLoaders);\n }\n } else {\n // No candidates returned a value\n callback(null);\n }\n }\n\n // Reference the loaders via string name so it's possible for developers\n // to replace the whole array by assigning to ko.components.loaders\n ko.components['loaders'] = [];\n\n ko.exportSymbol('components', ko.components);\n ko.exportSymbol('components.get', ko.components.get);\n ko.exportSymbol('components.clearCachedDefinition', ko.components.clearCachedDefinition);\n })();\n (function(undefined) {\n\n // The default loader is responsible for two things:\n // 1. Maintaining the default in-memory registry of component configuration objects\n // (i.e., the thing you're writing to when you call ko.components.register(someName, ...))\n // 2. Answering requests for components by fetching configuration objects\n // from that default in-memory registry and resolving them into standard\n // component definition objects (of the form { createViewModel: ..., template: ... })\n // Custom loaders may override either of these facilities, i.e.,\n // 1. To supply configuration objects from some other source (e.g., conventions)\n // 2. Or, to resolve configuration objects by loading viewmodels/templates via arbitrary logic.\n\n var defaultConfigRegistry = {};\n\n ko.components.register = function(componentName, config) {\n if (!config) {\n throw new Error('Invalid configuration for ' + componentName);\n }\n\n if (ko.components.isRegistered(componentName)) {\n throw new Error('Component ' + componentName + ' is already registered');\n }\n\n defaultConfigRegistry[componentName] = config;\n };\n\n ko.components.isRegistered = function(componentName) {\n return Object.prototype.hasOwnProperty.call(defaultConfigRegistry, componentName);\n };\n\n ko.components.unregister = function(componentName) {\n delete defaultConfigRegistry[componentName];\n ko.components.clearCachedDefinition(componentName);\n };\n\n ko.components.defaultLoader = {\n 'getConfig': function(componentName, callback) {\n var result = ko.components.isRegistered(componentName)\n ? defaultConfigRegistry[componentName]\n : null;\n callback(result);\n },\n\n 'loadComponent': function(componentName, config, callback) {\n var errorCallback = makeErrorCallback(componentName);\n possiblyGetConfigFromAmd(errorCallback, config, function(loadedConfig) {\n resolveConfig(componentName, errorCallback, loadedConfig, callback);\n });\n },\n\n 'loadTemplate': function(componentName, templateConfig, callback) {\n resolveTemplate(makeErrorCallback(componentName), templateConfig, callback);\n },\n\n 'loadViewModel': function(componentName, viewModelConfig, callback) {\n resolveViewModel(makeErrorCallback(componentName), viewModelConfig, callback);\n }\n };\n\n var createViewModelKey = 'createViewModel';\n\n // Takes a config object of the form { template: ..., viewModel: ... }, and asynchronously convert it\n // into the standard component definition format:\n // { template: <ArrayOfDomNodes>, createViewModel: function(params, componentInfo) { ... } }.\n // Since both template and viewModel may need to be resolved asynchronously, both tasks are performed\n // in parallel, and the results joined when both are ready. We don't depend on any promises infrastructure,\n // so this is implemented manually below.\n function resolveConfig(componentName, errorCallback, config, callback) {\n var result = {},\n makeCallBackWhenZero = 2,\n tryIssueCallback = function() {\n if (--makeCallBackWhenZero === 0) {\n callback(result);\n }\n },\n templateConfig = config['template'],\n viewModelConfig = config['viewModel'];\n\n if (templateConfig) {\n possiblyGetConfigFromAmd(errorCallback, templateConfig, function(loadedConfig) {\n ko.components._getFirstResultFromLoaders('loadTemplate', [componentName, loadedConfig], function(resolvedTemplate) {\n result['template'] = resolvedTemplate;\n tryIssueCallback();\n });\n });\n } else {\n tryIssueCallback();\n }\n\n if (viewModelConfig) {\n possiblyGetConfigFromAmd(errorCallback, viewModelConfig, function(loadedConfig) {\n ko.components._getFirstResultFromLoaders('loadViewModel', [componentName, loadedConfig], function(resolvedViewModel) {\n result[createViewModelKey] = resolvedViewModel;\n tryIssueCallback();\n });\n });\n } else {\n tryIssueCallback();\n }\n }\n\n function resolveTemplate(errorCallback, templateConfig, callback) {\n if (typeof templateConfig === 'string') {\n // Markup - parse it\n callback(ko.utils.parseHtmlFragment(templateConfig));\n } else if (templateConfig instanceof Array) {\n // Assume already an array of DOM nodes - pass through unchanged\n callback(templateConfig);\n } else if (isDocumentFragment(templateConfig)) {\n // Document fragment - use its child nodes\n callback(ko.utils.makeArray(templateConfig.childNodes));\n } else if (templateConfig['element']) {\n var element = templateConfig['element'];\n if (isDomElement(element)) {\n // Element instance - copy its child nodes\n callback(cloneNodesFromTemplateSourceElement(element));\n } else if (typeof element === 'string') {\n // Element ID - find it, then copy its child nodes\n var elemInstance = document.getElementById(element);\n if (elemInstance) {\n callback(cloneNodesFromTemplateSourceElement(elemInstance));\n } else {\n errorCallback('Cannot find element with ID ' + element);\n }\n } else {\n errorCallback('Unknown element type: ' + element);\n }\n } else {\n errorCallback('Unknown template value: ' + templateConfig);\n }\n }\n\n function resolveViewModel(errorCallback, viewModelConfig, callback) {\n if (typeof viewModelConfig === 'function') {\n // Constructor - convert to standard factory function format\n // By design, this does *not* supply componentInfo to the constructor, as the intent is that\n // componentInfo contains non-viewmodel data (e.g., the component's element) that should only\n // be used in factory functions, not viewmodel constructors.\n callback(function (params /*, componentInfo */) {\n return new viewModelConfig(params);\n });\n } else if (typeof viewModelConfig[createViewModelKey] === 'function') {\n // Already a factory function - use it as-is\n callback(viewModelConfig[createViewModelKey]);\n } else if ('instance' in viewModelConfig) {\n // Fixed object instance - promote to createViewModel format for API consistency\n var fixedInstance = viewModelConfig['instance'];\n callback(function (params, componentInfo) {\n return fixedInstance;\n });\n } else if ('viewModel' in viewModelConfig) {\n // Resolved AMD module whose value is of the form { viewModel: ... }\n resolveViewModel(errorCallback, viewModelConfig['viewModel'], callback);\n } else {\n errorCallback('Unknown viewModel value: ' + viewModelConfig);\n }\n }\n\n function cloneNodesFromTemplateSourceElement(elemInstance) {\n switch (ko.utils.tagNameLower(elemInstance)) {\n case 'script':\n return ko.utils.parseHtmlFragment(elemInstance.text);\n case 'textarea':\n return ko.utils.parseHtmlFragment(elemInstance.value);\n case 'template':\n // For browsers with proper <template> element support (i.e., where the .content property\n // gives a document fragment), use that document fragment.\n if (isDocumentFragment(elemInstance.content)) {\n return ko.utils.cloneNodes(elemInstance.content.childNodes);\n }\n }\n\n // Regular elements such as <div>, and <template> elements on old browsers that don't really\n // understand <template> and just treat it as a regular container\n return ko.utils.cloneNodes(elemInstance.childNodes);\n }\n\n function isDomElement(obj) {\n if (window['HTMLElement']) {\n return obj instanceof HTMLElement;\n } else {\n return obj && obj.tagName && obj.nodeType === 1;\n }\n }\n\n function isDocumentFragment(obj) {\n if (window['DocumentFragment']) {\n return obj instanceof DocumentFragment;\n } else {\n return obj && obj.nodeType === 11;\n }\n }\n\n function possiblyGetConfigFromAmd(errorCallback, config, callback) {\n if (typeof config['require'] === 'string') {\n // The config is the value of an AMD module\n if (amdRequire || window['require']) {\n (amdRequire || window['require'])([config['require']], function (module) {\n if (module && typeof module === 'object' && module.__esModule && module.default) {\n module = module.default;\n }\n callback(module);\n });\n } else {\n errorCallback('Uses require, but no AMD loader is present');\n }\n } else {\n callback(config);\n }\n }\n\n function makeErrorCallback(componentName) {\n return function (message) {\n throw new Error('Component \\'' + componentName + '\\': ' + message);\n };\n }\n\n ko.exportSymbol('components.register', ko.components.register);\n ko.exportSymbol('components.isRegistered', ko.components.isRegistered);\n ko.exportSymbol('components.unregister', ko.components.unregister);\n\n // Expose the default loader so that developers can directly ask it for configuration\n // or to resolve configuration\n ko.exportSymbol('components.defaultLoader', ko.components.defaultLoader);\n\n // By default, the default loader is the only registered component loader\n ko.components['loaders'].push(ko.components.defaultLoader);\n\n // Privately expose the underlying config registry for use in old-IE shim\n ko.components._allRegisteredComponents = defaultConfigRegistry;\n })();\n (function (undefined) {\n // Overridable API for determining which component name applies to a given node. By overriding this,\n // you can for example map specific tagNames to components that are not preregistered.\n ko.components['getComponentNameForNode'] = function(node) {\n var tagNameLower = ko.utils.tagNameLower(node);\n if (ko.components.isRegistered(tagNameLower)) {\n // Try to determine that this node can be considered a *custom* element; see https://github.com/knockout/knockout/issues/1603\n if (tagNameLower.indexOf('-') != -1 || ('' + node) == \"[object HTMLUnknownElement]\" || (ko.utils.ieVersion <= 8 && node.tagName === tagNameLower)) {\n return tagNameLower;\n }\n }\n };\n\n ko.components.addBindingsForCustomElement = function(allBindings, node, bindingContext, valueAccessors) {\n // Determine if it's really a custom element matching a component\n if (node.nodeType === 1) {\n var componentName = ko.components['getComponentNameForNode'](node);\n if (componentName) {\n // It does represent a component, so add a component binding for it\n allBindings = allBindings || {};\n\n if (allBindings['component']) {\n // Avoid silently overwriting some other 'component' binding that may already be on the element\n throw new Error('Cannot use the \"component\" binding on a custom element matching a component');\n }\n\n var componentBindingValue = { 'name': componentName, 'params': getComponentParamsFromCustomElement(node, bindingContext) };\n\n allBindings['component'] = valueAccessors\n ? function() { return componentBindingValue; }\n : componentBindingValue;\n }\n }\n\n return allBindings;\n }\n\n var nativeBindingProviderInstance = new ko.bindingProvider();\n\n function getComponentParamsFromCustomElement(elem, bindingContext) {\n var paramsAttribute = elem.getAttribute('params');\n\n if (paramsAttribute) {\n var params = nativeBindingProviderInstance['parseBindingsString'](paramsAttribute, bindingContext, elem, { 'valueAccessors': true, 'bindingParams': true }),\n rawParamComputedValues = ko.utils.objectMap(params, function(paramValue, paramName) {\n return ko.computed(paramValue, null, { disposeWhenNodeIsRemoved: elem });\n }),\n result = ko.utils.objectMap(rawParamComputedValues, function(paramValueComputed, paramName) {\n var paramValue = paramValueComputed.peek();\n // Does the evaluation of the parameter value unwrap any observables?\n if (!paramValueComputed.isActive()) {\n // No it doesn't, so there's no need for any computed wrapper. Just pass through the supplied value directly.\n // Example: \"someVal: firstName, age: 123\" (whether or not firstName is an observable/computed)\n return paramValue;\n } else {\n // Yes it does. Supply a computed property that unwraps both the outer (binding expression)\n // level of observability, and any inner (resulting model value) level of observability.\n // This means the component doesn't have to worry about multiple unwrapping. If the value is a\n // writable observable, the computed will also be writable and pass the value on to the observable.\n return ko.computed({\n 'read': function() {\n return ko.utils.unwrapObservable(paramValueComputed());\n },\n 'write': ko.isWriteableObservable(paramValue) && function(value) {\n paramValueComputed()(value);\n },\n disposeWhenNodeIsRemoved: elem\n });\n }\n });\n\n // Give access to the raw computeds, as long as that wouldn't overwrite any custom param also called '$raw'\n // This is in case the developer wants to react to outer (binding) observability separately from inner\n // (model value) observability, or in case the model value observable has subobservables.\n if (!Object.prototype.hasOwnProperty.call(result, '$raw')) {\n result['$raw'] = rawParamComputedValues;\n }\n\n return result;\n } else {\n // For consistency, absence of a \"params\" attribute is treated the same as the presence of\n // any empty one. Otherwise component viewmodels need special code to check whether or not\n // 'params' or 'params.$raw' is null/undefined before reading subproperties, which is annoying.\n return { '$raw': {} };\n }\n }\n\n // --------------------------------------------------------------------------------\n // Compatibility code for older (pre-HTML5) IE browsers\n\n if (ko.utils.ieVersion < 9) {\n // Whenever you preregister a component, enable it as a custom element in the current document\n ko.components['register'] = (function(originalFunction) {\n return function(componentName) {\n document.createElement(componentName); // Allows IE<9 to parse markup containing the custom element\n return originalFunction.apply(this, arguments);\n }\n })(ko.components['register']);\n\n // Whenever you create a document fragment, enable all preregistered component names as custom elements\n // This is needed to make innerShiv/jQuery HTML parsing correctly handle the custom elements\n document.createDocumentFragment = (function(originalFunction) {\n return function() {\n var newDocFrag = originalFunction(),\n allComponents = ko.components._allRegisteredComponents;\n for (var componentName in allComponents) {\n if (Object.prototype.hasOwnProperty.call(allComponents, componentName)) {\n newDocFrag.createElement(componentName);\n }\n }\n return newDocFrag;\n };\n })(document.createDocumentFragment);\n }\n })();(function(undefined) {\n var componentLoadingOperationUniqueId = 0;\n\n ko.bindingHandlers['component'] = {\n 'init': function(element, valueAccessor, ignored1, ignored2, bindingContext) {\n var currentViewModel,\n currentLoadingOperationId,\n afterRenderSub,\n disposeAssociatedComponentViewModel = function () {\n var currentViewModelDispose = currentViewModel && currentViewModel['dispose'];\n if (typeof currentViewModelDispose === 'function') {\n currentViewModelDispose.call(currentViewModel);\n }\n if (afterRenderSub) {\n afterRenderSub.dispose();\n }\n afterRenderSub = null;\n currentViewModel = null;\n // Any in-flight loading operation is no longer relevant, so make sure we ignore its completion\n currentLoadingOperationId = null;\n },\n originalChildNodes = ko.utils.makeArray(ko.virtualElements.childNodes(element));\n\n ko.virtualElements.emptyNode(element);\n ko.utils.domNodeDisposal.addDisposeCallback(element, disposeAssociatedComponentViewModel);\n\n ko.computed(function () {\n var value = ko.utils.unwrapObservable(valueAccessor()),\n componentName, componentParams;\n\n if (typeof value === 'string') {\n componentName = value;\n } else {\n componentName = ko.utils.unwrapObservable(value['name']);\n componentParams = ko.utils.unwrapObservable(value['params']);\n }\n\n if (!componentName) {\n throw new Error('No component name specified');\n }\n\n var asyncContext = ko.bindingEvent.startPossiblyAsyncContentBinding(element, bindingContext);\n\n var loadingOperationId = currentLoadingOperationId = ++componentLoadingOperationUniqueId;\n ko.components.get(componentName, function(componentDefinition) {\n // If this is not the current load operation for this element, ignore it.\n if (currentLoadingOperationId !== loadingOperationId) {\n return;\n }\n\n // Clean up previous state\n disposeAssociatedComponentViewModel();\n\n // Instantiate and bind new component. Implicitly this cleans any old DOM nodes.\n if (!componentDefinition) {\n throw new Error('Unknown component \\'' + componentName + '\\'');\n }\n cloneTemplateIntoElement(componentName, componentDefinition, element);\n\n var componentInfo = {\n 'element': element,\n 'templateNodes': originalChildNodes\n };\n\n var componentViewModel = createViewModel(componentDefinition, componentParams, componentInfo),\n childBindingContext = asyncContext['createChildContext'](componentViewModel, {\n 'extend': function(ctx) {\n ctx['$component'] = componentViewModel;\n ctx['$componentTemplateNodes'] = originalChildNodes;\n }\n });\n\n if (componentViewModel && componentViewModel['koDescendantsComplete']) {\n afterRenderSub = ko.bindingEvent.subscribe(element, ko.bindingEvent.descendantsComplete, componentViewModel['koDescendantsComplete'], componentViewModel);\n }\n\n currentViewModel = componentViewModel;\n ko.applyBindingsToDescendants(childBindingContext, element);\n });\n }, null, { disposeWhenNodeIsRemoved: element });\n\n return { 'controlsDescendantBindings': true };\n }\n };\n\n ko.virtualElements.allowedBindings['component'] = true;\n\n function cloneTemplateIntoElement(componentName, componentDefinition, element) {\n var template = componentDefinition['template'];\n if (!template) {\n throw new Error('Component \\'' + componentName + '\\' has no template');\n }\n\n var clonedNodesArray = ko.utils.cloneNodes(template);\n ko.virtualElements.setDomNodeChildren(element, clonedNodesArray);\n }\n\n function createViewModel(componentDefinition, componentParams, componentInfo) {\n var componentViewModelFactory = componentDefinition['createViewModel'];\n return componentViewModelFactory\n ? componentViewModelFactory.call(componentDefinition, componentParams, componentInfo)\n : componentParams; // Template-only component\n }\n\n })();\n var attrHtmlToJavaScriptMap = { 'class': 'className', 'for': 'htmlFor' };\n ko.bindingHandlers['attr'] = {\n 'update': function(element, valueAccessor, allBindings) {\n var value = ko.utils.unwrapObservable(valueAccessor()) || {};\n ko.utils.objectForEach(value, function(attrName, attrValue) {\n attrValue = ko.utils.unwrapObservable(attrValue);\n\n // Find the namespace of this attribute, if any.\n var prefixLen = attrName.indexOf(':');\n var namespace = \"lookupNamespaceURI\" in element && prefixLen > 0 && element.lookupNamespaceURI(attrName.substr(0, prefixLen));\n\n // To cover cases like \"attr: { checked:someProp }\", we want to remove the attribute entirely\n // when someProp is a \"no value\"-like value (strictly null, false, or undefined)\n // (because the absence of the \"checked\" attr is how to mark an element as not checked, etc.)\n var toRemove = (attrValue === false) || (attrValue === null) || (attrValue === undefined);\n if (toRemove) {\n namespace ? element.removeAttributeNS(namespace, attrName) : element.removeAttribute(attrName);\n } else {\n attrValue = attrValue.toString();\n }\n\n // In IE <= 7 and IE8 Quirks Mode, you have to use the JavaScript property name instead of the\n // HTML attribute name for certain attributes. IE8 Standards Mode supports the correct behavior,\n // but instead of figuring out the mode, we'll just set the attribute through the JavaScript\n // property for IE <= 8.\n if (ko.utils.ieVersion <= 8 && attrName in attrHtmlToJavaScriptMap) {\n attrName = attrHtmlToJavaScriptMap[attrName];\n if (toRemove)\n element.removeAttribute(attrName);\n else\n element[attrName] = attrValue;\n } else if (!toRemove) {\n namespace ? element.setAttributeNS(namespace, attrName, attrValue) : element.setAttribute(attrName, attrValue);\n }\n\n // Treat \"name\" specially - although you can think of it as an attribute, it also needs\n // special handling on older versions of IE (https://github.com/SteveSanderson/knockout/pull/333)\n // Deliberately being case-sensitive here because XHTML would regard \"Name\" as a different thing\n // entirely, and there's no strong reason to allow for such casing in HTML.\n if (attrName === \"name\") {\n ko.utils.setElementName(element, toRemove ? \"\" : attrValue);\n }\n });\n }\n };\n (function() {\n\n ko.bindingHandlers['checked'] = {\n 'after': ['value', 'attr'],\n 'init': function (element, valueAccessor, allBindings) {\n var checkedValue = ko.pureComputed(function() {\n // Treat \"value\" like \"checkedValue\" when it is included with \"checked\" binding\n if (allBindings['has']('checkedValue')) {\n return ko.utils.unwrapObservable(allBindings.get('checkedValue'));\n } else if (useElementValue) {\n if (allBindings['has']('value')) {\n return ko.utils.unwrapObservable(allBindings.get('value'));\n } else {\n return element.value;\n }\n }\n });\n\n function updateModel() {\n // This updates the model value from the view value.\n // It runs in response to DOM events (click) and changes in checkedValue.\n var isChecked = element.checked,\n elemValue = checkedValue();\n\n // When we're first setting up this computed, don't change any model state.\n if (ko.computedContext.isInitial()) {\n return;\n }\n\n // We can ignore unchecked radio buttons, because some other radio\n // button will be checked, and that one can take care of updating state.\n // Also ignore value changes to an already unchecked checkbox.\n if (!isChecked && (isRadio || ko.computedContext.getDependenciesCount())) {\n return;\n }\n\n var modelValue = ko.dependencyDetection.ignore(valueAccessor);\n if (valueIsArray) {\n var writableValue = rawValueIsNonArrayObservable ? modelValue.peek() : modelValue,\n saveOldValue = oldElemValue;\n oldElemValue = elemValue;\n\n if (saveOldValue !== elemValue) {\n // When we're responding to the checkedValue changing, and the element is\n // currently checked, replace the old elem value with the new elem value\n // in the model array.\n if (isChecked) {\n ko.utils.addOrRemoveItem(writableValue, elemValue, true);\n ko.utils.addOrRemoveItem(writableValue, saveOldValue, false);\n }\n } else {\n // When we're responding to the user having checked/unchecked a checkbox,\n // add/remove the element value to the model array.\n ko.utils.addOrRemoveItem(writableValue, elemValue, isChecked);\n }\n\n if (rawValueIsNonArrayObservable && ko.isWriteableObservable(modelValue)) {\n modelValue(writableValue);\n }\n } else {\n if (isCheckbox) {\n if (elemValue === undefined) {\n elemValue = isChecked;\n } else if (!isChecked) {\n elemValue = undefined;\n }\n }\n ko.expressionRewriting.writeValueToProperty(modelValue, allBindings, 'checked', elemValue, true);\n }\n };\n\n function updateView() {\n // This updates the view value from the model value.\n // It runs in response to changes in the bound (checked) value.\n var modelValue = ko.utils.unwrapObservable(valueAccessor()),\n elemValue = checkedValue();\n\n if (valueIsArray) {\n // When a checkbox is bound to an array, being checked represents its value being present in that array\n element.checked = ko.utils.arrayIndexOf(modelValue, elemValue) >= 0;\n oldElemValue = elemValue;\n } else if (isCheckbox && elemValue === undefined) {\n // When a checkbox is bound to any other value (not an array) and \"checkedValue\" is not defined,\n // being checked represents the value being trueish\n element.checked = !!modelValue;\n } else {\n // Otherwise, being checked means that the checkbox or radio button's value corresponds to the model value\n element.checked = (checkedValue() === modelValue);\n }\n };\n\n var isCheckbox = element.type == \"checkbox\",\n isRadio = element.type == \"radio\";\n\n // Only bind to check boxes and radio buttons\n if (!isCheckbox && !isRadio) {\n return;\n }\n\n var rawValue = valueAccessor(),\n valueIsArray = isCheckbox && (ko.utils.unwrapObservable(rawValue) instanceof Array),\n rawValueIsNonArrayObservable = !(valueIsArray && rawValue.push && rawValue.splice),\n useElementValue = isRadio || valueIsArray,\n oldElemValue = valueIsArray ? checkedValue() : undefined;\n\n // IE 6 won't allow radio buttons to be selected unless they have a name\n if (isRadio && !element.name)\n ko.bindingHandlers['uniqueName']['init'](element, function() { return true });\n\n // Set up two computeds to update the binding:\n\n // The first responds to changes in the checkedValue value and to element clicks\n ko.computed(updateModel, null, { disposeWhenNodeIsRemoved: element });\n ko.utils.registerEventHandler(element, \"click\", updateModel);\n\n // The second responds to changes in the model value (the one associated with the checked binding)\n ko.computed(updateView, null, { disposeWhenNodeIsRemoved: element });\n\n rawValue = undefined;\n }\n };\n ko.expressionRewriting.twoWayBindings['checked'] = true;\n\n ko.bindingHandlers['checkedValue'] = {\n 'update': function (element, valueAccessor) {\n element.value = ko.utils.unwrapObservable(valueAccessor());\n }\n };\n\n })();var classesWrittenByBindingKey = '__ko__cssValue';\n ko.bindingHandlers['class'] = {\n 'update': function (element, valueAccessor) {\n var value = ko.utils.stringTrim(ko.utils.unwrapObservable(valueAccessor()));\n ko.utils.toggleDomNodeCssClass(element, element[classesWrittenByBindingKey], false);\n element[classesWrittenByBindingKey] = value;\n ko.utils.toggleDomNodeCssClass(element, value, true);\n }\n };\n\n ko.bindingHandlers['css'] = {\n 'update': function (element, valueAccessor) {\n var value = ko.utils.unwrapObservable(valueAccessor());\n if (value !== null && typeof value == \"object\") {\n ko.utils.objectForEach(value, function(className, shouldHaveClass) {\n shouldHaveClass = ko.utils.unwrapObservable(shouldHaveClass);\n ko.utils.toggleDomNodeCssClass(element, className, shouldHaveClass);\n });\n } else {\n ko.bindingHandlers['class']['update'](element, valueAccessor);\n }\n }\n };\n ko.bindingHandlers['enable'] = {\n 'update': function (element, valueAccessor) {\n var value = ko.utils.unwrapObservable(valueAccessor());\n if (value && element.disabled)\n element.removeAttribute(\"disabled\");\n else if ((!value) && (!element.disabled))\n element.disabled = true;\n }\n };\n\n ko.bindingHandlers['disable'] = {\n 'update': function (element, valueAccessor) {\n ko.bindingHandlers['enable']['update'](element, function() { return !ko.utils.unwrapObservable(valueAccessor()) });\n }\n };\n// For certain common events (currently just 'click'), allow a simplified data-binding syntax\n// e.g. click:handler instead of the usual full-length event:{click:handler}\n function makeEventHandlerShortcut(eventName) {\n ko.bindingHandlers[eventName] = {\n 'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) {\n var newValueAccessor = function () {\n var result = {};\n result[eventName] = valueAccessor();\n return result;\n };\n return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindings, viewModel, bindingContext);\n }\n }\n }\n\n ko.bindingHandlers['event'] = {\n 'init' : function (element, valueAccessor, allBindings, viewModel, bindingContext) {\n var eventsToHandle = valueAccessor() || {};\n ko.utils.objectForEach(eventsToHandle, function(eventName) {\n if (typeof eventName == \"string\") {\n ko.utils.registerEventHandler(element, eventName, function (event) {\n var handlerReturnValue;\n var handlerFunction = valueAccessor()[eventName];\n if (!handlerFunction)\n return;\n\n try {\n // Take all the event args, and prefix with the viewmodel\n var argsForHandler = ko.utils.makeArray(arguments);\n viewModel = bindingContext['$data'];\n argsForHandler.unshift(viewModel);\n handlerReturnValue = handlerFunction.apply(viewModel, argsForHandler);\n } finally {\n if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.\n if (event.preventDefault)\n event.preventDefault();\n else\n event.returnValue = false;\n }\n }\n\n var bubble = allBindings.get(eventName + 'Bubble') !== false;\n if (!bubble) {\n event.cancelBubble = true;\n if (event.stopPropagation)\n event.stopPropagation();\n }\n });\n }\n });\n }\n };\n// \"foreach: someExpression\" is equivalent to \"template: { foreach: someExpression }\"\n// \"foreach: { data: someExpression, afterAdd: myfn }\" is equivalent to \"template: { foreach: someExpression, afterAdd: myfn }\"\n ko.bindingHandlers['foreach'] = {\n makeTemplateValueAccessor: function(valueAccessor) {\n return function() {\n var modelValue = valueAccessor(),\n unwrappedValue = ko.utils.peekObservable(modelValue); // Unwrap without setting a dependency here\n\n // If unwrappedValue is the array, pass in the wrapped value on its own\n // The value will be unwrapped and tracked within the template binding\n // (See https://github.com/SteveSanderson/knockout/issues/523)\n if ((!unwrappedValue) || typeof unwrappedValue.length == \"number\")\n return { 'foreach': modelValue, 'templateEngine': ko.nativeTemplateEngine.instance };\n\n // If unwrappedValue.data is the array, preserve all relevant options and unwrap again value so we get updates\n ko.utils.unwrapObservable(modelValue);\n return {\n 'foreach': unwrappedValue['data'],\n 'as': unwrappedValue['as'],\n 'noChildContext': unwrappedValue['noChildContext'],\n 'includeDestroyed': unwrappedValue['includeDestroyed'],\n 'afterAdd': unwrappedValue['afterAdd'],\n 'beforeRemove': unwrappedValue['beforeRemove'],\n 'afterRender': unwrappedValue['afterRender'],\n 'beforeMove': unwrappedValue['beforeMove'],\n 'afterMove': unwrappedValue['afterMove'],\n 'templateEngine': ko.nativeTemplateEngine.instance\n };\n };\n },\n 'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) {\n return ko.bindingHandlers['template']['init'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor));\n },\n 'update': function(element, valueAccessor, allBindings, viewModel, bindingContext) {\n return ko.bindingHandlers['template']['update'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor), allBindings, viewModel, bindingContext);\n }\n };\n ko.expressionRewriting.bindingRewriteValidators['foreach'] = false; // Can't rewrite control flow bindings\n ko.virtualElements.allowedBindings['foreach'] = true;\n var hasfocusUpdatingProperty = '__ko_hasfocusUpdating';\n var hasfocusLastValue = '__ko_hasfocusLastValue';\n ko.bindingHandlers['hasfocus'] = {\n 'init': function(element, valueAccessor, allBindings) {\n var handleElementFocusChange = function(isFocused) {\n // Where possible, ignore which event was raised and determine focus state using activeElement,\n // as this avoids phantom focus/blur events raised when changing tabs in modern browsers.\n // However, not all KO-targeted browsers (Firefox 2) support activeElement. For those browsers,\n // prevent a loss of focus when changing tabs/windows by setting a flag that prevents hasfocus\n // from calling 'blur()' on the element when it loses focus.\n // Discussion at https://github.com/SteveSanderson/knockout/pull/352\n element[hasfocusUpdatingProperty] = true;\n var ownerDoc = element.ownerDocument;\n if (\"activeElement\" in ownerDoc) {\n var active;\n try {\n active = ownerDoc.activeElement;\n } catch(e) {\n // IE9 throws if you access activeElement during page load (see issue #703)\n active = ownerDoc.body;\n }\n isFocused = (active === element);\n }\n var modelValue = valueAccessor();\n ko.expressionRewriting.writeValueToProperty(modelValue, allBindings, 'hasfocus', isFocused, true);\n\n //cache the latest value, so we can avoid unnecessarily calling focus/blur in the update function\n element[hasfocusLastValue] = isFocused;\n element[hasfocusUpdatingProperty] = false;\n };\n var handleElementFocusIn = handleElementFocusChange.bind(null, true);\n var handleElementFocusOut = handleElementFocusChange.bind(null, false);\n\n ko.utils.registerEventHandler(element, \"focus\", handleElementFocusIn);\n ko.utils.registerEventHandler(element, \"focusin\", handleElementFocusIn); // For IE\n ko.utils.registerEventHandler(element, \"blur\", handleElementFocusOut);\n ko.utils.registerEventHandler(element, \"focusout\", handleElementFocusOut); // For IE\n\n // Assume element is not focused (prevents \"blur\" being called initially)\n element[hasfocusLastValue] = false;\n },\n 'update': function(element, valueAccessor) {\n var value = !!ko.utils.unwrapObservable(valueAccessor());\n\n if (!element[hasfocusUpdatingProperty] && element[hasfocusLastValue] !== value) {\n value ? element.focus() : element.blur();\n\n // In IE, the blur method doesn't always cause the element to lose focus (for example, if the window is not in focus).\n // Setting focus to the body element does seem to be reliable in IE, but should only be used if we know that the current\n // element was focused already.\n if (!value && element[hasfocusLastValue]) {\n element.ownerDocument.body.focus();\n }\n\n // For IE, which doesn't reliably fire \"focus\" or \"blur\" events synchronously\n ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, value ? \"focusin\" : \"focusout\"]);\n }\n }\n };\n ko.expressionRewriting.twoWayBindings['hasfocus'] = true;\n\n ko.bindingHandlers['hasFocus'] = ko.bindingHandlers['hasfocus']; // Make \"hasFocus\" an alias\n ko.expressionRewriting.twoWayBindings['hasFocus'] = 'hasfocus';\n ko.bindingHandlers['html'] = {\n 'init': function() {\n // Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)\n return { 'controlsDescendantBindings': true };\n },\n 'update': function (element, valueAccessor) {\n // setHtml will unwrap the value if needed\n ko.utils.setHtml(element, valueAccessor());\n }\n };\n (function () {\n\n// Makes a binding like with or if\n function makeWithIfBinding(bindingKey, isWith, isNot) {\n ko.bindingHandlers[bindingKey] = {\n 'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) {\n var didDisplayOnLastUpdate, savedNodes, contextOptions = {}, completeOnRender, needAsyncContext, renderOnEveryChange;\n\n if (isWith) {\n var as = allBindings.get('as'), noChildContext = allBindings.get('noChildContext');\n renderOnEveryChange = !(as && noChildContext);\n contextOptions = { 'as': as, 'noChildContext': noChildContext, 'exportDependencies': renderOnEveryChange };\n }\n\n completeOnRender = allBindings.get(\"completeOn\") == \"render\";\n needAsyncContext = completeOnRender || allBindings['has'](ko.bindingEvent.descendantsComplete);\n\n ko.computed(function() {\n var value = ko.utils.unwrapObservable(valueAccessor()),\n shouldDisplay = !isNot !== !value, // equivalent to isNot ? !value : !!value,\n isInitial = !savedNodes,\n childContext;\n\n if (!renderOnEveryChange && shouldDisplay === didDisplayOnLastUpdate) {\n return;\n }\n\n if (needAsyncContext) {\n bindingContext = ko.bindingEvent.startPossiblyAsyncContentBinding(element, bindingContext);\n }\n\n if (shouldDisplay) {\n if (!isWith || renderOnEveryChange) {\n contextOptions['dataDependency'] = ko.computedContext.computed();\n }\n\n if (isWith) {\n childContext = bindingContext['createChildContext'](typeof value == \"function\" ? value : valueAccessor, contextOptions);\n } else if (ko.computedContext.getDependenciesCount()) {\n childContext = bindingContext['extend'](null, contextOptions);\n } else {\n childContext = bindingContext;\n }\n }\n\n // Save a copy of the inner nodes on the initial update, but only if we have dependencies.\n if (isInitial && ko.computedContext.getDependenciesCount()) {\n savedNodes = ko.utils.cloneNodes(ko.virtualElements.childNodes(element), true /* shouldCleanNodes */);\n }\n\n if (shouldDisplay) {\n if (!isInitial) {\n ko.virtualElements.setDomNodeChildren(element, ko.utils.cloneNodes(savedNodes));\n }\n\n ko.applyBindingsToDescendants(childContext, element);\n } else {\n ko.virtualElements.emptyNode(element);\n\n if (!completeOnRender) {\n ko.bindingEvent.notify(element, ko.bindingEvent.childrenComplete);\n }\n }\n\n didDisplayOnLastUpdate = shouldDisplay;\n\n }, null, { disposeWhenNodeIsRemoved: element });\n\n return { 'controlsDescendantBindings': true };\n }\n };\n ko.expressionRewriting.bindingRewriteValidators[bindingKey] = false; // Can't rewrite control flow bindings\n ko.virtualElements.allowedBindings[bindingKey] = true;\n }\n\n// Construct the actual binding handlers\n makeWithIfBinding('if');\n makeWithIfBinding('ifnot', false /* isWith */, true /* isNot */);\n makeWithIfBinding('with', true /* isWith */);\n\n })();ko.bindingHandlers['let'] = {\n 'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) {\n // Make a modified binding context, with extra properties, and apply it to descendant elements\n var innerContext = bindingContext['extend'](valueAccessor);\n ko.applyBindingsToDescendants(innerContext, element);\n\n return { 'controlsDescendantBindings': true };\n }\n };\n ko.virtualElements.allowedBindings['let'] = true;\n var captionPlaceholder = {};\n ko.bindingHandlers['options'] = {\n 'init': function(element) {\n if (ko.utils.tagNameLower(element) !== \"select\")\n throw new Error(\"options binding applies only to SELECT elements\");\n\n // Remove all existing <option>s.\n while (element.length > 0) {\n element.remove(0);\n }\n\n // Ensures that the binding processor doesn't try to bind the options\n return { 'controlsDescendantBindings': true };\n },\n 'update': function (element, valueAccessor, allBindings) {\n function selectedOptions() {\n return ko.utils.arrayFilter(element.options, function (node) { return node.selected; });\n }\n\n var selectWasPreviouslyEmpty = element.length == 0,\n multiple = element.multiple,\n previousScrollTop = (!selectWasPreviouslyEmpty && multiple) ? element.scrollTop : null,\n unwrappedArray = ko.utils.unwrapObservable(valueAccessor()),\n valueAllowUnset = allBindings.get('valueAllowUnset') && allBindings['has']('value'),\n includeDestroyed = allBindings.get('optionsIncludeDestroyed'),\n arrayToDomNodeChildrenOptions = {},\n captionValue,\n filteredArray,\n previousSelectedValues = [];\n\n if (!valueAllowUnset) {\n if (multiple) {\n previousSelectedValues = ko.utils.arrayMap(selectedOptions(), ko.selectExtensions.readValue);\n } else if (element.selectedIndex >= 0) {\n previousSelectedValues.push(ko.selectExtensions.readValue(element.options[element.selectedIndex]));\n }\n }\n\n if (unwrappedArray) {\n if (typeof unwrappedArray.length == \"undefined\") // Coerce single value into array\n unwrappedArray = [unwrappedArray];\n\n // Filter out any entries marked as destroyed\n filteredArray = ko.utils.arrayFilter(unwrappedArray, function(item) {\n return includeDestroyed || item === undefined || item === null || !ko.utils.unwrapObservable(item['_destroy']);\n });\n\n // If caption is included, add it to the array\n if (allBindings['has']('optionsCaption')) {\n captionValue = ko.utils.unwrapObservable(allBindings.get('optionsCaption'));\n // If caption value is null or undefined, don't show a caption\n if (captionValue !== null && captionValue !== undefined) {\n filteredArray.unshift(captionPlaceholder);\n }\n }\n } else {\n // If a falsy value is provided (e.g. null), we'll simply empty the select element\n }\n\n function applyToObject(object, predicate, defaultValue) {\n var predicateType = typeof predicate;\n if (predicateType == \"function\") // Given a function; run it against the data value\n return predicate(object);\n else if (predicateType == \"string\") // Given a string; treat it as a property name on the data value\n return object[predicate];\n else // Given no optionsText arg; use the data value itself\n return defaultValue;\n }\n\n // The following functions can run at two different times:\n // The first is when the whole array is being updated directly from this binding handler.\n // The second is when an observable value for a specific array entry is updated.\n // oldOptions will be empty in the first case, but will be filled with the previously generated option in the second.\n var itemUpdate = false;\n function optionForArrayItem(arrayEntry, index, oldOptions) {\n if (oldOptions.length) {\n previousSelectedValues = !valueAllowUnset && oldOptions[0].selected ? [ ko.selectExtensions.readValue(oldOptions[0]) ] : [];\n itemUpdate = true;\n }\n var option = element.ownerDocument.createElement(\"option\");\n if (arrayEntry === captionPlaceholder) {\n ko.utils.setTextContent(option, allBindings.get('optionsCaption'));\n ko.selectExtensions.writeValue(option, undefined);\n } else {\n // Apply a value to the option element\n var optionValue = applyToObject(arrayEntry, allBindings.get('optionsValue'), arrayEntry);\n ko.selectExtensions.writeValue(option, ko.utils.unwrapObservable(optionValue));\n\n // Apply some text to the option element\n var optionText = applyToObject(arrayEntry, allBindings.get('optionsText'), optionValue);\n ko.utils.setTextContent(option, optionText);\n }\n return [option];\n }\n\n // By using a beforeRemove callback, we delay the removal until after new items are added. This fixes a selection\n // problem in IE<=8 and Firefox. See https://github.com/knockout/knockout/issues/1208\n arrayToDomNodeChildrenOptions['beforeRemove'] =\n function (option) {\n element.removeChild(option);\n };\n\n function setSelectionCallback(arrayEntry, newOptions) {\n if (itemUpdate && valueAllowUnset) {\n // The model value is authoritative, so make sure its value is the one selected\n ko.bindingEvent.notify(element, ko.bindingEvent.childrenComplete);\n } else if (previousSelectedValues.length) {\n // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.\n // That's why we first added them without selection. Now it's time to set the selection.\n var isSelected = ko.utils.arrayIndexOf(previousSelectedValues, ko.selectExtensions.readValue(newOptions[0])) >= 0;\n ko.utils.setOptionNodeSelectionState(newOptions[0], isSelected);\n\n // If this option was changed from being selected during a single-item update, notify the change\n if (itemUpdate && !isSelected) {\n ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, \"change\"]);\n }\n }\n }\n\n var callback = setSelectionCallback;\n if (allBindings['has']('optionsAfterRender') && typeof allBindings.get('optionsAfterRender') == \"function\") {\n callback = function(arrayEntry, newOptions) {\n setSelectionCallback(arrayEntry, newOptions);\n ko.dependencyDetection.ignore(allBindings.get('optionsAfterRender'), null, [newOptions[0], arrayEntry !== captionPlaceholder ? arrayEntry : undefined]);\n }\n }\n\n ko.utils.setDomNodeChildrenFromArrayMapping(element, filteredArray, optionForArrayItem, arrayToDomNodeChildrenOptions, callback);\n\n if (!valueAllowUnset) {\n // Determine if the selection has changed as a result of updating the options list\n var selectionChanged;\n if (multiple) {\n // For a multiple-select box, compare the new selection count to the previous one\n // But if nothing was selected before, the selection can't have changed\n selectionChanged = previousSelectedValues.length && selectedOptions().length < previousSelectedValues.length;\n } else {\n // For a single-select box, compare the current value to the previous value\n // But if nothing was selected before or nothing is selected now, just look for a change in selection\n selectionChanged = (previousSelectedValues.length && element.selectedIndex >= 0)\n ? (ko.selectExtensions.readValue(element.options[element.selectedIndex]) !== previousSelectedValues[0])\n : (previousSelectedValues.length || element.selectedIndex >= 0);\n }\n\n // Ensure consistency between model value and selected option.\n // If the dropdown was changed so that selection is no longer the same,\n // notify the value or selectedOptions binding.\n if (selectionChanged) {\n ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, \"change\"]);\n }\n }\n\n if (valueAllowUnset || ko.computedContext.isInitial()) {\n ko.bindingEvent.notify(element, ko.bindingEvent.childrenComplete);\n }\n\n // Workaround for IE bug\n ko.utils.ensureSelectElementIsRenderedCorrectly(element);\n\n if (previousScrollTop && Math.abs(previousScrollTop - element.scrollTop) > 20)\n element.scrollTop = previousScrollTop;\n }\n };\n ko.bindingHandlers['options'].optionValueDomDataKey = ko.utils.domData.nextKey();\n ko.bindingHandlers['selectedOptions'] = {\n 'init': function (element, valueAccessor, allBindings) {\n function updateFromView() {\n var value = valueAccessor(), valueToWrite = [];\n ko.utils.arrayForEach(element.getElementsByTagName(\"option\"), function(node) {\n if (node.selected)\n valueToWrite.push(ko.selectExtensions.readValue(node));\n });\n ko.expressionRewriting.writeValueToProperty(value, allBindings, 'selectedOptions', valueToWrite);\n }\n\n function updateFromModel() {\n var newValue = ko.utils.unwrapObservable(valueAccessor()),\n previousScrollTop = element.scrollTop;\n\n if (newValue && typeof newValue.length == \"number\") {\n ko.utils.arrayForEach(element.getElementsByTagName(\"option\"), function(node) {\n var isSelected = ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0;\n if (node.selected != isSelected) { // This check prevents flashing of the select element in IE\n ko.utils.setOptionNodeSelectionState(node, isSelected);\n }\n });\n }\n\n element.scrollTop = previousScrollTop;\n }\n\n if (ko.utils.tagNameLower(element) != \"select\") {\n throw new Error(\"selectedOptions binding applies only to SELECT elements\");\n }\n\n var updateFromModelComputed;\n ko.bindingEvent.subscribe(element, ko.bindingEvent.childrenComplete, function () {\n if (!updateFromModelComputed) {\n ko.utils.registerEventHandler(element, \"change\", updateFromView);\n updateFromModelComputed = ko.computed(updateFromModel, null, { disposeWhenNodeIsRemoved: element });\n } else {\n updateFromView();\n }\n }, null, { 'notifyImmediately': true });\n },\n 'update': function() {} // Keep for backwards compatibility with code that may have wrapped binding\n };\n ko.expressionRewriting.twoWayBindings['selectedOptions'] = true;\n ko.bindingHandlers['style'] = {\n 'update': function (element, valueAccessor) {\n var value = ko.utils.unwrapObservable(valueAccessor() || {});\n ko.utils.objectForEach(value, function(styleName, styleValue) {\n styleValue = ko.utils.unwrapObservable(styleValue);\n\n if (styleValue === null || styleValue === undefined || styleValue === false) {\n // Empty string removes the value, whereas null/undefined have no effect\n styleValue = \"\";\n }\n\n if (jQueryInstance) {\n jQueryInstance(element)['css'](styleName, styleValue);\n } else if (/^--/.test(styleName)) {\n // Is styleName a custom CSS property?\n element.style.setProperty(styleName, styleValue);\n } else {\n styleName = styleName.replace(/-(\\w)/g, function (all, letter) {\n return letter.toUpperCase();\n });\n\n var previousStyle = element.style[styleName];\n element.style[styleName] = styleValue;\n\n if (styleValue !== previousStyle && element.style[styleName] == previousStyle && !isNaN(styleValue)) {\n element.style[styleName] = styleValue + \"px\";\n }\n }\n });\n }\n };\n ko.bindingHandlers['submit'] = {\n 'init': function (element, valueAccessor, allBindings, viewModel, bindingContext) {\n if (typeof valueAccessor() != \"function\")\n throw new Error(\"The value for a submit binding must be a function\");\n ko.utils.registerEventHandler(element, \"submit\", function (event) {\n var handlerReturnValue;\n var value = valueAccessor();\n try { handlerReturnValue = value.call(bindingContext['$data'], element); }\n finally {\n if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.\n if (event.preventDefault)\n event.preventDefault();\n else\n event.returnValue = false;\n }\n }\n });\n }\n };\n ko.bindingHandlers['text'] = {\n 'init': function() {\n // Prevent binding on the dynamically-injected text node (as developers are unlikely to expect that, and it has security implications).\n // It should also make things faster, as we no longer have to consider whether the text node might be bindable.\n return { 'controlsDescendantBindings': true };\n },\n 'update': function (element, valueAccessor) {\n ko.utils.setTextContent(element, valueAccessor());\n }\n };\n ko.virtualElements.allowedBindings['text'] = true;\n (function () {\n\n if (window && window.navigator) {\n var parseVersion = function (matches) {\n if (matches) {\n return parseFloat(matches[1]);\n }\n };\n\n // Detect various browser versions because some old versions don't fully support the 'input' event\n var userAgent = window.navigator.userAgent,\n operaVersion, chromeVersion, safariVersion, firefoxVersion, ieVersion, edgeVersion;\n\n (operaVersion = window.opera && window.opera.version && parseInt(window.opera.version()))\n || (edgeVersion = parseVersion(userAgent.match(/Edge\\/([^ ]+)$/)))\n || (chromeVersion = parseVersion(userAgent.match(/Chrome\\/([^ ]+)/)))\n || (safariVersion = parseVersion(userAgent.match(/Version\\/([^ ]+) Safari/)))\n || (firefoxVersion = parseVersion(userAgent.match(/Firefox\\/([^ ]+)/)))\n || (ieVersion = ko.utils.ieVersion || parseVersion(userAgent.match(/MSIE ([^ ]+)/))) // Detects up to IE 10\n || (ieVersion = parseVersion(userAgent.match(/rv:([^ )]+)/))); // Detects IE 11\n }\n\n// IE 8 and 9 have bugs that prevent the normal events from firing when the value changes.\n// But it does fire the 'selectionchange' event on many of those, presumably because the\n// cursor is moving and that counts as the selection changing. The 'selectionchange' event is\n// fired at the document level only and doesn't directly indicate which element changed. We\n// set up just one event handler for the document and use 'activeElement' to determine which\n// element was changed.\n if (ieVersion >= 8 && ieVersion < 10) {\n var selectionChangeRegisteredName = ko.utils.domData.nextKey(),\n selectionChangeHandlerName = ko.utils.domData.nextKey();\n var selectionChangeHandler = function(event) {\n var target = this.activeElement,\n handler = target && ko.utils.domData.get(target, selectionChangeHandlerName);\n if (handler) {\n handler(event);\n }\n };\n var registerForSelectionChangeEvent = function (element, handler) {\n var ownerDoc = element.ownerDocument;\n if (!ko.utils.domData.get(ownerDoc, selectionChangeRegisteredName)) {\n ko.utils.domData.set(ownerDoc, selectionChangeRegisteredName, true);\n ko.utils.registerEventHandler(ownerDoc, 'selectionchange', selectionChangeHandler);\n }\n ko.utils.domData.set(element, selectionChangeHandlerName, handler);\n };\n }\n\n ko.bindingHandlers['textInput'] = {\n 'init': function (element, valueAccessor, allBindings) {\n\n var previousElementValue = element.value,\n timeoutHandle,\n elementValueBeforeEvent;\n\n var updateModel = function (event) {\n clearTimeout(timeoutHandle);\n elementValueBeforeEvent = timeoutHandle = undefined;\n\n var elementValue = element.value;\n if (previousElementValue !== elementValue) {\n // Provide a way for tests to know exactly which event was processed\n if (DEBUG && event) element['_ko_textInputProcessedEvent'] = event.type;\n previousElementValue = elementValue;\n ko.expressionRewriting.writeValueToProperty(valueAccessor(), allBindings, 'textInput', elementValue);\n }\n };\n\n var deferUpdateModel = function (event) {\n if (!timeoutHandle) {\n // The elementValueBeforeEvent variable is set *only* during the brief gap between an\n // event firing and the updateModel function running. This allows us to ignore model\n // updates that are from the previous state of the element, usually due to techniques\n // such as rateLimit. Such updates, if not ignored, can cause keystrokes to be lost.\n elementValueBeforeEvent = element.value;\n var handler = DEBUG ? updateModel.bind(element, {type: event.type}) : updateModel;\n timeoutHandle = ko.utils.setTimeout(handler, 4);\n }\n };\n\n // IE9 will mess up the DOM if you handle events synchronously which results in DOM changes (such as other bindings);\n // so we'll make sure all updates are asynchronous\n var ieUpdateModel = ko.utils.ieVersion == 9 ? deferUpdateModel : updateModel,\n ourUpdate = false;\n\n var updateView = function () {\n var modelValue = ko.utils.unwrapObservable(valueAccessor());\n\n if (modelValue === null || modelValue === undefined) {\n modelValue = '';\n }\n\n if (elementValueBeforeEvent !== undefined && modelValue === elementValueBeforeEvent) {\n ko.utils.setTimeout(updateView, 4);\n return;\n }\n\n // Update the element only if the element and model are different. On some browsers, updating the value\n // will move the cursor to the end of the input, which would be bad while the user is typing.\n if (element.value !== modelValue) {\n ourUpdate = true; // Make sure we ignore events (propertychange) that result from updating the value\n element.value = modelValue;\n ourUpdate = false;\n previousElementValue = element.value; // In case the browser changes the value (see #2281)\n }\n };\n\n var onEvent = function (event, handler) {\n ko.utils.registerEventHandler(element, event, handler);\n };\n\n if (DEBUG && ko.bindingHandlers['textInput']['_forceUpdateOn']) {\n // Provide a way for tests to specify exactly which events are bound\n ko.utils.arrayForEach(ko.bindingHandlers['textInput']['_forceUpdateOn'], function(eventName) {\n if (eventName.slice(0,5) == 'after') {\n onEvent(eventName.slice(5), deferUpdateModel);\n } else {\n onEvent(eventName, updateModel);\n }\n });\n } else {\n if (ieVersion) {\n // All versions (including 11) of Internet Explorer have a bug that they don't generate an input or propertychange event when ESC is pressed\n onEvent('keypress', updateModel);\n }\n if (ieVersion < 11) {\n // Internet Explorer <= 8 doesn't support the 'input' event, but does include 'propertychange' that fires whenever\n // any property of an element changes. Unlike 'input', it also fires if a property is changed from JavaScript code,\n // but that's an acceptable compromise for this binding. IE 9 and 10 support 'input', but since they don't always\n // fire it when using autocomplete, we'll use 'propertychange' for them also.\n onEvent('propertychange', function(event) {\n if (!ourUpdate && event.propertyName === 'value') {\n ieUpdateModel(event);\n }\n });\n }\n if (ieVersion == 8) {\n // IE 8 has a bug where it fails to fire 'propertychange' on the first update following a value change from\n // JavaScript code. It also doesn't fire if you clear the entire value. To fix this, we bind to the following\n // events too.\n onEvent('keyup', updateModel); // A single keystoke\n onEvent('keydown', updateModel); // The first character when a key is held down\n }\n if (registerForSelectionChangeEvent) {\n // Internet Explorer 9 doesn't fire the 'input' event when deleting text, including using\n // the backspace, delete, or ctrl-x keys, clicking the 'x' to clear the input, dragging text\n // out of the field, and cutting or deleting text using the context menu. 'selectionchange'\n // can detect all of those except dragging text out of the field, for which we use 'dragend'.\n // These are also needed in IE8 because of the bug described above.\n registerForSelectionChangeEvent(element, ieUpdateModel); // 'selectionchange' covers cut, paste, drop, delete, etc.\n onEvent('dragend', deferUpdateModel);\n }\n\n if (!ieVersion || ieVersion >= 9) {\n // All other supported browsers support the 'input' event, which fires whenever the content of the element is changed\n // through the user interface.\n onEvent('input', ieUpdateModel);\n }\n\n if (safariVersion < 5 && ko.utils.tagNameLower(element) === \"textarea\") {\n // Safari <5 doesn't fire the 'input' event for <textarea> elements (it does fire 'textInput'\n // but only when typing). So we'll just catch as much as we can with keydown, cut, and paste.\n onEvent('keydown', deferUpdateModel);\n onEvent('paste', deferUpdateModel);\n onEvent('cut', deferUpdateModel);\n } else if (operaVersion < 11) {\n // Opera 10 doesn't always fire the 'input' event for cut, paste, undo & drop operations.\n // We can try to catch some of those using 'keydown'.\n onEvent('keydown', deferUpdateModel);\n } else if (firefoxVersion < 4.0) {\n // Firefox <= 3.6 doesn't fire the 'input' event when text is filled in through autocomplete\n onEvent('DOMAutoComplete', updateModel);\n\n // Firefox <=3.5 doesn't fire the 'input' event when text is dropped into the input.\n onEvent('dragdrop', updateModel); // <3.5\n onEvent('drop', updateModel); // 3.5\n } else if (edgeVersion && element.type === \"number\") {\n // Microsoft Edge doesn't fire 'input' or 'change' events for number inputs when\n // the value is changed via the up / down arrow keys\n onEvent('keydown', deferUpdateModel);\n }\n }\n\n // Bind to the change event so that we can catch programmatic updates of the value that fire this event.\n onEvent('change', updateModel);\n\n // To deal with browsers that don't notify any kind of event for some changes (IE, Safari, etc.)\n onEvent('blur', updateModel);\n\n ko.computed(updateView, null, { disposeWhenNodeIsRemoved: element });\n }\n };\n ko.expressionRewriting.twoWayBindings['textInput'] = true;\n\n// textinput is an alias for textInput\n ko.bindingHandlers['textinput'] = {\n // preprocess is the only way to set up a full alias\n 'preprocess': function (value, name, addBinding) {\n addBinding('textInput', value);\n }\n };\n\n })();ko.bindingHandlers['uniqueName'] = {\n 'init': function (element, valueAccessor) {\n if (valueAccessor()) {\n var name = \"ko_unique_\" + (++ko.bindingHandlers['uniqueName'].currentIndex);\n ko.utils.setElementName(element, name);\n }\n }\n };\n ko.bindingHandlers['uniqueName'].currentIndex = 0;\n ko.bindingHandlers['using'] = {\n 'init': function(element, valueAccessor, allBindings, viewModel, bindingContext) {\n var options;\n\n if (allBindings['has']('as')) {\n options = { 'as': allBindings.get('as'), 'noChildContext': allBindings.get('noChildContext') };\n }\n\n var innerContext = bindingContext['createChildContext'](valueAccessor, options);\n ko.applyBindingsToDescendants(innerContext, element);\n\n return { 'controlsDescendantBindings': true };\n }\n };\n ko.virtualElements.allowedBindings['using'] = true;\n ko.bindingHandlers['value'] = {\n 'init': function (element, valueAccessor, allBindings) {\n var tagName = ko.utils.tagNameLower(element),\n isInputElement = tagName == \"input\";\n\n // If the value binding is placed on a radio/checkbox, then just pass through to checkedValue and quit\n if (isInputElement && (element.type == \"checkbox\" || element.type == \"radio\")) {\n ko.applyBindingAccessorsToNode(element, { 'checkedValue': valueAccessor });\n return;\n }\n\n var eventsToCatch = [];\n var requestedEventsToCatch = allBindings.get(\"valueUpdate\");\n var propertyChangedFired = false;\n var elementValueBeforeEvent = null;\n\n if (requestedEventsToCatch) {\n // Allow both individual event names, and arrays of event names\n if (typeof requestedEventsToCatch == \"string\") {\n eventsToCatch = [requestedEventsToCatch];\n } else {\n eventsToCatch = ko.utils.arrayGetDistinctValues(requestedEventsToCatch);\n }\n ko.utils.arrayRemoveItem(eventsToCatch, \"change\"); // We'll subscribe to \"change\" events later\n }\n\n var valueUpdateHandler = function() {\n elementValueBeforeEvent = null;\n propertyChangedFired = false;\n var modelValue = valueAccessor();\n var elementValue = ko.selectExtensions.readValue(element);\n ko.expressionRewriting.writeValueToProperty(modelValue, allBindings, 'value', elementValue);\n }\n\n // Workaround for https://github.com/SteveSanderson/knockout/issues/122\n // IE doesn't fire \"change\" events on textboxes if the user selects a value from its autocomplete list\n var ieAutoCompleteHackNeeded = ko.utils.ieVersion && isInputElement && element.type == \"text\"\n && element.autocomplete != \"off\" && (!element.form || element.form.autocomplete != \"off\");\n if (ieAutoCompleteHackNeeded && ko.utils.arrayIndexOf(eventsToCatch, \"propertychange\") == -1) {\n ko.utils.registerEventHandler(element, \"propertychange\", function () { propertyChangedFired = true });\n ko.utils.registerEventHandler(element, \"focus\", function () { propertyChangedFired = false });\n ko.utils.registerEventHandler(element, \"blur\", function() {\n if (propertyChangedFired) {\n valueUpdateHandler();\n }\n });\n }\n\n ko.utils.arrayForEach(eventsToCatch, function(eventName) {\n // The syntax \"after<eventname>\" means \"run the handler asynchronously after the event\"\n // This is useful, for example, to catch \"keydown\" events after the browser has updated the control\n // (otherwise, ko.selectExtensions.readValue(this) will receive the control's value *before* the key event)\n var handler = valueUpdateHandler;\n if (ko.utils.stringStartsWith(eventName, \"after\")) {\n handler = function() {\n // The elementValueBeforeEvent variable is non-null *only* during the brief gap between\n // a keyX event firing and the valueUpdateHandler running, which is scheduled to happen\n // at the earliest asynchronous opportunity. We store this temporary information so that\n // if, between keyX and valueUpdateHandler, the underlying model value changes separately,\n // we can overwrite that model value change with the value the user just typed. Otherwise,\n // techniques like rateLimit can trigger model changes at critical moments that will\n // override the user's inputs, causing keystrokes to be lost.\n elementValueBeforeEvent = ko.selectExtensions.readValue(element);\n ko.utils.setTimeout(valueUpdateHandler, 0);\n };\n eventName = eventName.substring(\"after\".length);\n }\n ko.utils.registerEventHandler(element, eventName, handler);\n });\n\n var updateFromModel;\n\n if (isInputElement && element.type == \"file\") {\n // For file input elements, can only write the empty string\n updateFromModel = function () {\n var newValue = ko.utils.unwrapObservable(valueAccessor());\n if (newValue === null || newValue === undefined || newValue === \"\") {\n element.value = \"\";\n } else {\n ko.dependencyDetection.ignore(valueUpdateHandler); // reset the model to match the element\n }\n }\n } else {\n updateFromModel = function () {\n var newValue = ko.utils.unwrapObservable(valueAccessor());\n var elementValue = ko.selectExtensions.readValue(element);\n\n if (elementValueBeforeEvent !== null && newValue === elementValueBeforeEvent) {\n ko.utils.setTimeout(updateFromModel, 0);\n return;\n }\n\n var valueHasChanged = newValue !== elementValue;\n\n if (valueHasChanged || elementValue === undefined) {\n if (tagName === \"select\") {\n var allowUnset = allBindings.get('valueAllowUnset');\n ko.selectExtensions.writeValue(element, newValue, allowUnset);\n if (!allowUnset && newValue !== ko.selectExtensions.readValue(element)) {\n // If you try to set a model value that can't be represented in an already-populated dropdown, reject that change,\n // because you're not allowed to have a model value that disagrees with a visible UI selection.\n ko.dependencyDetection.ignore(valueUpdateHandler);\n }\n } else {\n ko.selectExtensions.writeValue(element, newValue);\n }\n }\n };\n }\n\n if (tagName === \"select\") {\n var updateFromModelComputed;\n ko.bindingEvent.subscribe(element, ko.bindingEvent.childrenComplete, function () {\n if (!updateFromModelComputed) {\n ko.utils.registerEventHandler(element, \"change\", valueUpdateHandler);\n updateFromModelComputed = ko.computed(updateFromModel, null, { disposeWhenNodeIsRemoved: element });\n } else if (allBindings.get('valueAllowUnset')) {\n updateFromModel();\n } else {\n valueUpdateHandler();\n }\n }, null, { 'notifyImmediately': true });\n } else {\n ko.utils.registerEventHandler(element, \"change\", valueUpdateHandler);\n ko.computed(updateFromModel, null, { disposeWhenNodeIsRemoved: element });\n }\n },\n 'update': function() {} // Keep for backwards compatibility with code that may have wrapped value binding\n };\n ko.expressionRewriting.twoWayBindings['value'] = true;\n ko.bindingHandlers['visible'] = {\n 'update': function (element, valueAccessor) {\n var value = ko.utils.unwrapObservable(valueAccessor());\n var isCurrentlyVisible = !(element.style.display == \"none\");\n if (value && !isCurrentlyVisible)\n element.style.display = \"\";\n else if ((!value) && isCurrentlyVisible)\n element.style.display = \"none\";\n }\n };\n\n ko.bindingHandlers['hidden'] = {\n 'update': function (element, valueAccessor) {\n ko.bindingHandlers['visible']['update'](element, function() { return !ko.utils.unwrapObservable(valueAccessor()) });\n }\n };\n// 'click' is just a shorthand for the usual full-length event:{click:handler}\n makeEventHandlerShortcut('click');\n// If you want to make a custom template engine,\n//\n// [1] Inherit from this class (like ko.nativeTemplateEngine does)\n// [2] Override 'renderTemplateSource', supplying a function with this signature:\n//\n// function (templateSource, bindingContext, options) {\n// // - templateSource.text() is the text of the template you should render\n// // - bindingContext.$data is the data you should pass into the template\n// // - you might also want to make bindingContext.$parent, bindingContext.$parents,\n// // and bindingContext.$root available in the template too\n// // - options gives you access to any other properties set on \"data-bind: { template: options }\"\n// // - templateDocument is the document object of the template\n// //\n// // Return value: an array of DOM nodes\n// }\n//\n// [3] Override 'createJavaScriptEvaluatorBlock', supplying a function with this signature:\n//\n// function (script) {\n// // Return value: Whatever syntax means \"Evaluate the JavaScript statement 'script' and output the result\"\n// // For example, the jquery.tmpl template engine converts 'someScript' to '${ someScript }'\n// }\n//\n// This is only necessary if you want to allow data-bind attributes to reference arbitrary template variables.\n// If you don't want to allow that, you can set the property 'allowTemplateRewriting' to false (like ko.nativeTemplateEngine does)\n// and then you don't need to override 'createJavaScriptEvaluatorBlock'.\n\n ko.templateEngine = function () { };\n\n ko.templateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options, templateDocument) {\n throw new Error(\"Override renderTemplateSource\");\n };\n\n ko.templateEngine.prototype['createJavaScriptEvaluatorBlock'] = function (script) {\n throw new Error(\"Override createJavaScriptEvaluatorBlock\");\n };\n\n ko.templateEngine.prototype['makeTemplateSource'] = function(template, templateDocument) {\n // Named template\n if (typeof template == \"string\") {\n templateDocument = templateDocument || document;\n var elem = templateDocument.getElementById(template);\n if (!elem)\n throw new Error(\"Cannot find template with ID \" + template);\n return new ko.templateSources.domElement(elem);\n } else if ((template.nodeType == 1) || (template.nodeType == 8)) {\n // Anonymous template\n return new ko.templateSources.anonymousTemplate(template);\n } else\n throw new Error(\"Unknown template type: \" + template);\n };\n\n ko.templateEngine.prototype['renderTemplate'] = function (template, bindingContext, options, templateDocument) {\n var templateSource = this['makeTemplateSource'](template, templateDocument);\n return this['renderTemplateSource'](templateSource, bindingContext, options, templateDocument);\n };\n\n ko.templateEngine.prototype['isTemplateRewritten'] = function (template, templateDocument) {\n // Skip rewriting if requested\n if (this['allowTemplateRewriting'] === false)\n return true;\n return this['makeTemplateSource'](template, templateDocument)['data'](\"isRewritten\");\n };\n\n ko.templateEngine.prototype['rewriteTemplate'] = function (template, rewriterCallback, templateDocument) {\n var templateSource = this['makeTemplateSource'](template, templateDocument);\n var rewritten = rewriterCallback(templateSource['text']());\n templateSource['text'](rewritten);\n templateSource['data'](\"isRewritten\", true);\n };\n\n ko.exportSymbol('templateEngine', ko.templateEngine);\n\n ko.templateRewriting = (function () {\n var memoizeDataBindingAttributeSyntaxRegex = /(<([a-z]+\\d*)(?:\\s+(?!data-bind\\s*=\\s*)[a-z0-9\\-]+(?:=(?:\\\"[^\\\"]*\\\"|\\'[^\\']*\\'|[^>]*))?)*\\s+)data-bind\\s*=\\s*([\"'])([\\s\\S]*?)\\3/gi;\n var memoizeVirtualContainerBindingSyntaxRegex = /<!--\\s*ko\\b\\s*([\\s\\S]*?)\\s*-->/g;\n\n function validateDataBindValuesForRewriting(keyValueArray) {\n var allValidators = ko.expressionRewriting.bindingRewriteValidators;\n for (var i = 0; i < keyValueArray.length; i++) {\n var key = keyValueArray[i]['key'];\n if (Object.prototype.hasOwnProperty.call(allValidators, key)) {\n var validator = allValidators[key];\n\n if (typeof validator === \"function\") {\n var possibleErrorMessage = validator(keyValueArray[i]['value']);\n if (possibleErrorMessage)\n throw new Error(possibleErrorMessage);\n } else if (!validator) {\n throw new Error(\"This template engine does not support the '\" + key + \"' binding within its templates\");\n }\n }\n }\n }\n\n function constructMemoizedTagReplacement(dataBindAttributeValue, tagToRetain, nodeName, templateEngine) {\n var dataBindKeyValueArray = ko.expressionRewriting.parseObjectLiteral(dataBindAttributeValue);\n validateDataBindValuesForRewriting(dataBindKeyValueArray);\n var rewrittenDataBindAttributeValue = ko.expressionRewriting.preProcessBindings(dataBindKeyValueArray, {'valueAccessors':true});\n\n // For no obvious reason, Opera fails to evaluate rewrittenDataBindAttributeValue unless it's wrapped in an additional\n // anonymous function, even though Opera's built-in debugger can evaluate it anyway. No other browser requires this\n // extra indirection.\n var applyBindingsToNextSiblingScript =\n \"ko.__tr_ambtns(function($context,$element){return(function(){return{ \" + rewrittenDataBindAttributeValue + \" } })()},'\" + nodeName.toLowerCase() + \"')\";\n return templateEngine['createJavaScriptEvaluatorBlock'](applyBindingsToNextSiblingScript) + tagToRetain;\n }\n\n return {\n ensureTemplateIsRewritten: function (template, templateEngine, templateDocument) {\n if (!templateEngine['isTemplateRewritten'](template, templateDocument))\n templateEngine['rewriteTemplate'](template, function (htmlString) {\n return ko.templateRewriting.memoizeBindingAttributeSyntax(htmlString, templateEngine);\n }, templateDocument);\n },\n\n memoizeBindingAttributeSyntax: function (htmlString, templateEngine) {\n return htmlString.replace(memoizeDataBindingAttributeSyntaxRegex, function () {\n return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[4], /* tagToRetain: */ arguments[1], /* nodeName: */ arguments[2], templateEngine);\n }).replace(memoizeVirtualContainerBindingSyntaxRegex, function() {\n return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[1], /* tagToRetain: */ \"<!-- ko -->\", /* nodeName: */ \"#comment\", templateEngine);\n });\n },\n\n applyMemoizedBindingsToNextSibling: function (bindings, nodeName) {\n return ko.memoization.memoize(function (domNode, bindingContext) {\n var nodeToBind = domNode.nextSibling;\n if (nodeToBind && nodeToBind.nodeName.toLowerCase() === nodeName) {\n ko.applyBindingAccessorsToNode(nodeToBind, bindings, bindingContext);\n }\n });\n }\n }\n })();\n\n\n// Exported only because it has to be referenced by string lookup from within rewritten template\n ko.exportSymbol('__tr_ambtns', ko.templateRewriting.applyMemoizedBindingsToNextSibling);\n (function() {\n // A template source represents a read/write way of accessing a template. This is to eliminate the need for template loading/saving\n // logic to be duplicated in every template engine (and means they can all work with anonymous templates, etc.)\n //\n // Two are provided by default:\n // 1. ko.templateSources.domElement - reads/writes the text content of an arbitrary DOM element\n // 2. ko.templateSources.anonymousElement - uses ko.utils.domData to read/write text *associated* with the DOM element, but\n // without reading/writing the actual element text content, since it will be overwritten\n // with the rendered template output.\n // You can implement your own template source if you want to fetch/store templates somewhere other than in DOM elements.\n // Template sources need to have the following functions:\n // text() \t\t\t- returns the template text from your storage location\n // text(value)\t\t- writes the supplied template text to your storage location\n // data(key)\t\t\t- reads values stored using data(key, value) - see below\n // data(key, value)\t- associates \"value\" with this template and the key \"key\". Is used to store information like \"isRewritten\".\n //\n // Optionally, template sources can also have the following functions:\n // nodes() - returns a DOM element containing the nodes of this template, where available\n // nodes(value) - writes the given DOM element to your storage location\n // If a DOM element is available for a given template source, template engines are encouraged to use it in preference over text()\n // for improved speed. However, all templateSources must supply text() even if they don't supply nodes().\n //\n // Once you've implemented a templateSource, make your template engine use it by subclassing whatever template engine you were\n // using and overriding \"makeTemplateSource\" to return an instance of your custom template source.\n\n ko.templateSources = {};\n\n // ---- ko.templateSources.domElement -----\n\n // template types\n var templateScript = 1,\n templateTextArea = 2,\n templateTemplate = 3,\n templateElement = 4;\n\n ko.templateSources.domElement = function(element) {\n this.domElement = element;\n\n if (element) {\n var tagNameLower = ko.utils.tagNameLower(element);\n this.templateType =\n tagNameLower === \"script\" ? templateScript :\n tagNameLower === \"textarea\" ? templateTextArea :\n // For browsers with proper <template> element support, where the .content property gives a document fragment\n tagNameLower == \"template\" && element.content && element.content.nodeType === 11 ? templateTemplate :\n templateElement;\n }\n }\n\n ko.templateSources.domElement.prototype['text'] = function(/* valueToWrite */) {\n var elemContentsProperty = this.templateType === templateScript ? \"text\"\n : this.templateType === templateTextArea ? \"value\"\n : \"innerHTML\";\n\n if (arguments.length == 0) {\n return this.domElement[elemContentsProperty];\n } else {\n var valueToWrite = arguments[0];\n if (elemContentsProperty === \"innerHTML\")\n ko.utils.setHtml(this.domElement, valueToWrite);\n else\n this.domElement[elemContentsProperty] = valueToWrite;\n }\n };\n\n var dataDomDataPrefix = ko.utils.domData.nextKey() + \"_\";\n ko.templateSources.domElement.prototype['data'] = function(key /*, valueToWrite */) {\n if (arguments.length === 1) {\n return ko.utils.domData.get(this.domElement, dataDomDataPrefix + key);\n } else {\n ko.utils.domData.set(this.domElement, dataDomDataPrefix + key, arguments[1]);\n }\n };\n\n var templatesDomDataKey = ko.utils.domData.nextKey();\n function getTemplateDomData(element) {\n return ko.utils.domData.get(element, templatesDomDataKey) || {};\n }\n function setTemplateDomData(element, data) {\n ko.utils.domData.set(element, templatesDomDataKey, data);\n }\n\n ko.templateSources.domElement.prototype['nodes'] = function(/* valueToWrite */) {\n var element = this.domElement;\n if (arguments.length == 0) {\n var templateData = getTemplateDomData(element),\n nodes = templateData.containerData || (\n this.templateType === templateTemplate ? element.content :\n this.templateType === templateElement ? element :\n undefined);\n if (!nodes || templateData.alwaysCheckText) {\n // If the template is associated with an element that stores the template as text,\n // parse and cache the nodes whenever there's new text content available. This allows\n // the user to update the template content by updating the text of template node.\n var text = this['text']();\n if (text && text !== templateData.textData) {\n nodes = ko.utils.parseHtmlForTemplateNodes(text, element.ownerDocument);\n setTemplateDomData(element, {containerData: nodes, textData: text, alwaysCheckText: true});\n }\n }\n return nodes;\n } else {\n var valueToWrite = arguments[0];\n if (this.templateType !== undefined) {\n this['text'](\"\"); // clear the text from the node\n }\n setTemplateDomData(element, {containerData: valueToWrite});\n }\n };\n\n // ---- ko.templateSources.anonymousTemplate -----\n // Anonymous templates are normally saved/retrieved as DOM nodes through \"nodes\".\n // For compatibility, you can also read \"text\"; it will be serialized from the nodes on demand.\n // Writing to \"text\" is still supported, but then the template data will not be available as DOM nodes.\n\n ko.templateSources.anonymousTemplate = function(element) {\n this.domElement = element;\n }\n ko.templateSources.anonymousTemplate.prototype = new ko.templateSources.domElement();\n ko.templateSources.anonymousTemplate.prototype.constructor = ko.templateSources.anonymousTemplate;\n ko.templateSources.anonymousTemplate.prototype['text'] = function(/* valueToWrite */) {\n if (arguments.length == 0) {\n var templateData = getTemplateDomData(this.domElement);\n if (templateData.textData === undefined && templateData.containerData)\n templateData.textData = templateData.containerData.innerHTML;\n return templateData.textData;\n } else {\n var valueToWrite = arguments[0];\n setTemplateDomData(this.domElement, {textData: valueToWrite});\n }\n };\n\n ko.exportSymbol('templateSources', ko.templateSources);\n ko.exportSymbol('templateSources.domElement', ko.templateSources.domElement);\n ko.exportSymbol('templateSources.anonymousTemplate', ko.templateSources.anonymousTemplate);\n })();\n (function () {\n var _templateEngine;\n ko.setTemplateEngine = function (templateEngine) {\n if ((templateEngine != undefined) && !(templateEngine instanceof ko.templateEngine))\n throw new Error(\"templateEngine must inherit from ko.templateEngine\");\n _templateEngine = templateEngine;\n }\n\n function invokeForEachNodeInContinuousRange(firstNode, lastNode, action) {\n var node, nextInQueue = firstNode, firstOutOfRangeNode = ko.virtualElements.nextSibling(lastNode);\n while (nextInQueue && ((node = nextInQueue) !== firstOutOfRangeNode)) {\n nextInQueue = ko.virtualElements.nextSibling(node);\n action(node, nextInQueue);\n }\n }\n\n function activateBindingsOnContinuousNodeArray(continuousNodeArray, bindingContext) {\n // To be used on any nodes that have been rendered by a template and have been inserted into some parent element\n // Walks through continuousNodeArray (which *must* be continuous, i.e., an uninterrupted sequence of sibling nodes, because\n // the algorithm for walking them relies on this), and for each top-level item in the virtual-element sense,\n // (1) Does a regular \"applyBindings\" to associate bindingContext with this node and to activate any non-memoized bindings\n // (2) Unmemoizes any memos in the DOM subtree (e.g., to activate bindings that had been memoized during template rewriting)\n\n if (continuousNodeArray.length) {\n var firstNode = continuousNodeArray[0],\n lastNode = continuousNodeArray[continuousNodeArray.length - 1],\n parentNode = firstNode.parentNode,\n provider = ko.bindingProvider['instance'],\n preprocessNode = provider['preprocessNode'];\n\n if (preprocessNode) {\n invokeForEachNodeInContinuousRange(firstNode, lastNode, function(node, nextNodeInRange) {\n var nodePreviousSibling = node.previousSibling;\n var newNodes = preprocessNode.call(provider, node);\n if (newNodes) {\n if (node === firstNode)\n firstNode = newNodes[0] || nextNodeInRange;\n if (node === lastNode)\n lastNode = newNodes[newNodes.length - 1] || nodePreviousSibling;\n }\n });\n\n // Because preprocessNode can change the nodes, including the first and last nodes, update continuousNodeArray to match.\n // We need the full set, including inner nodes, because the unmemoize step might remove the first node (and so the real\n // first node needs to be in the array).\n continuousNodeArray.length = 0;\n if (!firstNode) { // preprocessNode might have removed all the nodes, in which case there's nothing left to do\n return;\n }\n if (firstNode === lastNode) {\n continuousNodeArray.push(firstNode);\n } else {\n continuousNodeArray.push(firstNode, lastNode);\n ko.utils.fixUpContinuousNodeArray(continuousNodeArray, parentNode);\n }\n }\n\n // Need to applyBindings *before* unmemoziation, because unmemoization might introduce extra nodes (that we don't want to re-bind)\n // whereas a regular applyBindings won't introduce new memoized nodes\n invokeForEachNodeInContinuousRange(firstNode, lastNode, function(node) {\n if (node.nodeType === 1 || node.nodeType === 8)\n ko.applyBindings(bindingContext, node);\n });\n invokeForEachNodeInContinuousRange(firstNode, lastNode, function(node) {\n if (node.nodeType === 1 || node.nodeType === 8)\n ko.memoization.unmemoizeDomNodeAndDescendants(node, [bindingContext]);\n });\n\n // Make sure any changes done by applyBindings or unmemoize are reflected in the array\n ko.utils.fixUpContinuousNodeArray(continuousNodeArray, parentNode);\n }\n }\n\n function getFirstNodeFromPossibleArray(nodeOrNodeArray) {\n return nodeOrNodeArray.nodeType ? nodeOrNodeArray\n : nodeOrNodeArray.length > 0 ? nodeOrNodeArray[0]\n : null;\n }\n\n function executeTemplate(targetNodeOrNodeArray, renderMode, template, bindingContext, options) {\n options = options || {};\n var firstTargetNode = targetNodeOrNodeArray && getFirstNodeFromPossibleArray(targetNodeOrNodeArray);\n var templateDocument = (firstTargetNode || template || {}).ownerDocument;\n var templateEngineToUse = (options['templateEngine'] || _templateEngine);\n ko.templateRewriting.ensureTemplateIsRewritten(template, templateEngineToUse, templateDocument);\n var renderedNodesArray = templateEngineToUse['renderTemplate'](template, bindingContext, options, templateDocument);\n\n // Loosely check result is an array of DOM nodes\n if ((typeof renderedNodesArray.length != \"number\") || (renderedNodesArray.length > 0 && typeof renderedNodesArray[0].nodeType != \"number\"))\n throw new Error(\"Template engine must return an array of DOM nodes\");\n\n var haveAddedNodesToParent = false;\n switch (renderMode) {\n case \"replaceChildren\":\n ko.virtualElements.setDomNodeChildren(targetNodeOrNodeArray, renderedNodesArray);\n haveAddedNodesToParent = true;\n break;\n case \"replaceNode\":\n ko.utils.replaceDomNodes(targetNodeOrNodeArray, renderedNodesArray);\n haveAddedNodesToParent = true;\n break;\n case \"ignoreTargetNode\": break;\n default:\n throw new Error(\"Unknown renderMode: \" + renderMode);\n }\n\n if (haveAddedNodesToParent) {\n activateBindingsOnContinuousNodeArray(renderedNodesArray, bindingContext);\n if (options['afterRender']) {\n ko.dependencyDetection.ignore(options['afterRender'], null, [renderedNodesArray, bindingContext[options['as'] || '$data']]);\n }\n if (renderMode == \"replaceChildren\") {\n ko.bindingEvent.notify(targetNodeOrNodeArray, ko.bindingEvent.childrenComplete);\n }\n }\n\n return renderedNodesArray;\n }\n\n function resolveTemplateName(template, data, context) {\n // The template can be specified as:\n if (ko.isObservable(template)) {\n // 1. An observable, with string value\n return template();\n } else if (typeof template === 'function') {\n // 2. A function of (data, context) returning a string\n return template(data, context);\n } else {\n // 3. A string\n return template;\n }\n }\n\n ko.renderTemplate = function (template, dataOrBindingContext, options, targetNodeOrNodeArray, renderMode) {\n options = options || {};\n if ((options['templateEngine'] || _templateEngine) == undefined)\n throw new Error(\"Set a template engine before calling renderTemplate\");\n renderMode = renderMode || \"replaceChildren\";\n\n if (targetNodeOrNodeArray) {\n var firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);\n\n var whenToDispose = function () { return (!firstTargetNode) || !ko.utils.domNodeIsAttachedToDocument(firstTargetNode); }; // Passive disposal (on next evaluation)\n var activelyDisposeWhenNodeIsRemoved = (firstTargetNode && renderMode == \"replaceNode\") ? firstTargetNode.parentNode : firstTargetNode;\n\n return ko.dependentObservable( // So the DOM is automatically updated when any dependency changes\n function () {\n // Ensure we've got a proper binding context to work with\n var bindingContext = (dataOrBindingContext && (dataOrBindingContext instanceof ko.bindingContext))\n ? dataOrBindingContext\n : new ko.bindingContext(dataOrBindingContext, null, null, null, { \"exportDependencies\": true });\n\n var templateName = resolveTemplateName(template, bindingContext['$data'], bindingContext),\n renderedNodesArray = executeTemplate(targetNodeOrNodeArray, renderMode, templateName, bindingContext, options);\n\n if (renderMode == \"replaceNode\") {\n targetNodeOrNodeArray = renderedNodesArray;\n firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);\n }\n },\n null,\n { disposeWhen: whenToDispose, disposeWhenNodeIsRemoved: activelyDisposeWhenNodeIsRemoved }\n );\n } else {\n // We don't yet have a DOM node to evaluate, so use a memo and render the template later when there is a DOM node\n return ko.memoization.memoize(function (domNode) {\n ko.renderTemplate(template, dataOrBindingContext, options, domNode, \"replaceNode\");\n });\n }\n };\n\n ko.renderTemplateForEach = function (template, arrayOrObservableArray, options, targetNode, parentBindingContext) {\n // Since setDomNodeChildrenFromArrayMapping always calls executeTemplateForArrayItem and then\n // activateBindingsCallback for added items, we can store the binding context in the former to use in the latter.\n var arrayItemContext, asName = options['as'];\n\n // This will be called by setDomNodeChildrenFromArrayMapping to get the nodes to add to targetNode\n var executeTemplateForArrayItem = function (arrayValue, index) {\n // Support selecting template as a function of the data being rendered\n arrayItemContext = parentBindingContext['createChildContext'](arrayValue, {\n 'as': asName,\n 'noChildContext': options['noChildContext'],\n 'extend': function(context) {\n context['$index'] = index;\n if (asName) {\n context[asName + \"Index\"] = index;\n }\n }\n });\n\n var templateName = resolveTemplateName(template, arrayValue, arrayItemContext);\n return executeTemplate(targetNode, \"ignoreTargetNode\", templateName, arrayItemContext, options);\n };\n\n // This will be called whenever setDomNodeChildrenFromArrayMapping has added nodes to targetNode\n var activateBindingsCallback = function(arrayValue, addedNodesArray, index) {\n activateBindingsOnContinuousNodeArray(addedNodesArray, arrayItemContext);\n if (options['afterRender'])\n options['afterRender'](addedNodesArray, arrayValue);\n\n // release the \"cache\" variable, so that it can be collected by\n // the GC when its value isn't used from within the bindings anymore.\n arrayItemContext = null;\n };\n\n var setDomNodeChildrenFromArrayMapping = function (newArray, changeList) {\n // Call setDomNodeChildrenFromArrayMapping, ignoring any observables unwrapped within (most likely from a callback function).\n // If the array items are observables, though, they will be unwrapped in executeTemplateForArrayItem and managed within setDomNodeChildrenFromArrayMapping.\n ko.dependencyDetection.ignore(ko.utils.setDomNodeChildrenFromArrayMapping, null, [targetNode, newArray, executeTemplateForArrayItem, options, activateBindingsCallback, changeList]);\n ko.bindingEvent.notify(targetNode, ko.bindingEvent.childrenComplete);\n };\n\n var shouldHideDestroyed = (options['includeDestroyed'] === false) || (ko.options['foreachHidesDestroyed'] && !options['includeDestroyed']);\n\n if (!shouldHideDestroyed && !options['beforeRemove'] && ko.isObservableArray(arrayOrObservableArray)) {\n setDomNodeChildrenFromArrayMapping(arrayOrObservableArray.peek());\n\n var subscription = arrayOrObservableArray.subscribe(function (changeList) {\n setDomNodeChildrenFromArrayMapping(arrayOrObservableArray(), changeList);\n }, null, \"arrayChange\");\n subscription.disposeWhenNodeIsRemoved(targetNode);\n\n return subscription;\n } else {\n return ko.dependentObservable(function () {\n var unwrappedArray = ko.utils.unwrapObservable(arrayOrObservableArray) || [];\n if (typeof unwrappedArray.length == \"undefined\") // Coerce single value into array\n unwrappedArray = [unwrappedArray];\n\n if (shouldHideDestroyed) {\n // Filter out any entries marked as destroyed\n unwrappedArray = ko.utils.arrayFilter(unwrappedArray, function(item) {\n return item === undefined || item === null || !ko.utils.unwrapObservable(item['_destroy']);\n });\n }\n setDomNodeChildrenFromArrayMapping(unwrappedArray);\n\n }, null, { disposeWhenNodeIsRemoved: targetNode });\n }\n };\n\n var templateComputedDomDataKey = ko.utils.domData.nextKey();\n function disposeOldComputedAndStoreNewOne(element, newComputed) {\n var oldComputed = ko.utils.domData.get(element, templateComputedDomDataKey);\n if (oldComputed && (typeof(oldComputed.dispose) == 'function'))\n oldComputed.dispose();\n ko.utils.domData.set(element, templateComputedDomDataKey, (newComputed && (!newComputed.isActive || newComputed.isActive())) ? newComputed : undefined);\n }\n\n var cleanContainerDomDataKey = ko.utils.domData.nextKey();\n ko.bindingHandlers['template'] = {\n 'init': function(element, valueAccessor) {\n // Support anonymous templates\n var bindingValue = ko.utils.unwrapObservable(valueAccessor());\n if (typeof bindingValue == \"string\" || 'name' in bindingValue) {\n // It's a named template - clear the element\n ko.virtualElements.emptyNode(element);\n } else if ('nodes' in bindingValue) {\n // We've been given an array of DOM nodes. Save them as the template source.\n // There is no known use case for the node array being an observable array (if the output\n // varies, put that behavior *into* your template - that's what templates are for), and\n // the implementation would be a mess, so assert that it's not observable.\n var nodes = bindingValue['nodes'] || [];\n if (ko.isObservable(nodes)) {\n throw new Error('The \"nodes\" option must be a plain, non-observable array.');\n }\n\n // If the nodes are already attached to a KO-generated container, we reuse that container without moving the\n // elements to a new one (we check only the first node, as the nodes are always moved together)\n var container = nodes[0] && nodes[0].parentNode;\n if (!container || !ko.utils.domData.get(container, cleanContainerDomDataKey)) {\n container = ko.utils.moveCleanedNodesToContainerElement(nodes);\n ko.utils.domData.set(container, cleanContainerDomDataKey, true);\n }\n\n new ko.templateSources.anonymousTemplate(element)['nodes'](container);\n } else {\n // It's an anonymous template - store the element contents, then clear the element\n var templateNodes = ko.virtualElements.childNodes(element);\n if (templateNodes.length > 0) {\n var container = ko.utils.moveCleanedNodesToContainerElement(templateNodes); // This also removes the nodes from their current parent\n new ko.templateSources.anonymousTemplate(element)['nodes'](container);\n } else {\n throw new Error(\"Anonymous template defined, but no template content was provided\");\n }\n }\n return { 'controlsDescendantBindings': true };\n },\n 'update': function (element, valueAccessor, allBindings, viewModel, bindingContext) {\n var value = valueAccessor(),\n options = ko.utils.unwrapObservable(value),\n shouldDisplay = true,\n templateComputed = null,\n template;\n\n if (typeof options == \"string\") {\n template = value;\n options = {};\n } else {\n template = 'name' in options ? options['name'] : element;\n\n // Support \"if\"/\"ifnot\" conditions\n if ('if' in options)\n shouldDisplay = ko.utils.unwrapObservable(options['if']);\n if (shouldDisplay && 'ifnot' in options)\n shouldDisplay = !ko.utils.unwrapObservable(options['ifnot']);\n\n // Don't show anything if an empty name is given (see #2446)\n if (shouldDisplay && !template) {\n shouldDisplay = false;\n }\n }\n\n if ('foreach' in options) {\n // Render once for each data point (treating data set as empty if shouldDisplay==false)\n var dataArray = (shouldDisplay && options['foreach']) || [];\n templateComputed = ko.renderTemplateForEach(template, dataArray, options, element, bindingContext);\n } else if (!shouldDisplay) {\n ko.virtualElements.emptyNode(element);\n } else {\n // Render once for this single data point (or use the viewModel if no data was provided)\n var innerBindingContext = bindingContext;\n if ('data' in options) {\n innerBindingContext = bindingContext['createChildContext'](options['data'], {\n 'as': options['as'],\n 'noChildContext': options['noChildContext'],\n 'exportDependencies': true\n });\n }\n templateComputed = ko.renderTemplate(template, innerBindingContext, options, element);\n }\n\n // It only makes sense to have a single template computed per element (otherwise which one should have its output displayed?)\n disposeOldComputedAndStoreNewOne(element, templateComputed);\n }\n };\n\n // Anonymous templates can't be rewritten. Give a nice error message if you try to do it.\n ko.expressionRewriting.bindingRewriteValidators['template'] = function(bindingValue) {\n var parsedBindingValue = ko.expressionRewriting.parseObjectLiteral(bindingValue);\n\n if ((parsedBindingValue.length == 1) && parsedBindingValue[0]['unknown'])\n return null; // It looks like a string literal, not an object literal, so treat it as a named template (which is allowed for rewriting)\n\n if (ko.expressionRewriting.keyValueArrayContainsKey(parsedBindingValue, \"name\"))\n return null; // Named templates can be rewritten, so return \"no error\"\n return \"This template engine does not support anonymous templates nested within its templates\";\n };\n\n ko.virtualElements.allowedBindings['template'] = true;\n })();\n\n ko.exportSymbol('setTemplateEngine', ko.setTemplateEngine);\n ko.exportSymbol('renderTemplate', ko.renderTemplate);\n// Go through the items that have been added and deleted and try to find matches between them.\n ko.utils.findMovesInArrayComparison = function (left, right, limitFailedCompares) {\n if (left.length && right.length) {\n var failedCompares, l, r, leftItem, rightItem;\n for (failedCompares = l = 0; (!limitFailedCompares || failedCompares < limitFailedCompares) && (leftItem = left[l]); ++l) {\n for (r = 0; rightItem = right[r]; ++r) {\n if (leftItem['value'] === rightItem['value']) {\n leftItem['moved'] = rightItem['index'];\n rightItem['moved'] = leftItem['index'];\n right.splice(r, 1); // This item is marked as moved; so remove it from right list\n failedCompares = r = 0; // Reset failed compares count because we're checking for consecutive failures\n break;\n }\n }\n failedCompares += r;\n }\n }\n };\n\n ko.utils.compareArrays = (function () {\n var statusNotInOld = 'added', statusNotInNew = 'deleted';\n\n // Simple calculation based on Levenshtein distance.\n function compareArrays(oldArray, newArray, options) {\n // For backward compatibility, if the third arg is actually a bool, interpret\n // it as the old parameter 'dontLimitMoves'. Newer code should use { dontLimitMoves: true }.\n options = (typeof options === 'boolean') ? { 'dontLimitMoves': options } : (options || {});\n oldArray = oldArray || [];\n newArray = newArray || [];\n\n if (oldArray.length < newArray.length)\n return compareSmallArrayToBigArray(oldArray, newArray, statusNotInOld, statusNotInNew, options);\n else\n return compareSmallArrayToBigArray(newArray, oldArray, statusNotInNew, statusNotInOld, options);\n }\n\n function compareSmallArrayToBigArray(smlArray, bigArray, statusNotInSml, statusNotInBig, options) {\n var myMin = Math.min,\n myMax = Math.max,\n editDistanceMatrix = [],\n smlIndex, smlIndexMax = smlArray.length,\n bigIndex, bigIndexMax = bigArray.length,\n compareRange = (bigIndexMax - smlIndexMax) || 1,\n maxDistance = smlIndexMax + bigIndexMax + 1,\n thisRow, lastRow,\n bigIndexMaxForRow, bigIndexMinForRow;\n\n for (smlIndex = 0; smlIndex <= smlIndexMax; smlIndex++) {\n lastRow = thisRow;\n editDistanceMatrix.push(thisRow = []);\n bigIndexMaxForRow = myMin(bigIndexMax, smlIndex + compareRange);\n bigIndexMinForRow = myMax(0, smlIndex - 1);\n for (bigIndex = bigIndexMinForRow; bigIndex <= bigIndexMaxForRow; bigIndex++) {\n if (!bigIndex)\n thisRow[bigIndex] = smlIndex + 1;\n else if (!smlIndex) // Top row - transform empty array into new array via additions\n thisRow[bigIndex] = bigIndex + 1;\n else if (smlArray[smlIndex - 1] === bigArray[bigIndex - 1])\n thisRow[bigIndex] = lastRow[bigIndex - 1]; // copy value (no edit)\n else {\n var northDistance = lastRow[bigIndex] || maxDistance; // not in big (deletion)\n var westDistance = thisRow[bigIndex - 1] || maxDistance; // not in small (addition)\n thisRow[bigIndex] = myMin(northDistance, westDistance) + 1;\n }\n }\n }\n\n var editScript = [], meMinusOne, notInSml = [], notInBig = [];\n for (smlIndex = smlIndexMax, bigIndex = bigIndexMax; smlIndex || bigIndex;) {\n meMinusOne = editDistanceMatrix[smlIndex][bigIndex] - 1;\n if (bigIndex && meMinusOne === editDistanceMatrix[smlIndex][bigIndex-1]) {\n notInSml.push(editScript[editScript.length] = { // added\n 'status': statusNotInSml,\n 'value': bigArray[--bigIndex],\n 'index': bigIndex });\n } else if (smlIndex && meMinusOne === editDistanceMatrix[smlIndex - 1][bigIndex]) {\n notInBig.push(editScript[editScript.length] = { // deleted\n 'status': statusNotInBig,\n 'value': smlArray[--smlIndex],\n 'index': smlIndex });\n } else {\n --bigIndex;\n --smlIndex;\n if (!options['sparse']) {\n editScript.push({\n 'status': \"retained\",\n 'value': bigArray[bigIndex] });\n }\n }\n }\n\n // Set a limit on the number of consecutive non-matching comparisons; having it a multiple of\n // smlIndexMax keeps the time complexity of this algorithm linear.\n ko.utils.findMovesInArrayComparison(notInBig, notInSml, !options['dontLimitMoves'] && smlIndexMax * 10);\n\n return editScript.reverse();\n }\n\n return compareArrays;\n })();\n\n ko.exportSymbol('utils.compareArrays', ko.utils.compareArrays);\n (function () {\n // Objective:\n // * Given an input array, a container DOM node, and a function from array elements to arrays of DOM nodes,\n // map the array elements to arrays of DOM nodes, concatenate together all these arrays, and use them to populate the container DOM node\n // * Next time we're given the same combination of things (with the array possibly having mutated), update the container DOM node\n // so that its children is again the concatenation of the mappings of the array elements, but don't re-map any array elements that we\n // previously mapped - retain those nodes, and just insert/delete other ones\n\n // \"callbackAfterAddingNodes\" will be invoked after any \"mapping\"-generated nodes are inserted into the container node\n // You can use this, for example, to activate bindings on those nodes.\n\n function mapNodeAndRefreshWhenChanged(containerNode, mapping, valueToMap, callbackAfterAddingNodes, index) {\n // Map this array value inside a dependentObservable so we re-map when any dependency changes\n var mappedNodes = [];\n var dependentObservable = ko.dependentObservable(function() {\n var newMappedNodes = mapping(valueToMap, index, ko.utils.fixUpContinuousNodeArray(mappedNodes, containerNode)) || [];\n\n // On subsequent evaluations, just replace the previously-inserted DOM nodes\n if (mappedNodes.length > 0) {\n ko.utils.replaceDomNodes(mappedNodes, newMappedNodes);\n if (callbackAfterAddingNodes)\n ko.dependencyDetection.ignore(callbackAfterAddingNodes, null, [valueToMap, newMappedNodes, index]);\n }\n\n // Replace the contents of the mappedNodes array, thereby updating the record\n // of which nodes would be deleted if valueToMap was itself later removed\n mappedNodes.length = 0;\n ko.utils.arrayPushAll(mappedNodes, newMappedNodes);\n }, null, { disposeWhenNodeIsRemoved: containerNode, disposeWhen: function() { return !ko.utils.anyDomNodeIsAttachedToDocument(mappedNodes); } });\n return { mappedNodes : mappedNodes, dependentObservable : (dependentObservable.isActive() ? dependentObservable : undefined) };\n }\n\n var lastMappingResultDomDataKey = ko.utils.domData.nextKey(),\n deletedItemDummyValue = ko.utils.domData.nextKey();\n\n ko.utils.setDomNodeChildrenFromArrayMapping = function (domNode, array, mapping, options, callbackAfterAddingNodes, editScript) {\n array = array || [];\n if (typeof array.length == \"undefined\") // Coerce single value into array\n array = [array];\n\n options = options || {};\n var lastMappingResult = ko.utils.domData.get(domNode, lastMappingResultDomDataKey);\n var isFirstExecution = !lastMappingResult;\n\n // Build the new mapping result\n var newMappingResult = [];\n var lastMappingResultIndex = 0;\n var currentArrayIndex = 0;\n\n var nodesToDelete = [];\n var itemsToMoveFirstIndexes = [];\n var itemsForBeforeRemoveCallbacks = [];\n var itemsForMoveCallbacks = [];\n var itemsForAfterAddCallbacks = [];\n var mapData;\n var countWaitingForRemove = 0;\n\n function itemAdded(value) {\n mapData = { arrayEntry: value, indexObservable: ko.observable(currentArrayIndex++) };\n newMappingResult.push(mapData);\n if (!isFirstExecution) {\n itemsForAfterAddCallbacks.push(mapData);\n }\n }\n\n function itemMovedOrRetained(oldPosition) {\n mapData = lastMappingResult[oldPosition];\n if (currentArrayIndex !== mapData.indexObservable.peek())\n itemsForMoveCallbacks.push(mapData);\n // Since updating the index might change the nodes, do so before calling fixUpContinuousNodeArray\n mapData.indexObservable(currentArrayIndex++);\n ko.utils.fixUpContinuousNodeArray(mapData.mappedNodes, domNode);\n newMappingResult.push(mapData);\n }\n\n function callCallback(callback, items) {\n if (callback) {\n for (var i = 0, n = items.length; i < n; i++) {\n ko.utils.arrayForEach(items[i].mappedNodes, function(node) {\n callback(node, i, items[i].arrayEntry);\n });\n }\n }\n }\n\n if (isFirstExecution) {\n ko.utils.arrayForEach(array, itemAdded);\n } else {\n if (!editScript || (lastMappingResult && lastMappingResult['_countWaitingForRemove'])) {\n // Compare the provided array against the previous one\n var lastArray = ko.utils.arrayMap(lastMappingResult, function (x) { return x.arrayEntry; }),\n compareOptions = {\n 'dontLimitMoves': options['dontLimitMoves'],\n 'sparse': true\n };\n editScript = ko.utils.compareArrays(lastArray, array, compareOptions);\n }\n\n for (var i = 0, editScriptItem, movedIndex, itemIndex; editScriptItem = editScript[i]; i++) {\n movedIndex = editScriptItem['moved'];\n itemIndex = editScriptItem['index'];\n switch (editScriptItem['status']) {\n case \"deleted\":\n while (lastMappingResultIndex < itemIndex) {\n itemMovedOrRetained(lastMappingResultIndex++);\n }\n if (movedIndex === undefined) {\n mapData = lastMappingResult[lastMappingResultIndex];\n\n // Stop tracking changes to the mapping for these nodes\n if (mapData.dependentObservable) {\n mapData.dependentObservable.dispose();\n mapData.dependentObservable = undefined;\n }\n\n // Queue these nodes for later removal\n if (ko.utils.fixUpContinuousNodeArray(mapData.mappedNodes, domNode).length) {\n if (options['beforeRemove']) {\n newMappingResult.push(mapData);\n countWaitingForRemove++;\n if (mapData.arrayEntry === deletedItemDummyValue) {\n mapData = null;\n } else {\n itemsForBeforeRemoveCallbacks.push(mapData);\n }\n }\n if (mapData) {\n nodesToDelete.push.apply(nodesToDelete, mapData.mappedNodes);\n }\n }\n }\n lastMappingResultIndex++;\n break;\n\n case \"added\":\n while (currentArrayIndex < itemIndex) {\n itemMovedOrRetained(lastMappingResultIndex++);\n }\n if (movedIndex !== undefined) {\n itemsToMoveFirstIndexes.push(newMappingResult.length);\n itemMovedOrRetained(movedIndex);\n } else {\n itemAdded(editScriptItem['value']);\n }\n break;\n }\n }\n\n while (currentArrayIndex < array.length) {\n itemMovedOrRetained(lastMappingResultIndex++);\n }\n\n // Record that the current view may still contain deleted items\n // because it means we won't be able to use a provided editScript.\n newMappingResult['_countWaitingForRemove'] = countWaitingForRemove;\n }\n\n // Store a copy of the array items we just considered so we can difference it next time\n ko.utils.domData.set(domNode, lastMappingResultDomDataKey, newMappingResult);\n\n // Call beforeMove first before any changes have been made to the DOM\n callCallback(options['beforeMove'], itemsForMoveCallbacks);\n\n // Next remove nodes for deleted items (or just clean if there's a beforeRemove callback)\n ko.utils.arrayForEach(nodesToDelete, options['beforeRemove'] ? ko.cleanNode : ko.removeNode);\n\n var i, j, lastNode, nodeToInsert, mappedNodes, activeElement;\n\n // Since most browsers remove the focus from an element when it's moved to another location,\n // save the focused element and try to restore it later.\n try {\n activeElement = domNode.ownerDocument.activeElement;\n } catch(e) {\n // IE9 throws if you access activeElement during page load (see issue #703)\n }\n\n // Try to reduce overall moved nodes by first moving the ones that were marked as moved by the edit script\n if (itemsToMoveFirstIndexes.length) {\n while ((i = itemsToMoveFirstIndexes.shift()) != undefined) {\n mapData = newMappingResult[i];\n for (lastNode = undefined; i; ) {\n if ((mappedNodes = newMappingResult[--i].mappedNodes) && mappedNodes.length) {\n lastNode = mappedNodes[mappedNodes.length-1];\n break;\n }\n }\n for (j = 0; nodeToInsert = mapData.mappedNodes[j]; lastNode = nodeToInsert, j++) {\n ko.virtualElements.insertAfter(domNode, nodeToInsert, lastNode);\n }\n }\n }\n\n // Next add/reorder the remaining items (will include deleted items if there's a beforeRemove callback)\n for (i = 0; mapData = newMappingResult[i]; i++) {\n // Get nodes for newly added items\n if (!mapData.mappedNodes)\n ko.utils.extend(mapData, mapNodeAndRefreshWhenChanged(domNode, mapping, mapData.arrayEntry, callbackAfterAddingNodes, mapData.indexObservable));\n\n // Put nodes in the right place if they aren't there already\n for (j = 0; nodeToInsert = mapData.mappedNodes[j]; lastNode = nodeToInsert, j++) {\n ko.virtualElements.insertAfter(domNode, nodeToInsert, lastNode);\n }\n\n // Run the callbacks for newly added nodes (for example, to apply bindings, etc.)\n if (!mapData.initialized && callbackAfterAddingNodes) {\n callbackAfterAddingNodes(mapData.arrayEntry, mapData.mappedNodes, mapData.indexObservable);\n mapData.initialized = true;\n lastNode = mapData.mappedNodes[mapData.mappedNodes.length - 1]; // get the last node again since it may have been changed by a preprocessor\n }\n }\n\n // Restore the focused element if it had lost focus\n if (activeElement && domNode.ownerDocument.activeElement != activeElement) {\n activeElement.focus();\n }\n\n // If there's a beforeRemove callback, call it after reordering.\n // Note that we assume that the beforeRemove callback will usually be used to remove the nodes using\n // some sort of animation, which is why we first reorder the nodes that will be removed. If the\n // callback instead removes the nodes right away, it would be more efficient to skip reordering them.\n // Perhaps we'll make that change in the future if this scenario becomes more common.\n callCallback(options['beforeRemove'], itemsForBeforeRemoveCallbacks);\n\n // Replace the stored values of deleted items with a dummy value. This provides two benefits: it marks this item\n // as already \"removed\" so we won't call beforeRemove for it again, and it ensures that the item won't match up\n // with an actual item in the array and appear as \"retained\" or \"moved\".\n for (i = 0; i < itemsForBeforeRemoveCallbacks.length; ++i) {\n itemsForBeforeRemoveCallbacks[i].arrayEntry = deletedItemDummyValue;\n }\n\n // Finally call afterMove and afterAdd callbacks\n callCallback(options['afterMove'], itemsForMoveCallbacks);\n callCallback(options['afterAdd'], itemsForAfterAddCallbacks);\n }\n })();\n\n ko.exportSymbol('utils.setDomNodeChildrenFromArrayMapping', ko.utils.setDomNodeChildrenFromArrayMapping);\n ko.nativeTemplateEngine = function () {\n this['allowTemplateRewriting'] = false;\n }\n\n ko.nativeTemplateEngine.prototype = new ko.templateEngine();\n ko.nativeTemplateEngine.prototype.constructor = ko.nativeTemplateEngine;\n ko.nativeTemplateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options, templateDocument) {\n var useNodesIfAvailable = !(ko.utils.ieVersion < 9), // IE<9 cloneNode doesn't work properly\n templateNodesFunc = useNodesIfAvailable ? templateSource['nodes'] : null,\n templateNodes = templateNodesFunc ? templateSource['nodes']() : null;\n\n if (templateNodes) {\n return ko.utils.makeArray(templateNodes.cloneNode(true).childNodes);\n } else {\n var templateText = templateSource['text']();\n return ko.utils.parseHtmlFragment(templateText, templateDocument);\n }\n };\n\n ko.nativeTemplateEngine.instance = new ko.nativeTemplateEngine();\n ko.setTemplateEngine(ko.nativeTemplateEngine.instance);\n\n ko.exportSymbol('nativeTemplateEngine', ko.nativeTemplateEngine);\n (function() {\n ko.jqueryTmplTemplateEngine = function () {\n // Detect which version of jquery-tmpl you're using. Unfortunately jquery-tmpl\n // doesn't expose a version number, so we have to infer it.\n // Note that as of Knockout 1.3, we only support jQuery.tmpl 1.0.0pre and later,\n // which KO internally refers to as version \"2\", so older versions are no longer detected.\n var jQueryTmplVersion = this.jQueryTmplVersion = (function() {\n if (!jQueryInstance || !(jQueryInstance['tmpl']))\n return 0;\n // Since it exposes no official version number, we use our own numbering system. To be updated as jquery-tmpl evolves.\n try {\n if (jQueryInstance['tmpl']['tag']['tmpl']['open'].toString().indexOf('__') >= 0) {\n // Since 1.0.0pre, custom tags should append markup to an array called \"__\"\n return 2; // Final version of jquery.tmpl\n }\n } catch(ex) { /* Apparently not the version we were looking for */ }\n\n return 1; // Any older version that we don't support\n })();\n\n function ensureHasReferencedJQueryTemplates() {\n if (jQueryTmplVersion < 2)\n throw new Error(\"Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.\");\n }\n\n function executeTemplate(compiledTemplate, data, jQueryTemplateOptions) {\n return jQueryInstance['tmpl'](compiledTemplate, data, jQueryTemplateOptions);\n }\n\n this['renderTemplateSource'] = function(templateSource, bindingContext, options, templateDocument) {\n templateDocument = templateDocument || document;\n options = options || {};\n ensureHasReferencedJQueryTemplates();\n\n // Ensure we have stored a precompiled version of this template (don't want to reparse on every render)\n var precompiled = templateSource['data']('precompiled');\n if (!precompiled) {\n var templateText = templateSource['text']() || \"\";\n // Wrap in \"with($whatever.koBindingContext) { ... }\"\n templateText = \"{{ko_with $item.koBindingContext}}\" + templateText + \"{{/ko_with}}\";\n\n precompiled = jQueryInstance['template'](null, templateText);\n templateSource['data']('precompiled', precompiled);\n }\n\n var data = [bindingContext['$data']]; // Prewrap the data in an array to stop jquery.tmpl from trying to unwrap any arrays\n var jQueryTemplateOptions = jQueryInstance['extend']({ 'koBindingContext': bindingContext }, options['templateOptions']);\n\n var resultNodes = executeTemplate(precompiled, data, jQueryTemplateOptions);\n resultNodes['appendTo'](templateDocument.createElement(\"div\")); // Using \"appendTo\" forces jQuery/jQuery.tmpl to perform necessary cleanup work\n\n jQueryInstance['fragments'] = {}; // Clear jQuery's fragment cache to avoid a memory leak after a large number of template renders\n return resultNodes;\n };\n\n this['createJavaScriptEvaluatorBlock'] = function(script) {\n return \"{{ko_code ((function() { return \" + script + \" })()) }}\";\n };\n\n this['addTemplate'] = function(templateName, templateMarkup) {\n document.write(\"<script type='text/html' id='\" + templateName + \"'>\" + templateMarkup + \"<\" + \"/script>\");\n };\n\n if (jQueryTmplVersion > 0) {\n jQueryInstance['tmpl']['tag']['ko_code'] = {\n open: \"__.push($1 || '');\"\n };\n jQueryInstance['tmpl']['tag']['ko_with'] = {\n open: \"with($1) {\",\n close: \"} \"\n };\n }\n };\n\n ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine();\n ko.jqueryTmplTemplateEngine.prototype.constructor = ko.jqueryTmplTemplateEngine;\n\n // Use this one by default *only if jquery.tmpl is referenced*\n var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine();\n if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0)\n ko.setTemplateEngine(jqueryTmplTemplateEngineInstance);\n\n ko.exportSymbol('jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine);\n })();\n }));\n }());\n})();\n","WebShopApps_MatrixRate/js/view/shipping-rates-validation.js":"/**\n * Copyright \u00a9 2015 Magento. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*browser:true*/\n/*global define*/\ndefine(\n [\n 'uiComponent',\n 'Magento_Checkout/js/model/shipping-rates-validator',\n 'Magento_Checkout/js/model/shipping-rates-validation-rules',\n '../model/shipping-rates-validator',\n '../model/shipping-rates-validation-rules'\n ],\n function (\n Component,\n defaultShippingRatesValidator,\n defaultShippingRatesValidationRules,\n matrixrateShippingRatesValidator,\n matrixrateShippingRatesValidationRules\n ) {\n \"use strict\";\n defaultShippingRatesValidator.registerValidator('matrixrate', matrixrateShippingRatesValidator);\n defaultShippingRatesValidationRules.registerRules('matrixrate', matrixrateShippingRatesValidationRules);\n return Component;\n }\n);\n","WebShopApps_MatrixRate/js/model/shipping-rates-validator.js":"define(\n [\n 'jquery',\n 'mageUtils',\n './shipping-rates-validation-rules',\n 'mage/translate'\n ],\n function ($, utils, validationRules, $t) {\n \"use strict\";\n return {\n validationErrors: [],\n validate: function (address) {\n var self = this;\n this.validationErrors = [];\n $.each(validationRules.getRules(), function (field, rule) {\n if (rule.required && utils.isEmpty(address[field])) {\n var message = $t('Field ') + field + $t(' is required.');\n self.validationErrors.push(message);\n }\n });\n return !Boolean(this.validationErrors.length);\n }\n };\n }\n);","WebShopApps_MatrixRate/js/model/shipping-rates-validation-rules.js":"/**\n * Copyright \u00a9 2015 Magento. All rights reserved.\n * See COPYING.txt for license details.\n */\n/*global define*/\ndefine(\n [],\n function () {\n \"use strict\";\n return {\n getRules: function () {\n return {\n 'postcode': {\n 'required': true\n },\n 'country_id': {\n 'required': true\n },\n 'region_id' : {\n 'required': false\n },\n 'city' : {\n 'required': false\n }\n };\n }\n };\n }\n);\n","Magento_Paypal/js/paypal-checkout.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'Magento_Ui/js/modal/confirm',\n 'Magento_Customer/js/customer-data',\n 'jquery-ui-modules/widget',\n 'mage/mage'\n], function ($, confirm, customerData) {\n 'use strict';\n\n $.widget('mage.paypalCheckout', {\n options: {\n originalForm:\n 'form:not(#product_addtocart_form_from_popup):has(input[name=\"product\"][value=%1])',\n productId: 'input[type=\"hidden\"][name=\"product\"]',\n ppCheckoutSelector: '[data-role=pp-checkout-url]',\n ppCheckoutInput: '<input type=\"hidden\" data-role=\"pp-checkout-url\" name=\"return_url\" value=\"\"/>'\n },\n\n /**\n * Initialize store credit events\n * @private\n */\n _create: function () {\n this.element.on('click', '[data-action=\"checkout-form-submit\"]', $.proxy(function (e) {\n var $target = $(e.target),\n returnUrl = $target.data('checkout-url'),\n productId = $target.closest('form').find(this.options.productId).val(),\n originalForm = this.options.originalForm.replace('%1', productId),\n self = this,\n billingAgreement = customerData.get('paypal-billing-agreement');\n\n e.preventDefault();\n\n if (billingAgreement().askToCreate) {\n confirm({\n content: billingAgreement().confirmMessage,\n actions: {\n\n /**\n * Confirmation handler\n *\n */\n confirm: function () {\n returnUrl = billingAgreement().confirmUrl;\n self._redirect(returnUrl, originalForm);\n },\n\n /**\n * Cancel confirmation handler\n *\n */\n cancel: function (event) {\n if (event && !$(event.target).hasClass('action-close')) {\n self._redirect(returnUrl);\n }\n }\n }\n });\n } else {\n this._redirect(returnUrl, originalForm);\n }\n }, this));\n },\n\n /**\n * Redirect to certain url, with optional form\n * @param {String} returnUrl\n * @param {HTMLElement} originalForm\n *\n */\n _redirect: function (returnUrl, originalForm) {\n var $form,\n ppCheckoutInput;\n\n if (this.options.isCatalogProduct) {\n // find the form from which the button was clicked\n $form = originalForm ? $(originalForm) : $($(this.options.shortcutContainerClass).closest('form'));\n\n ppCheckoutInput = $form.find(this.options.ppCheckoutSelector)[0];\n\n if (!ppCheckoutInput) {\n ppCheckoutInput = $(this.options.ppCheckoutInput);\n ppCheckoutInput.appendTo($form);\n }\n $(ppCheckoutInput).val(returnUrl);\n\n $form.trigger('submit');\n } else {\n $.mage.redirect(returnUrl);\n }\n }\n });\n\n return $.mage.paypalCheckout;\n});\n","Magento_Paypal/js/order-review.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'Magento_Ui/js/modal/alert',\n 'jquery-ui-modules/widget',\n 'mage/translate',\n 'mage/mage',\n 'mage/validation'\n], function ($, alert) {\n 'use strict';\n\n $.widget('mage.orderReview', {\n options: {\n orderReviewSubmitSelector: '#review-button',\n shippingSelector: '#shipping_method',\n shippingSubmitFormSelector: null,\n updateOrderSelector: '#update-order',\n billingAsShippingSelector: '#billing\\\\:as_shipping',\n updateContainerSelector: '#details-reload',\n waitLoadingContainer: '#review-please-wait',\n shippingMethodContainer: '#shipping-method-container',\n agreementSelector: 'div.checkout-agreements input',\n isAjax: false,\n shippingMethodUpdateUrl: null,\n updateOrderSubmitUrl: null,\n canEditShippingMethod: false\n },\n\n /**\n * Widget instance properties\n */\n triggerPropertyChange: true,\n isShippingSubmitForm: false,\n\n /** @inheritdoc */\n _create: function () {\n var isDisable;\n\n //change handler for ajaxEnabled\n if (this.options.isAjax) {\n this._submitOrder = this._ajaxSubmitOrder;\n }\n\n this.element.on('click', this.options.orderReviewSubmitSelector, $.proxy(this._submitOrder, this))\n .on('click', this.options.billingAsShippingSelector, $.proxy(this._shippingTobilling, this))\n .on('change',\n this.options.shippingSelector,\n $.proxy(this._submitUpdateOrder,\n this,\n this.options.updateOrderSubmitUrl,\n this.options.updateContainerSelector\n )\n ).find(this.options.updateOrderSelector).on('click', $.proxy(this._updateOrderHandler, this)).end();\n this._shippingTobilling();\n\n if ($(this.options.shippingSubmitFormSelector).length && this.options.canEditShippingMethod) {\n this.isShippingSubmitForm = true;\n $(this.options.shippingSubmitFormSelector)\n .on('change',\n this.options.shippingSelector,\n $.proxy(\n this._submitUpdateOrder,\n this,\n $(this.options.shippingSubmitFormSelector).prop('action'),\n this.options.updateContainerSelector\n )\n );\n this._updateOrderSubmit(!$(this.options.shippingSubmitFormSelector)\n .find(this.options.shippingSelector).val());\n } else {\n isDisable = this.isShippingSubmitForm && this.element.find(this.options.shippingSelector).val();\n this.element\n .on('input propertychange', ':input[name]',\n $.proxy(this._updateOrderSubmit, this, isDisable, this._onShippingChange)\n ).find('select').not(this.options.shippingSelector).on('change', this._propertyChange);\n this._updateOrderSubmit(isDisable);\n }\n },\n\n /**\n * show ajax loader\n */\n _ajaxBeforeSend: function () {\n this.element.find(this.options.waitLoadingContainer).show();\n },\n\n /**\n * hide ajax loader\n */\n _ajaxComplete: function () {\n this.element.find(this.options.waitLoadingContainer).hide();\n },\n\n /**\n * trigger propertychange for input type select\n */\n _propertyChange: function () {\n $(this).trigger('propertychange');\n },\n\n /**\n * trigger change for the update of shipping methods from server\n */\n _updateOrderHandler: function () {\n $(this.options.shippingSelector).trigger('change');\n },\n\n /**\n * Attempt to submit order\n */\n _submitOrder: function () {\n if (this._validateForm()) {\n this.element.find(this.options.updateOrderSelector).fadeTo(0, 0.5)\n .end().find(this.options.waitLoadingContainer).show()\n .end().trigger('submit');\n this._updateOrderSubmit(true);\n }\n },\n\n /**\n * Attempt to ajax submit order\n */\n _ajaxSubmitOrder: function () {\n if (this.element.find(this.options.waitLoadingContainer).is(':visible')) {\n return false;\n }\n $.ajax({\n url: this.element.prop('action'),\n type: 'post',\n context: this,\n data: {\n isAjax: 1\n },\n dataType: 'json',\n beforeSend: this._ajaxBeforeSend,\n complete: this._ajaxComplete,\n\n /** @inheritdoc */\n success: function (response) {\n var msg;\n\n if (typeof response === 'object' && !$.isEmptyObject(response)) {\n if (response['error_messages']) {\n this._ajaxComplete();\n msg = response['error_messages'];\n\n /* eslint-disable max-depth */\n if (msg) {\n if (Array.isArray(msg)) {\n msg = msg.join('\\n');\n }\n }\n\n /* eslint-enablemax-depth */\n alert({\n content: msg\n });\n\n return false;\n }\n\n if (response.redirect) {\n $.mage.redirect(response.redirect);\n\n return false;\n } else if (response.success) {\n $.mage.redirect(this.options.successUrl);\n\n return false;\n }\n this._ajaxComplete();\n alert({\n content: $.mage.__('Sorry, something went wrong.')\n });\n }\n },\n\n /** @inheritdoc */\n error: function () {\n alert({\n content: $.mage.__('Sorry, something went wrong. Please try again later.')\n });\n this._ajaxComplete();\n }\n });\n },\n\n /**\n * Validate Order form\n */\n _validateForm: function () {\n this.element.find(this.options.agreementSelector).off('change').on('change', $.proxy(function () {\n var isValid = this._validateForm();\n\n this._updateOrderSubmit(!isValid);\n }, this));\n\n if (this.element.data('mageValidation')) {\n return this.element.validation().valid();\n }\n\n return true;\n },\n\n /**\n * Check/Set whether order can be submitted\n * Also disables form submission element, if any\n * @param {*} shouldDisable - whether should prevent order submission explicitly\n * @param {Function} [fn] - function for shipping change handler\n * @param {*} [*] - if true the property change will be set to true\n */\n _updateOrderSubmit: function (shouldDisable, fn) {\n this._toggleButton(this.options.orderReviewSubmitSelector, shouldDisable);\n\n if (typeof fn === 'function') {\n fn.call(this);\n }\n },\n\n /**\n * Enable/Disable button\n * @param {jQuery} button - button selector to be toggled\n * @param {*} disable - boolean for toggling\n */\n _toggleButton: function (button, disable) {\n $(button).prop({\n 'disabled': disable\n }).toggleClass('no-checkout', disable).fadeTo(0, disable ? 0.5 : 1);\n },\n\n /**\n * Copy element value from shipping to billing address\n * @param {jQuery.Event} e - optional\n */\n _shippingTobilling: function (e) {\n var isChecked, opacity;\n\n if (this.options.shippingSubmitFormSelector) {\n return false;\n }\n isChecked = $(this.options.billingAsShippingSelector).is(':checked');\n opacity = isChecked ? 0.5 : 1;\n\n if (isChecked) {\n this.element.validation('clearError', ':input[name^=\"billing\"]');\n }\n $(':input[name^=\"shipping\"]', this.element).each($.proxy(function (key, value) {\n var fieldObj = $(value.id.replace('shipping:', '#billing\\\\:'));\n\n if (isChecked) {\n fieldObj = fieldObj.val($(value).val());\n }\n fieldObj.prop({\n 'readonly': isChecked,\n 'disabled': isChecked\n }).fadeTo(0, opacity);\n\n if (fieldObj.is('select')) {\n this.triggerPropertyChange = false;\n fieldObj.trigger('change');\n }\n }, this));\n\n if (isChecked || e) {\n this._updateOrderSubmit(true);\n }\n this.triggerPropertyChange = true;\n },\n\n /**\n * Dispatch an ajax request of Update Order submission\n * @param {*} url - url where to submit shipping method\n * @param {*} resultId - id of element to be updated\n */\n _submitUpdateOrder: function (url, resultId) {\n var isChecked, formData, callBackResponseHandler, shippingMethod;\n\n if (this.element.find(this.options.waitLoadingContainer).is(':visible')) {\n return false;\n }\n isChecked = $(this.options.billingAsShippingSelector).is(':checked');\n formData = null;\n callBackResponseHandler = null;\n let val = $(this.options.shippingSelector).val();\n\n shippingMethod = val.trim();\n this._shippingTobilling();\n\n if (url && resultId && shippingMethod) {\n this._updateOrderSubmit(true);\n this._toggleButton(this.options.updateOrderSelector, true);\n\n // form data and callBack updated based on the shipping Form element\n if (this.isShippingSubmitForm) {\n formData = $(this.options.shippingSubmitFormSelector).serialize() + '&isAjax=true';\n\n /**\n * @param {Object} response\n */\n callBackResponseHandler = function (response) {\n $(resultId).html(response);\n this._updateOrderSubmit(false);\n this._ajaxComplete();\n };\n } else {\n formData = this.element.serialize() + '&isAjax=true';\n\n /**\n * @param {Object} response\n */\n callBackResponseHandler = function (response) {\n $(resultId).html(response);\n this._ajaxShippingUpdate(shippingMethod);\n };\n }\n\n if (isChecked) {\n $(this.options.shippingSelect).prop('disabled', true);\n }\n $.ajax({\n url: url,\n type: 'post',\n context: this,\n beforeSend: this._ajaxBeforeSend,\n data: formData,\n success: callBackResponseHandler\n });\n }\n },\n\n /**\n * Update Shipping Methods Element from server\n * @param {*} shippingMethod\n */\n _ajaxShippingUpdate: function (shippingMethod) {\n $.ajax({\n url: this.options.shippingMethodUpdateUrl,\n data: {\n isAjax: true,\n 'shipping_method': shippingMethod\n },\n type: 'post',\n context: this,\n\n /** @inheritdoc */\n success: function (response) {\n $(this.options.shippingMethodContainer).parent().html(response);\n this._toggleButton(this.options.updateOrderSelector, false);\n this._updateOrderSubmit(false);\n },\n complete: this._ajaxComplete\n });\n },\n\n /**\n * Actions on change Shipping Address data\n */\n _onShippingChange: function () {\n let val = $(this.options.shippingSelector).val();\n\n if (this.triggerPropertyChange && val.trim()) {\n this.element.find(this.options.shippingSelector).hide().end()\n .find(this.options.shippingSelector + '_update').show();\n }\n }\n });\n\n return $.mage.orderReview;\n});\n","Magento_Paypal/js/action/set-payment-method.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'Magento_Checkout/js/model/quote',\n 'Magento_Checkout/js/action/set-payment-information'\n], function (quote, setPaymentInformation) {\n 'use strict';\n\n return function (messageContainer) {\n return setPaymentInformation(messageContainer, quote.paymentMethod());\n };\n});\n","Magento_Paypal/js/in-context/button.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'uiComponent',\n 'jquery',\n 'Magento_Paypal/js/in-context/express-checkout-wrapper',\n 'Magento_Customer/js/customer-data'\n], function (Component, $, Wrapper, customerData) {\n 'use strict';\n\n return Component.extend(Wrapper).extend({\n defaults: {\n declinePayment: false\n },\n\n /** @inheritdoc */\n initialize: function (config, element) {\n var cart = customerData.get('cart'),\n customer = customerData.get('customer');\n\n this._super();\n this.renderPayPalButtons(element);\n\n if (cart().isGuestCheckoutAllowed === undefined) {\n cart.subscribe(function (updatedCart) {\n this.declinePayment = !customer().firstname && !cart().isGuestCheckoutAllowed;\n\n return updatedCart;\n }.bind(this));\n }\n\n return this;\n },\n\n /** @inheritdoc */\n beforePayment: function (resolve, reject) {\n var promise = $.Deferred();\n\n if (this.declinePayment) {\n this.addError(this.signInMessage, 'warning');\n\n reject();\n } else {\n promise.resolve();\n }\n\n return promise;\n },\n\n /** @inheritdoc */\n prepareClientConfig: function () {\n this._super();\n\n return this.clientConfig;\n }\n });\n});\n","Magento_Paypal/js/in-context/express-checkout-wrapper.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'mage/translate',\n 'Magento_Customer/js/customer-data',\n 'Magento_Paypal/js/in-context/express-checkout-smart-buttons',\n 'Magento_Ui/js/modal/alert',\n 'mage/cookies'\n], function ($, $t, customerData, checkoutSmartButtons, alert) {\n 'use strict';\n\n return {\n defaults: {\n paymentActionError: $t('Something went wrong with your request. Please try again later.'),\n signInMessage: $t('To check out, please sign in with your email address.')\n },\n\n /**\n * Render PayPal buttons using checkout.js\n */\n renderPayPalButtons: function (element) {\n checkoutSmartButtons(this.prepareClientConfig(), element);\n },\n\n /**\n * Validate payment method\n *\n * @param {Object} actions\n */\n validate: function (actions) {\n this.actions = actions || this.actions;\n },\n\n /**\n * Execute logic on Paypal button click\n */\n onClick: function () {},\n\n /**\n * Before payment execute\n *\n * @param {Function} resolve\n * @param {Function} reject\n * @return {*}\n */\n beforePayment: function (resolve, reject) { //eslint-disable-line no-unused-vars\n return $.Deferred().resolve();\n },\n\n /**\n * After payment execute\n *\n * @param {Object} res\n * @param {Function} resolve\n * @param {Function} reject\n *\n * @return {*}\n */\n afterPayment: function (res, resolve, reject) {\n\n if (res.success) {\n return resolve(res.token);\n }\n\n return reject(new Error(res['error_message']));\n },\n\n /**\n * Catch payment\n *\n * @param {Error} err\n * @param {Function} resolve\n * @param {Function} reject\n */\n catchPayment: function (err, resolve, reject) {\n this.addAlert(this.paymentActionError);\n reject(err);\n },\n\n /**\n * Before onAuthorize execute\n *\n * @param {Function} resolve\n * @param {Function} reject\n * @param {Object} actions\n *\n * @return {jQuery.Deferred}\n */\n beforeOnAuthorize: function (resolve, reject, actions) { //eslint-disable-line no-unused-vars\n //display loading widget.\n $('body').trigger('processStart');\n\n return $.Deferred().resolve();\n },\n\n /**\n * After onAuthorize execute\n *\n * @param {Object} res\n * @param {Function} resolve\n * @param {Function} reject\n * @param {Object} actions\n *\n * @return {*}\n */\n afterOnAuthorize: function (res, resolve, reject, actions) {\n $('body').trigger('processStop');\n\n if (res.success) {\n resolve();\n\n return actions.redirect(res.redirectUrl);\n }\n\n return reject(new Error(res['error_message']));\n },\n\n /**\n * Catch payment\n *\n * @param {Error} err\n * @param {Function} resolve\n * @param {Function} reject\n */\n catchOnAuthorize: function (err, resolve, reject) {\n $('body').trigger('processStop');\n this.addAlert(this.paymentActionError);\n reject(err);\n },\n\n /**\n * Process cancel action\n *\n * @param {Object} data\n * @param {Object} actions\n */\n onCancel: function (data, actions) {\n $('body').trigger('processStop');\n actions.redirect(this.clientConfig.onCancelUrl);\n },\n\n /**\n * Process errors\n *\n * @param {Error} err\n */\n onError: function (err) { //eslint-disable-line no-unused-vars\n // Uncaught error isn't displayed in the console\n },\n\n /**\n * Adds error message\n *\n * @param {String} message\n * @param {String} [type]\n */\n addError: function (message, type) {\n type = type || 'error';\n customerData.set('messages', {\n messages: [{\n type: type,\n text: message\n }],\n 'data_id': Math.floor(Date.now() / 1000)\n });\n },\n\n /**\n * Add alert message\n *\n * @param {String} message\n */\n addAlert: function (message) {\n alert({\n content: message\n });\n },\n\n /**\n * @returns {String}\n */\n getButtonId: function () {\n return this.inContextId;\n },\n\n /**\n * Populate client config with all required data\n *\n * @return {Object}\n */\n prepareClientConfig: function () {\n this.clientConfig.rendererComponent = this;\n this.clientConfig.formKey = $.mage.cookies.get('form_key');\n\n return this.clientConfig;\n }\n };\n});\n","Magento_Paypal/js/in-context/express-checkout-smart-buttons.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/* eslint-disable max-nested-callbacks */\ndefine([\n 'underscore',\n 'jquery',\n 'Magento_Paypal/js/in-context/paypal-sdk',\n 'Magento_Customer/js/customer-data',\n 'domReady!'\n], function (_, $, paypalSdk, customerData) {\n 'use strict';\n\n /**\n * Triggers beforePayment action on PayPal buttons\n *\n * @param {Object} clientConfig\n * @returns {Object} jQuery promise\n */\n function performCreateOrder(clientConfig) {\n var params = {\n 'quote_id': clientConfig.quoteId,\n 'customer_id': clientConfig.customerId || '',\n 'form_key': clientConfig.formKey,\n button: clientConfig.button\n };\n\n return $.Deferred(function (deferred) {\n clientConfig.rendererComponent.beforePayment(deferred.resolve, deferred.reject).then(function () {\n $.post(clientConfig.getTokenUrl, params).done(function (res) {\n clientConfig.rendererComponent.afterPayment(res, deferred.resolve, deferred.reject);\n }).fail(function (jqXHR, textStatus, err) {\n clientConfig.rendererComponent.catchPayment(err, deferred.resolve, deferred.reject);\n });\n });\n }).promise();\n }\n\n /**\n * Triggers beforeOnAuthorize action on PayPal buttons\n * @param {Object} clientConfig\n * @param {Object} data\n * @param {Object} actions\n * @returns {Object} jQuery promise\n */\n function performOnApprove(clientConfig, data, actions) {\n var params = {\n paymentToken: data.orderID,\n payerId: data.payerID,\n paypalFundingSource: customerData.get('paypal-funding-source'),\n 'form_key': clientConfig.formKey\n };\n\n return $.Deferred(function (deferred) {\n clientConfig.rendererComponent.beforeOnAuthorize(deferred.resolve, deferred.reject, actions)\n .then(function () {\n $.post(clientConfig.onAuthorizeUrl, params).done(function (res) {\n clientConfig.rendererComponent\n .afterOnAuthorize(res, deferred.resolve, deferred.reject, actions);\n customerData.set('paypal-funding-source', '');\n }).fail(function (jqXHR, textStatus, err) {\n clientConfig.rendererComponent.catchOnAuthorize(err, deferred.resolve, deferred.reject);\n customerData.set('paypal-funding-source', '');\n });\n });\n }).promise();\n }\n\n return function (clientConfig, element) {\n paypalSdk(clientConfig.sdkUrl, clientConfig.dataAttributes).done(function (paypal) {\n paypal.Buttons({\n style: clientConfig.styles,\n\n /**\n * onInit is called when the button first renders\n * @param {Object} data\n * @param {Object} actions\n */\n onInit: function (data, actions) {\n clientConfig.rendererComponent.validate(actions);\n },\n\n /**\n * Triggers beforePayment action on PayPal buttons\n * @returns {Object} jQuery promise\n */\n createOrder: function () {\n return performCreateOrder(clientConfig);\n },\n\n /**\n * Triggers beforeOnAuthorize action on PayPal buttons\n * @param {Object} data\n * @param {Object} actions\n */\n onApprove: function (data, actions) {\n performOnApprove(clientConfig, data, actions);\n },\n\n /**\n * Execute logic on Paypal button click\n */\n onClick: function (data) {\n customerData.set('paypal-funding-source', data.fundingSource);\n clientConfig.rendererComponent.validate();\n clientConfig.rendererComponent.onClick();\n },\n\n /**\n * Process cancel action\n * @param {Object} data\n * @param {Object} actions\n */\n onCancel: function (data, actions) {\n clientConfig.rendererComponent.onCancel(data, actions);\n },\n\n /**\n * Process errors\n *\n * @param {Error} err\n */\n onError: function (err) {\n clientConfig.rendererComponent.onError(err);\n }\n }).render(element);\n });\n };\n});\n","Magento_Paypal/js/in-context/paypal-sdk.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery'\n], function ($) {\n 'use strict';\n\n var dfd = $.Deferred();\n\n /**\n * Loads the PayPal SDK object\n * @param {String} paypalUrl - the url of the PayPal SDK\n * @param {Array} dataAttributes - Array of the Attributes for PayPal SDK Script tag\n */\n return function loadPaypalScript(paypalUrl, dataAttributes) {\n //configuration for loaded PayPal script\n require.config({\n paths: {\n paypalSdk: paypalUrl\n },\n shim: {\n paypalSdk: {\n exports: 'paypal'\n }\n },\n attributes: {\n 'paypalSdk': dataAttributes\n },\n\n /**\n * Add attributes under Paypal SDK Script tag\n */\n onNodeCreated: function (node, config, name) {\n if (config.attributes && config.attributes[name]) {\n $.each(dataAttributes, function (index, elem) {\n node.setAttribute(index, elem);\n });\n }\n }\n });\n\n if (dfd.state() !== 'resolved') {\n require(['paypalSdk'], function (paypalObject) {\n dfd.resolve(paypalObject);\n });\n }\n\n return dfd.promise();\n };\n});\n","Magento_Paypal/js/in-context/product-express-checkout.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'underscore',\n 'jquery',\n 'uiComponent',\n 'Magento_Paypal/js/in-context/express-checkout-wrapper',\n 'Magento_Customer/js/customer-data'\n], function (_, $, Component, Wrapper, customerData) {\n 'use strict';\n\n return Component.extend(Wrapper).extend({\n defaults: {\n productFormSelector: '#product_addtocart_form',\n declinePayment: false,\n formInvalid: false,\n productAddedToCart: false\n },\n\n /** @inheritdoc */\n initialize: function (config, element) {\n var cart = customerData.get('cart'),\n customer = customerData.get('customer'),\n isGuestCheckoutAllowed;\n\n this._super();\n\n isGuestCheckoutAllowed = cart().isGuestCheckoutAllowed;\n\n if (typeof isGuestCheckoutAllowed === 'undefined') {\n isGuestCheckoutAllowed = config.clientConfig.isGuestCheckoutAllowed;\n }\n\n if (config.clientConfig.isVisibleOnProductPage) {\n this.renderPayPalButtons(element);\n }\n\n this.declinePayment = !customer().firstname && !isGuestCheckoutAllowed;\n\n return this;\n },\n\n /** @inheritdoc */\n onClick: function () {\n var $form = $(this.productFormSelector);\n\n if (!this.declinePayment && !this.productAddedToCart) {\n $form.trigger('submit');\n this.formInvalid = !$form.validation('isValid');\n this.productAddedToCart = true;\n }\n },\n\n /** @inheritdoc */\n beforePayment: function (resolve, reject) {\n var promise = $.Deferred();\n\n if (this.declinePayment) {\n this.addError(this.signInMessage, 'warning');\n reject();\n } else if (this.formInvalid) {\n reject();\n } else {\n $(document).on('ajax:addToCart', function (e, data) {\n if (_.isEmpty(data.response)) {\n return promise.resolve();\n }\n\n return reject();\n });\n $(document).on('ajax:addToCart:error', reject);\n }\n\n return promise;\n },\n\n /**\n * After payment execute\n *\n * @param {Object} res\n * @param {Function} resolve\n * @param {Function} reject\n *\n * @return {*}\n */\n afterPayment: function (res, resolve, reject) {\n if (res.success) {\n return resolve(res.token);\n }\n\n this.addAlert(res['error_message']);\n\n return reject(new Error(res['error_message']));\n },\n\n /** @inheritdoc */\n prepareClientConfig: function () {\n this._super();\n this.clientConfig.quoteId = '';\n this.clientConfig.customerId = '';\n\n return this.clientConfig;\n },\n\n /** @inheritdoc */\n onError: function (err) {\n this.productAddedToCart = false;\n this._super(err);\n },\n\n /** @inheritdoc */\n onCancel: function (data, actions) {\n this.productAddedToCart = false;\n this._super(data, actions);\n },\n\n /** @inheritdoc */\n afterOnAuthorize: function (res, resolve, reject, actions) {\n this.productAddedToCart = false;\n\n return this._super(res, resolve, reject, actions);\n }\n });\n});\n","Magento_Paypal/js/in-context/billing-agreement.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'Magento_Ui/js/modal/confirm',\n 'Magento_Customer/js/customer-data'\n], function ($, confirm, customerData) {\n 'use strict';\n\n $.widget('mage.billingAgreement', {\n options: {\n invalidateOnLoad: false,\n cancelButtonSelector: '.block-billing-agreements-view button.cancel',\n cancelMessage: '',\n cancelUrl: ''\n },\n\n /**\n * Initialize billing agreements events\n * @private\n */\n _create: function () {\n var self = this;\n\n if (this.options.invalidateOnLoad) {\n this.invalidate();\n }\n $(this.options.cancelButtonSelector).on('click', function () {\n confirm({\n content: self.options.cancelMessage,\n actions: {\n /**\n * 'Confirm' action handler.\n */\n confirm: function () {\n self.invalidate();\n window.location.href = self.options.cancelUrl;\n }\n }\n });\n\n return false;\n });\n },\n\n /**\n * clear paypal billing agreement customer data\n * @returns void\n */\n invalidate: function () {\n customerData.invalidate(['paypal-billing-agreement']);\n }\n });\n\n return $.mage.billingAgreement;\n});\n","Magento_Paypal/js/view/paylater.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'ko',\n 'uiElement',\n 'uiLayout',\n 'Magento_Paypal/js/in-context/paypal-sdk',\n 'domReady!'\n], function (\n $,\n ko,\n Component,\n layout,\n paypalSdk\n) {\n 'use strict';\n\n return Component.extend({\n\n defaults: {\n template: 'Magento_Paypal/paylater',\n sdkUrl: '',\n attributes: {\n class: 'pay-later-message'\n },\n dataAttributes: {},\n refreshSelector: '',\n displayAmount: false,\n amountComponentConfig: {\n name: '${ $.name }.amountProvider',\n component: ''\n }\n },\n paypal: null,\n amount: null,\n\n /**\n * Initialize\n *\n * @returns {*}\n */\n initialize: function () {\n this._super()\n .observe(['amount']);\n\n if (this.displayAmount) {\n layout([this.amountComponentConfig]);\n }\n\n if (this.sdkUrl !== '') {\n this.loadPayPalSdk(this.sdkUrl, this.dataAttributes)\n .then(this._setPayPalObject.bind(this));\n }\n\n if (this.refreshSelector) {\n $(this.refreshSelector).on('click', this._refreshMessages.bind(this));\n }\n\n return this;\n },\n\n /**\n * Get attribute value from configuration\n *\n * @param {String} attributeName\n * @returns {*|null}\n */\n getAttribute: function (attributeName) {\n return typeof this.attributes[attributeName] !== 'undefined' ?\n this.attributes[attributeName] : null;\n },\n\n /**\n * Load PP SDK with preconfigured options\n *\n * @param {String} sdkUrl - the url of the PayPal SDK\n * @param {Array} dataAttributes - Array of the Attributes for PayPal SDK Script tag\n */\n loadPayPalSdk: function (sdkUrl, dataAttributes) {\n return paypalSdk(sdkUrl, dataAttributes);\n },\n\n /**\n * Set reference to paypal Sdk object\n *\n * @param {Object} paypal\n * @private\n */\n _setPayPalObject: function (paypal) {\n this.paypal = paypal;\n },\n\n /**\n * Render messages\n *\n * @private\n */\n _refreshMessages: function () {\n if (this.paypal) {\n this.paypal.Messages.render();\n }\n }\n });\n});\n","Magento_Paypal/js/view/payment/paypal-payments.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'uiComponent',\n 'Magento_Checkout/js/model/payment/renderer-list'\n], function (Component, rendererList) {\n 'use strict';\n\n var isContextCheckout = window.checkoutConfig.payment.paypalExpress.isContextCheckout,\n paypalExpress = 'Magento_Paypal/js/view/payment/method-renderer' +\n (isContextCheckout ? '/in-context/checkout-express' : '/paypal-express');\n\n rendererList.push(\n {\n type: 'paypal_express',\n component: paypalExpress,\n config: window.checkoutConfig.payment.paypalExpress.inContextConfig\n },\n {\n type: 'payflow_express',\n component: 'Magento_Paypal/js/view/payment/method-renderer/payflow-express'\n },\n {\n type: 'payflow_express_bml',\n component: 'Magento_Paypal/js/view/payment/method-renderer/payflow-express-bml'\n },\n {\n type: 'payflowpro',\n component: 'Magento_Paypal/js/view/payment/method-renderer/payflowpro-method'\n },\n {\n type: 'payflow_link',\n component: 'Magento_Paypal/js/view/payment/method-renderer/iframe-methods'\n },\n {\n type: 'payflow_advanced',\n component: 'Magento_Paypal/js/view/payment/method-renderer/iframe-methods'\n },\n {\n type: 'hosted_pro',\n component: 'Magento_Paypal/js/view/payment/method-renderer/iframe-methods'\n },\n {\n type: 'paypal_billing_agreement',\n component: 'Magento_Paypal/js/view/payment/method-renderer/paypal-billing-agreement'\n }\n );\n\n /**\n * Add view logic here if needed\n **/\n return Component.extend({});\n});\n","Magento_Paypal/js/view/payment/method-renderer/payflowpro-method.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'Magento_Payment/js/view/payment/iframe',\n 'Magento_Checkout/js/model/payment/additional-validators',\n 'Magento_Checkout/js/action/set-payment-information',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'Magento_Vault/js/view/payment/vault-enabler'\n], function ($, Component, additionalValidators, setPaymentInformationAction, fullScreenLoader, VaultEnabler) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Paypal/payment/payflowpro-form'\n },\n placeOrderHandler: null,\n validateHandler: null,\n\n /**\n * @returns {exports.initialize}\n */\n initialize: function () {\n this._super();\n this.vaultEnabler = new VaultEnabler();\n this.vaultEnabler.setPaymentCode(this.getVaultCode());\n\n return this;\n },\n\n /**\n * @param {Function} handler\n */\n setPlaceOrderHandler: function (handler) {\n this.placeOrderHandler = handler;\n },\n\n /**\n * @param {Function} handler\n */\n setValidateHandler: function (handler) {\n this.validateHandler = handler;\n },\n\n /**\n * @returns {Object}\n */\n context: function () {\n return this;\n },\n\n /**\n * @returns {Boolean}\n */\n isShowLegend: function () {\n return true;\n },\n\n /**\n * @returns {String}\n */\n getCode: function () {\n return 'payflowpro';\n },\n\n /**\n * @returns {Boolean}\n */\n isActive: function () {\n return true;\n },\n\n /**\n * @override\n */\n placeOrder: function () {\n var self = this;\n\n if (this.validateHandler() &&\n additionalValidators.validate() &&\n this.isPlaceOrderActionAllowed() === true\n ) {\n this.isPlaceOrderActionAllowed(false);\n fullScreenLoader.startLoader();\n $.when(\n setPaymentInformationAction(this.messageContainer, self.getData())\n ).done(\n function () {\n self.placeOrderHandler().fail(\n function () {\n fullScreenLoader.stopLoader();\n }\n );\n }\n ).always(\n function () {\n self.isPlaceOrderActionAllowed(true);\n fullScreenLoader.stopLoader();\n }\n );\n }\n },\n\n /**\n * @returns {Object}\n */\n getData: function () {\n var data = {\n 'method': this.getCode(),\n 'additional_data': {\n 'cc_type': this.creditCardType(),\n 'cc_exp_year': this.creditCardExpYear(),\n 'cc_exp_month': this.creditCardExpMonth(),\n 'cc_last_4': this.creditCardNumber().substr(-4)\n }\n };\n\n this.vaultEnabler.visitAdditionalData(data);\n\n return data;\n },\n\n /**\n * @returns {Bool}\n */\n isVaultEnabled: function () {\n return this.vaultEnabler.isVaultEnabled();\n },\n\n /**\n * @returns {String}\n */\n getVaultCode: function () {\n return 'payflowpro_cc_vault';\n }\n });\n});\n","Magento_Paypal/js/view/payment/method-renderer/paypal-express.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'Magento_Paypal/js/view/payment/method-renderer/paypal-express-abstract'\n], function (Component) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Paypal/payment/paypal-express'\n }\n });\n});\n","Magento_Paypal/js/view/payment/method-renderer/payflow-express.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'Magento_Paypal/js/view/payment/method-renderer/paypal-express-abstract'\n], function (Component) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Paypal/payment/payflow-express'\n }\n });\n});\n","Magento_Paypal/js/view/payment/method-renderer/payflow-express-bml.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'Magento_Paypal/js/view/payment/method-renderer/paypal-express-abstract'\n], function (Component) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Paypal/payment/payflow-express-bml'\n }\n });\n});\n","Magento_Paypal/js/view/payment/method-renderer/iframe-methods.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'Magento_Checkout/js/view/payment/default',\n 'Magento_Paypal/js/model/iframe',\n 'Magento_Checkout/js/model/full-screen-loader'\n], function (Component, iframe, fullScreenLoader) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Paypal/payment/iframe-methods',\n paymentReady: false\n },\n redirectAfterPlaceOrder: false,\n isInAction: iframe.isInAction,\n\n /**\n * @return {exports}\n */\n initObservable: function () {\n this._super()\n .observe('paymentReady');\n\n return this;\n },\n\n /**\n * @return {*}\n */\n isPaymentReady: function () {\n return this.paymentReady();\n },\n\n /**\n * Get action url for payment method iframe.\n * @returns {String}\n */\n getActionUrl: function () {\n return this.isInAction() ? window.checkoutConfig.payment.paypalIframe.actionUrl[this.getCode()] : '';\n },\n\n /**\n * Places order in pending payment status.\n */\n placePendingPaymentOrder: function () {\n if (this.placeOrder()) {\n fullScreenLoader.startLoader();\n this.isInAction(true);\n // capture all click events\n document.addEventListener('click', iframe.stopEventPropagation, true);\n }\n },\n\n /**\n * @return {*}\n */\n getPlaceOrderDeferredObject: function () {\n var self = this;\n\n return this._super().fail(function () {\n fullScreenLoader.stopLoader();\n self.isInAction(false);\n document.removeEventListener('click', iframe.stopEventPropagation, true);\n });\n },\n\n /**\n * After place order callback\n */\n afterPlaceOrder: function () {\n if (this.iframeIsLoaded) {\n document.getElementById(this.getCode() + '-iframe')\n .contentWindow.location.reload();\n this.paymentReady(false);\n }\n\n this.paymentReady(true);\n this.iframeIsLoaded = true;\n this.isPlaceOrderActionAllowed(true);\n fullScreenLoader.stopLoader();\n },\n\n /**\n * Hide loader when iframe is fully loaded.\n */\n iframeLoaded: function () {\n fullScreenLoader.stopLoader();\n }\n });\n});\n","Magento_Paypal/js/view/payment/method-renderer/paypal-billing-agreement.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'Magento_Checkout/js/view/payment/default',\n 'mage/validation'\n], function ($, Component) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Paypal/payment/paypal_billing_agreement-form',\n selectedBillingAgreement: ''\n },\n\n /** @inheritdoc */\n initObservable: function () {\n this._super()\n .observe('selectedBillingAgreement');\n\n return this;\n },\n\n /**\n * @return {*}\n */\n getTransportName: function () {\n return window.checkoutConfig.payment.paypalBillingAgreement.transportName;\n },\n\n /**\n * @return {*}\n */\n getBillingAgreements: function () {\n return window.checkoutConfig.payment.paypalBillingAgreement.agreements;\n },\n\n /**\n * @return {Object}\n */\n getData: function () {\n var additionalData = null;\n\n if (this.getTransportName()) {\n additionalData = {};\n additionalData[this.getTransportName()] = this.selectedBillingAgreement();\n }\n\n return {\n 'method': this.item.method,\n 'additional_data': additionalData\n };\n },\n\n /**\n * @return {jQuery}\n */\n validate: function () {\n var form = '#billing-agreement-form';\n\n return $(form).validation() && $(form).validation('isValid');\n }\n });\n});\n","Magento_Paypal/js/view/payment/method-renderer/paypal-express-abstract.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'Magento_Checkout/js/view/payment/default',\n 'Magento_Paypal/js/action/set-payment-method',\n 'Magento_Checkout/js/model/payment/additional-validators',\n 'Magento_Checkout/js/model/quote',\n 'Magento_Customer/js/customer-data'\n], function ($, Component, setPaymentMethodAction, additionalValidators, quote, customerData) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Paypal/payment/payflow-express-bml',\n billingAgreement: ''\n },\n\n /** Init observable variables */\n initObservable: function () {\n this._super()\n .observe('billingAgreement');\n\n return this;\n },\n\n /** Open window with */\n showAcceptanceWindow: function (data, event) {\n window.open(\n $(event.currentTarget).attr('href'),\n 'olcwhatispaypal',\n 'toolbar=no, location=no,' +\n ' directories=no, status=no,' +\n ' menubar=no, scrollbars=yes,' +\n ' resizable=yes, ,left=0,' +\n ' top=0, width=400, height=350'\n );\n\n return false;\n },\n\n /** Returns payment acceptance mark link path */\n getPaymentAcceptanceMarkHref: function () {\n return window.checkoutConfig.payment.paypalExpress.paymentAcceptanceMarkHref;\n },\n\n /** Returns payment acceptance mark image path */\n getPaymentAcceptanceMarkSrc: function () {\n return window.checkoutConfig.payment.paypalExpress.paymentAcceptanceMarkSrc;\n },\n\n /** Returns billing agreement data */\n getBillingAgreementCode: function () {\n return window.checkoutConfig.payment.paypalExpress.billingAgreementCode[this.item.method];\n },\n\n /** Returns payment information data */\n getData: function () {\n var parent = this._super(),\n additionalData = null;\n\n if (this.getBillingAgreementCode()) {\n additionalData = {};\n additionalData[this.getBillingAgreementCode()] = this.billingAgreement();\n }\n\n return $.extend(true, parent, {\n 'additional_data': additionalData\n });\n },\n\n /** Redirect to paypal */\n continueToPayPal: function () {\n if (additionalValidators.validate()) {\n //update payment method information if additional data was changed\n setPaymentMethodAction(this.messageContainer).done(\n function () {\n customerData.invalidate(['cart']);\n $.mage.redirect(\n window.checkoutConfig.payment.paypalExpress.redirectUrl[quote.paymentMethod().method]\n );\n }\n );\n\n return false;\n }\n }\n });\n});\n","Magento_Paypal/js/view/payment/method-renderer/payflowpro/vault.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'Magento_Vault/js/view/payment/method-renderer/vault'\n], function (VaultComponent) {\n 'use strict';\n\n return VaultComponent.extend({\n defaults: {\n template: 'Magento_Vault/payment/form'\n },\n\n /**\n * @returns {String}\n */\n getToken: function () {\n return this.publicHash;\n },\n\n /**\n * Get last 4 digits of card\n * @returns {String}\n */\n getMaskedCard: function () {\n return this.details['cc_last_4'];\n },\n\n /**\n * Get expiration date\n * @returns {String}\n */\n getExpirationDate: function () {\n return this.details['cc_exp_month'] + '/' + this.details['cc_exp_year'];\n },\n\n /**\n * Get card type\n * @returns {String}\n */\n getCardType: function () {\n return this.details['cc_type'];\n }\n });\n});\n","Magento_Paypal/js/view/payment/method-renderer/in-context/checkout-express.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'Magento_Paypal/js/view/payment/method-renderer/paypal-express-abstract',\n 'Magento_Paypal/js/in-context/express-checkout-wrapper',\n 'Magento_Paypal/js/action/set-payment-method',\n 'Magento_Checkout/js/model/payment/additional-validators',\n 'Magento_Ui/js/model/messageList',\n 'Magento_Ui/js/lib/view/utils/async'\n], function ($, Component, Wrapper, setPaymentMethod, additionalValidators, messageList) {\n 'use strict';\n\n return Component.extend(Wrapper).extend({\n defaults: {\n template: 'Magento_Paypal/payment/paypal-express-in-context',\n validationElements: 'input'\n },\n\n /**\n * Listens element on change and validate it.\n *\n * @param {HTMLElement} context\n */\n initListeners: function (context) {\n $.async(this.validationElements, context, function (element) {\n $(element).on('change', function () {\n this.validate();\n }.bind(this));\n }.bind(this));\n },\n\n /**\n * Validates Smart Buttons\n */\n validate: function () {\n this._super();\n\n if (this.actions) {\n additionalValidators.validate(true) ? this.actions.enable() : this.actions.disable();\n }\n },\n\n /** @inheritdoc */\n beforePayment: function (resolve, reject) {\n var promise = $.Deferred();\n\n setPaymentMethod(this.messageContainer).done(function () {\n return promise.resolve();\n }).fail(function (response) {\n var error;\n\n try {\n error = JSON.parse(response.responseText);\n } catch (exception) {\n error = this.paymentActionError;\n }\n\n this.addError(error);\n\n return reject(new Error(error));\n }.bind(this));\n\n return promise;\n },\n\n /**\n * Populate client config with all required data\n *\n * @return {Object}\n */\n prepareClientConfig: function () {\n this._super();\n this.clientConfig.quoteId = window.checkoutConfig.quoteData['entity_id'];\n this.clientConfig.customerId = window.customerData.id;\n this.clientConfig.button = 0;\n\n return this.clientConfig;\n },\n\n /**\n * Adding logic to be triggered onClick action for smart buttons component\n */\n onClick: function () {\n additionalValidators.validate();\n },\n\n /**\n * Adds error message\n *\n * @param {String} message\n */\n addError: function (message) {\n messageList.addErrorMessage({\n message: message\n });\n },\n\n /**\n * After payment execute\n *\n * @param {Object} res\n * @param {Function} resolve\n * @param {Function} reject\n *\n * @return {*}\n */\n afterPayment: function (res, resolve, reject) {\n if (res.success) {\n return resolve(res.token);\n }\n\n this.addError(res['error_message']);\n\n return reject(new Error(res['error_message']));\n },\n\n /**\n * After onAuthorize execute\n *\n * @param {Object} res\n * @param {Function} resolve\n * @param {Function} reject\n * @param {Object} actions\n *\n * @return {*}\n */\n afterOnAuthorize: function (res, resolve, reject, actions) {\n if (res.success) {\n resolve();\n\n return actions.redirect(res.redirectUrl);\n }\n\n this.addError(res['error_message']);\n\n return reject(new Error(res['error_message']));\n }\n });\n});\n","Magento_Paypal/js/view/amountProviders/checkout.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'ko',\n 'uiElement',\n 'uiRegistry',\n 'Magento_Checkout/js/model/quote',\n 'domReady!'\n], function (\n $,\n ko,\n Component,\n registry,\n quote\n) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n amount: null\n },\n\n /**\n * Initialize\n *\n * @returns {*}\n */\n initialize: function () {\n this._super();\n\n this.updateAmount();\n\n return this;\n },\n\n /**\n * Update amount\n */\n updateAmount: function () {\n var payLater = registry.get(this.parentName);\n\n quote.totals.subscribe(function (newValue) {\n payLater.amount(newValue['base_grand_total']);\n });\n }\n });\n});\n","Magento_Paypal/js/view/amountProviders/product-grouped.js":"/**\n* Copyright \u00a9 Magento, Inc. All rights reserved.\n* See COPYING.txt for license details.\n*/\n\ndefine([\n 'jquery',\n 'uiElement',\n 'uiRegistry',\n 'domReady!'\n], function (\n $,\n Component,\n registry\n) {\n 'use strict';\n\n return Component.extend({\n\n defaults: {\n tableWrapperSelector: '.table-wrapper.grouped',\n priceBoxSelector: '[data-role=\"priceBox\"]',\n qtyFieldSelector: '.input-text.qty',\n amount: null\n },\n priceInfo: {},\n\n /**\n * Initialize\n *\n * @returns {*}\n */\n initialize: function () {\n var self = this;\n\n this._super();\n\n $('tbody tr', this.tableWrapperSelector).each(function (index, element) {\n var priceBox = $(self.priceBoxSelector, element),\n qtyElement = $(self.qtyFieldSelector, element),\n productId = priceBox.data('productId'),\n priceElement = $('#product-price-' + productId);\n\n self.priceInfo[productId] = {\n qty: self._getQty(qtyElement),\n price: priceElement.data('priceAmount')\n };\n });\n\n $(this.qtyFieldSelector).on('change', this._onQtyChange.bind(this));\n\n this._updateAmount();\n\n return this;\n },\n\n /**\n * Get product quantity\n *\n * @param {jQuery.Element} element\n * @private\n */\n _getQty: function (element) {\n var qty = parseFloat(element.val());\n\n return !isNaN(qty) && qty ? qty : 0;\n },\n\n /**\n * Handle changed product quantity\n *\n * @param {jQuery.Event} event\n * @private\n */\n _onQtyChange: function (event) {\n var qtyElement = $(event.target),\n parent = qtyElement.parents('tr'),\n priceBox = $(this.priceBoxSelector, parent),\n productId = priceBox.data('productId');\n\n if (this.priceInfo[productId]) {\n this.priceInfo[productId].qty = this._getQty(qtyElement);\n }\n\n this._updateAmount();\n },\n\n /**\n * Calculate and update amount\n *\n * @private\n */\n _updateAmount: function () {\n var productId,\n amount = 0,\n payLater = registry.get(this.parentName);\n\n for (productId in this.priceInfo) {\n if (this.priceInfo.hasOwnProperty(productId)) {\n amount += this.priceInfo[productId].price * this.priceInfo[productId].qty;\n }\n }\n\n payLater.amount(amount);\n }\n });\n});\n","Magento_Paypal/js/view/amountProviders/product.js":"/**\n* Copyright \u00a9 Magento, Inc. All rights reserved.\n* See COPYING.txt for license details.\n*/\n\ndefine([\n 'jquery',\n 'uiElement',\n 'uiRegistry',\n 'priceBox',\n 'domReady!'\n], function (\n $,\n Component,\n registry\n) {\n 'use strict';\n\n return Component.extend({\n\n defaults: {\n priceBoxSelector: '.price-box',\n qtyFieldSelector: '#product_addtocart_form [name=\"qty\"]',\n amount: null\n },\n qty: 1,\n price: 0,\n priceType: '',\n\n /**\n * Initialize\n *\n * @returns {*}\n */\n initialize: function () {\n var priceBox;\n\n this._super();\n\n priceBox = $(this.priceBoxSelector);\n priceBox.on('priceUpdated', this._onPriceChange.bind(this));\n\n if (priceBox.priceBox('option') &&\n priceBox.priceBox('option').prices &&\n (priceBox.priceBox('option').prices.finalPrice || priceBox.priceBox('option').prices.basePrice)\n ) {\n this.priceType = priceBox.priceBox('option').prices.finalPrice ? 'finalPrice' : 'basePrice';\n this.price = priceBox.priceBox('option').prices[this.priceType].amount;\n }\n\n $(this.qtyFieldSelector).on('change', this._onQtyChange.bind(this));\n\n priceBox.trigger('updatePrice');\n\n return this;\n },\n\n /**\n * Handle changed product qty\n *\n * @param {jQuery.Event} event\n * @private\n */\n _onQtyChange: function (event) {\n var qty = parseFloat($(event.target).val());\n\n this.qty = !isNaN(qty) && qty ? qty : 1;\n this._updateAmount();\n },\n\n /**\n * Handle product price change\n *\n * @param {jQuery.Event} event\n * @param {Object} data\n * @private\n */\n _onPriceChange: function (event, data) {\n this.price = data[this.priceType].amount;\n this._updateAmount();\n },\n\n /**\n * Calculate and update amount\n *\n * @private\n */\n _updateAmount: function () {\n var amount = this.price * this.qty,\n payLater = registry.get(this.parentName);\n\n if (amount !== 0) {\n payLater.amount(amount);\n }\n }\n });\n});\n","Magento_Paypal/js/model/iframe-redirect.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'ko',\n 'Magento_Paypal/js/model/iframe',\n 'Magento_Ui/js/model/messageList'\n],\nfunction (ko, iframe, messageList) {\n 'use strict';\n\n return function (cartUrl, errorMessage, goToSuccessPage, successUrl) {\n if (this === window.self) {\n window.location = cartUrl;\n }\n\n if (!!errorMessage.message) { //eslint-disable-line no-extra-boolean-cast\n document.removeEventListener('click', iframe.stopEventPropagation, true);\n iframe.isInAction(false);\n messageList.addErrorMessage(errorMessage);\n } else if (!!goToSuccessPage) { //eslint-disable-line no-extra-boolean-cast\n window.location = successUrl;\n } else {\n window.location = cartUrl;\n }\n };\n});\n","Magento_Paypal/js/model/iframe.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['ko'], function (ko) {\n 'use strict';\n\n var isInAction = ko.observable(false);\n\n return {\n isInAction: isInAction,\n\n /**\n * @param {jQuery.Event} event\n */\n stopEventPropagation: function (event) {\n event.stopImmediatePropagation();\n event.preventDefault();\n }\n };\n});\n","Magento_Reports/js/recently-viewed.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'jquery',\n 'jquery-ui-modules/widget'\n], function ($) {\n 'use strict';\n\n $.widget('mage.recentlyViewedProducts', {\n options: {\n localStorageKey: 'recently-viewed-products',\n productBlock: '#widget_viewed_item',\n viewedContainer: 'ol'\n },\n\n /**\n * Bind events to the appropriate handlers.\n * @private\n */\n _create: function () {\n var productHtml = $(this.options.productBlock).html(),\n productSku = $(this.options.productBlock).data('sku'),\n products = JSON.parse(window.localStorage.getItem(this.options.localStorageKey)),\n productsLength, maximum, showed, index;\n\n if (products) {\n productsLength = products.sku.length;\n maximum = $(this.element).data('count');\n showed = 0;\n\n for (index = 0; index <= productsLength; index++) {\n if (products.sku[index] == productSku || showed >= maximum) { //eslint-disable-line\n products.sku.splice(index, 1);\n products.html.splice(index, 1);\n } else {\n $(this.element).find(this.options.viewedContainer).append(products.html[index]);\n $(this.element).show();\n showed++;\n }\n }\n $(this.element).find(this.options.productBlock).show();\n } else {\n products = {};\n products.sku = [];\n products.html = [];\n }\n products.sku.unshift(productSku);\n products.html.unshift(productHtml);\n window.localStorage.setItem(this.options.localStorageKey, JSON.stringify(products));\n }\n });\n\n return $.mage.recentlyViewedProducts;\n});\n","Magento_GoogleGtag/js/google-adwords.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/* jscs:disable */\n/* eslint-disable */\ndefine([\n 'jquery'\n], function ($) {\n 'use strict';\n\n /**\n * @param {Object} config\n */\n return function (config) {\n if (!window.gtag) {\n // Inject Global Site Tag\n var gtagScript = document.createElement('script');\n gtagScript.type = 'text/javascript';\n gtagScript.async = true;\n gtagScript.src = config.gtagSiteSrc;\n document.head.appendChild(gtagScript);\n\n window.dataLayer = window.dataLayer || [];\n\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('set', 'developer_id.dYjhlMD', true);\n if (config.conversionLabel) {\n gtag(\n 'event',\n 'conversion',\n {'send_to': config.conversionId + '/'\n + config.conversionLabel}\n );\n }\n } else {\n gtag('config', config.conversionId);\n }\n }\n});\n","Magento_GoogleGtag/js/google-analytics.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/* jscs:disable */\n/* eslint-disable */\ndefine([\n 'jquery',\n 'mage/cookies'\n], function ($) {\n 'use strict';\n\n /**\n * @param {Object} config\n */\n return function (config) {\n var allowServices = false,\n allowedCookies,\n allowedWebsites,\n measurementId;\n\n if (config.isCookieRestrictionModeEnabled) {\n allowedCookies = $.mage.cookies.get(config.cookieName);\n\n if (allowedCookies !== null) {\n allowedWebsites = JSON.parse(allowedCookies);\n\n if (allowedWebsites[config.currentWebsite] === 1) {\n allowServices = true;\n }\n }\n } else {\n allowServices = true;\n }\n\n if (allowServices) {\n /* Global site tag (gtag.js) - Google Analytics */\n measurementId = config.pageTrackingData.measurementId;\n if (window.gtag) {\n gtag('config', measurementId, { 'anonymize_ip': true });\n // Purchase Event\n if (config.ordersTrackingData.hasOwnProperty('currency')) {\n var purchaseObject = config.ordersTrackingData.orders[0];\n purchaseObject['items'] = config.ordersTrackingData.products;\n gtag('event', 'purchase', purchaseObject);\n }\n } else {\n (function(d,s,u){\n var gtagScript = d.createElement(s);\n gtagScript.type = 'text/javascript';\n gtagScript.async = true;\n gtagScript.src = u;\n d.head.insertBefore(gtagScript, d.head.children[0]);\n })(document, 'script', 'https://www.googletagmanager.com/gtag/js?id=' + measurementId);\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('set', 'developer_id.dYjhlMD', true);\n gtag('config', measurementId, { 'anonymize_ip': true });\n // Purchase Event\n if (config.ordersTrackingData.hasOwnProperty('currency')) {\n var purchaseObject = config.ordersTrackingData.orders[0];\n purchaseObject['items'] = config.ordersTrackingData.products;\n gtag('event', 'purchase', purchaseObject);\n }\n }\n }\n }\n});\n","Magento_Shipping/js/view/checkout/shipping/shipping-policy.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'uiComponent',\n 'Magento_Shipping/js/model/config'\n\n], function (Component, config) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Shipping/checkout/shipping/shipping-policy'\n },\n config: config()\n });\n});\n","Magento_Shipping/js/model/config.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n 'use strict';\n\n return function () {\n return window.checkoutConfig.shippingPolicy;\n };\n});\n","Magento_Payment/js/transparent.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'jquery',\n 'mage/template',\n 'Magento_Ui/js/modal/alert',\n 'jquery-ui-modules/widget',\n 'Magento_Payment/js/model/credit-card-validation/validator',\n 'Magento_Checkout/js/model/full-screen-loader'\n], function ($, mageTemplate, alert, ui, validator, fullScreenLoader) {\n 'use strict';\n\n $.widget('mage.transparent', {\n options: {\n context: null,\n placeOrderSelector: '[data-role=\"review-save\"]',\n paymentFormSelector: '#co-payment-form',\n updateSelectorPrefix: '#checkout-',\n updateSelectorSuffix: '-load',\n hiddenFormTmpl:\n '<form target=\"<%= data.target %>\" action=\"<%= data.action %>\" method=\"POST\" ' +\n 'hidden enctype=\"application/x-www-form-urlencoded\" class=\"no-display\">' +\n '<% _.each(data.inputs, function(val, key){ %>' +\n '<input value=\"<%= val %>\" name=\"<%= key %>\" type=\"hidden\">' +\n '<% }); %>' +\n '</form>',\n reviewAgreementForm: '#checkout-agreements',\n cgiUrl: null,\n orderSaveUrl: null,\n controller: null,\n gateway: null,\n dateDelim: null,\n cardFieldsMap: null,\n expireYearLength: 2\n },\n\n /**\n * {Function}\n * @private\n */\n _create: function () {\n this.hiddenFormTmpl = mageTemplate(this.options.hiddenFormTmpl);\n\n if (this.options.context) {\n this.options.context.setPlaceOrderHandler($.proxy(this._orderSave, this));\n this.options.context.setValidateHandler($.proxy(this._validateHandler, this));\n } else {\n $(this.options.placeOrderSelector)\n .off('click')\n .on('click', $.proxy(this._placeOrderHandler, this));\n }\n\n this.element.validation();\n $('[data-container=\"' + this.options.gateway + '-cc-number\"]').on('focusout', function () {\n $(this).valid();\n });\n },\n\n /**\n * handler for credit card validation\n * @return {Boolean}\n * @private\n */\n _validateHandler: function () {\n return this.element.validation && this.element.validation('isValid');\n },\n\n /**\n * handler for Place Order button to call gateway for credit card validation\n * @return {Boolean}\n * @private\n */\n _placeOrderHandler: function () {\n if (this._validateHandler()) {\n this._orderSave();\n }\n\n return false;\n },\n\n /**\n * Save order and generate post data for gateway call\n * @private\n */\n _orderSave: function () {\n var postData = $(this.options.paymentFormSelector).serialize();\n\n if ($(this.options.reviewAgreementForm).length) {\n postData += '&' + $(this.options.reviewAgreementForm).serialize();\n }\n postData += '&controller=' + this.options.controller;\n postData += '&cc_type=' + this.element.find(\n '[data-container=\"' + this.options.gateway + '-cc-type\"]'\n ).val();\n\n return $.ajax({\n url: this.options.orderSaveUrl,\n type: 'post',\n context: this,\n data: postData,\n dataType: 'json',\n\n /**\n * {Function}\n */\n beforeSend: function () {\n fullScreenLoader.startLoader();\n },\n\n /**\n * {Function}\n */\n success: function (response) {\n var preparedData,\n msg,\n\n /**\n * {Function}\n */\n alertActionHandler = function () {\n // default action\n };\n\n if (response.success && response[this.options.gateway]) {\n preparedData = this._preparePaymentData(\n response[this.options.gateway].fields,\n this.options.cardFieldsMap\n );\n this._postPaymentToGateway(preparedData);\n } else {\n fullScreenLoader.stopLoader(true);\n\n msg = response['error_messages'];\n\n if (this.options.context) {\n this.options.context.clearTimeout().fail();\n alertActionHandler = this.options.context.alertActionHandler;\n }\n\n if (typeof msg === 'object') {\n msg = msg.join('\\n');\n }\n\n if (msg) {\n alert(\n {\n content: msg,\n actions: {\n\n /**\n * {Function}\n */\n always: alertActionHandler\n }\n }\n );\n }\n }\n }.bind(this)\n });\n },\n\n /**\n * Post data to gateway for credit card validation\n * @param {Object} data\n * @private\n */\n _postPaymentToGateway: function (data) {\n var tmpl,\n iframeSelector = '[data-container=\"' + this.options.gateway + '-transparent-iframe\"]';\n\n tmpl = this.hiddenFormTmpl({\n data: {\n target: $(iframeSelector).attr('name'),\n action: this.options.cgiUrl,\n inputs: data\n }\n });\n $(tmpl).appendTo($(iframeSelector)).trigger('submit');\n },\n\n /**\n * Add credit card fields to post data for gateway\n * @param {Object} data\n * @param {Object} ccfields\n * @private\n */\n _preparePaymentData: function (data, ccfields) {\n var preparedata;\n\n if (this.element.find('[data-container=\"' + this.options.gateway + '-cc-cvv\"]').length) {\n data[ccfields.cccvv] = this.element.find(\n '[data-container=\"' + this.options.gateway + '-cc-cvv\"]'\n ).val();\n }\n preparedata = this._prepareExpDate();\n data[ccfields.ccexpdate] = preparedata.month + this.options.dateDelim + preparedata.year;\n data[ccfields.ccnum] = this.element.find(\n '[data-container=\"' + this.options.gateway + '-cc-number\"]'\n ).val();\n\n return data;\n },\n\n /**\n * Grab Month and Year into one\n * @returns {Object}\n * @private\n */\n _prepareExpDate: function () {\n var year = this.element.find('[data-container=\"' + this.options.gateway + '-cc-year\"]').val(),\n month = parseInt(\n this.element.find('[data-container=\"' + this.options.gateway + '-cc-month\"]').val(),\n 10\n );\n\n if (year.length > this.options.expireYearLength) {\n year = year.substring(year.length - this.options.expireYearLength);\n }\n\n if (month < 10) {\n month = '0' + month;\n }\n\n return {\n month: month, year: year\n };\n }\n });\n\n return $.mage.transparent;\n});\n","Magento_Payment/js/cc-type.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'jquery',\n 'jquery-ui-modules/widget'\n], function ($) {\n 'use strict';\n\n $.widget('mage.creditCardType', {\n options: {\n typeCodes: ['SS', 'SM', 'SO'] // Type codes for Switch/Maestro/Solo credit cards.\n },\n\n /**\n * Bind change handler to select element and trigger the event to show/hide\n * the Switch/Maestro or Solo credit card type container for those credit card types.\n * @private\n */\n _create: function () {\n this.element.on('change', $.proxy(this._toggleCardType, this)).trigger('change');\n },\n\n /**\n * Toggle the Switch/Maestro and Solo credit card type container depending on which\n * credit card type is selected.\n * @private\n */\n _toggleCardType: function () {\n $(this.options.creditCardTypeContainer)\n .toggle($.inArray(this.element.val(), this.options.typeCodes) !== -1);\n }\n });\n\n return $.mage.creditCardType;\n});\n","Magento_Payment/js/view/payment/cc-form.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'underscore',\n 'Magento_Checkout/js/view/payment/default',\n 'Magento_Payment/js/model/credit-card-validation/credit-card-data',\n 'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator',\n 'mage/translate'\n], function (_, Component, creditCardData, cardNumberValidator, $t) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n creditCardType: '',\n creditCardExpYear: '',\n creditCardExpMonth: '',\n creditCardNumber: '',\n creditCardSsStartMonth: '',\n creditCardSsStartYear: '',\n creditCardSsIssue: '',\n creditCardVerificationNumber: '',\n selectedCardType: null\n },\n\n /** @inheritdoc */\n initObservable: function () {\n this._super()\n .observe([\n 'creditCardType',\n 'creditCardExpYear',\n 'creditCardExpMonth',\n 'creditCardNumber',\n 'creditCardVerificationNumber',\n 'creditCardSsStartMonth',\n 'creditCardSsStartYear',\n 'creditCardSsIssue',\n 'selectedCardType'\n ]);\n\n return this;\n },\n\n /**\n * Init component\n */\n initialize: function () {\n var self = this;\n\n this._super();\n\n //Set credit card number to credit card data object\n this.creditCardNumber.subscribe(function (value) {\n var result;\n\n self.selectedCardType(null);\n\n if (value === '' || value === null) {\n return false;\n }\n result = cardNumberValidator(value);\n\n if (!result.isPotentiallyValid && !result.isValid) {\n return false;\n }\n\n if (result.card !== null) {\n self.selectedCardType(result.card.type);\n creditCardData.creditCard = result.card;\n }\n\n if (result.isValid) {\n creditCardData.creditCardNumber = value;\n self.creditCardType(result.card.type);\n }\n });\n\n //Set expiration year to credit card data object\n this.creditCardExpYear.subscribe(function (value) {\n creditCardData.expirationYear = value;\n });\n\n //Set expiration month to credit card data object\n this.creditCardExpMonth.subscribe(function (value) {\n creditCardData.expirationMonth = value;\n });\n\n //Set cvv code to credit card data object\n this.creditCardVerificationNumber.subscribe(function (value) {\n creditCardData.cvvCode = value;\n });\n },\n\n /**\n * Get code\n * @returns {String}\n */\n getCode: function () {\n return 'cc';\n },\n\n /**\n * Get data\n * @returns {Object}\n */\n getData: function () {\n return {\n 'method': this.item.method,\n 'additional_data': {\n 'cc_cid': this.creditCardVerificationNumber(),\n 'cc_ss_start_month': this.creditCardSsStartMonth(),\n 'cc_ss_start_year': this.creditCardSsStartYear(),\n 'cc_ss_issue': this.creditCardSsIssue(),\n 'cc_type': this.creditCardType(),\n 'cc_exp_year': this.creditCardExpYear(),\n 'cc_exp_month': this.creditCardExpMonth(),\n 'cc_number': this.creditCardNumber()\n }\n };\n },\n\n /**\n * Get list of available credit card types\n * @returns {Object}\n */\n getCcAvailableTypes: function () {\n return window.checkoutConfig.payment.ccform.availableTypes[this.getCode()];\n },\n\n /**\n * Get payment icons\n * @param {String} type\n * @returns {Boolean}\n */\n getIcons: function (type) {\n return window.checkoutConfig.payment.ccform.icons.hasOwnProperty(type) ?\n window.checkoutConfig.payment.ccform.icons[type]\n : false;\n },\n\n /**\n * Get list of months\n * @returns {Object}\n */\n getCcMonths: function () {\n return window.checkoutConfig.payment.ccform.months[this.getCode()];\n },\n\n /**\n * Get list of years\n * @returns {Object}\n */\n getCcYears: function () {\n return window.checkoutConfig.payment.ccform.years[this.getCode()];\n },\n\n /**\n * Check if current payment has verification\n * @returns {Boolean}\n */\n hasVerification: function () {\n return window.checkoutConfig.payment.ccform.hasVerification[this.getCode()];\n },\n\n /**\n * @deprecated\n * @returns {Boolean}\n */\n hasSsCardType: function () {\n return window.checkoutConfig.payment.ccform.hasSsCardType[this.getCode()];\n },\n\n /**\n * Get image url for CVV\n * @returns {String}\n */\n getCvvImageUrl: function () {\n return window.checkoutConfig.payment.ccform.cvvImageUrl[this.getCode()];\n },\n\n /**\n * Get image for CVV\n * @returns {String}\n */\n getCvvImageHtml: function () {\n return '<img src=\"' + this.getCvvImageUrl() +\n '\" alt=\"' + $t('Card Verification Number Visual Reference') +\n '\" title=\"' + $t('Card Verification Number Visual Reference') +\n '\" />';\n },\n\n /**\n * Get unsanitized html for image for CVV\n * @returns {String}\n */\n getCvvImageUnsanitizedHtml: function () {\n return this.getCvvImageHtml();\n },\n\n /**\n * @deprecated\n * @returns {Object}\n */\n getSsStartYears: function () {\n return window.checkoutConfig.payment.ccform.ssStartYears[this.getCode()];\n },\n\n /**\n * Get list of available credit card types values\n * @returns {Object}\n */\n getCcAvailableTypesValues: function () {\n return _.map(this.getCcAvailableTypes(), function (value, key) {\n return {\n 'value': key,\n 'type': value\n };\n });\n },\n\n /**\n * Get list of available month values\n * @returns {Object}\n */\n getCcMonthsValues: function () {\n return _.map(this.getCcMonths(), function (value, key) {\n return {\n 'value': key,\n 'month': value\n };\n });\n },\n\n /**\n * Get list of available year values\n * @returns {Object}\n */\n getCcYearsValues: function () {\n return _.map(this.getCcYears(), function (value, key) {\n return {\n 'value': key,\n 'year': value\n };\n });\n },\n\n /**\n * @deprecated\n * @returns {Object}\n */\n getSsStartYearsValues: function () {\n return _.map(this.getSsStartYears(), function (value, key) {\n return {\n 'value': key,\n 'year': value\n };\n });\n },\n\n /**\n * Is legend available to display\n * @returns {Boolean}\n */\n isShowLegend: function () {\n return false;\n },\n\n /**\n * Get available credit card type by code\n * @param {String} code\n * @returns {String}\n */\n getCcTypeTitleByCode: function (code) {\n var title = '',\n keyValue = 'value',\n keyType = 'type';\n\n _.each(this.getCcAvailableTypesValues(), function (value) {\n if (value[keyValue] === code) {\n title = value[keyType];\n }\n });\n\n return title;\n },\n\n /**\n * Prepare credit card number to output\n * @param {String} number\n * @returns {String}\n */\n formatDisplayCcNumber: function (number) {\n return 'xxxx-' + number.substr(-4);\n },\n\n /**\n * Get credit card details\n * @returns {Array}\n */\n getInfo: function () {\n return [\n {\n 'name': 'Credit Card Type', value: this.getCcTypeTitleByCode(this.creditCardType())\n },\n {\n 'name': 'Credit Card Number', value: this.formatDisplayCcNumber(this.creditCardNumber())\n }\n ];\n }\n });\n});\n","Magento_Payment/js/view/payment/payments.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'uiComponent',\n 'Magento_Checkout/js/model/payment/renderer-list'\n], function (Component, rendererList) {\n 'use strict';\n\n rendererList.push(\n {\n type: 'free',\n component: 'Magento_Payment/js/view/payment/method-renderer/free-method'\n }\n );\n\n /** Add view logic here if needed */\n return Component.extend({});\n});\n","Magento_Payment/js/view/payment/iframe.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'jquery',\n 'Magento_Payment/js/view/payment/cc-form',\n 'Magento_Ui/js/model/messageList',\n 'mage/translate',\n 'Magento_Checkout/js/model/full-screen-loader',\n 'Magento_Checkout/js/action/set-payment-information',\n 'Magento_Checkout/js/model/payment/additional-validators',\n 'Magento_Ui/js/modal/alert'\n], function (\n $,\n Component,\n messageList,\n $t,\n fullScreenLoader,\n setPaymentInformationAction,\n additionalValidators,\n alert\n) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Payment/payment/iframe',\n timeoutId: null,\n timeoutMessage: 'Sorry, but something went wrong.'\n },\n\n /**\n * @returns {String}\n */\n getSource: function () {\n return window.checkoutConfig.payment.iframe.source[this.getCode()];\n },\n\n /**\n * @returns {String}\n */\n getControllerName: function () {\n return window.checkoutConfig.payment.iframe.controllerName[this.getCode()];\n },\n\n /**\n * @returns {String}\n */\n getPlaceOrderUrl: function () {\n return window.checkoutConfig.payment.iframe.placeOrderUrl[this.getCode()];\n },\n\n /**\n * @returns {String}\n */\n getCgiUrl: function () {\n return window.checkoutConfig.payment.iframe.cgiUrl[this.getCode()];\n },\n\n /**\n * @returns {String}\n */\n getSaveOrderUrl: function () {\n return window.checkoutConfig.payment.iframe.saveOrderUrl[this.getCode()];\n },\n\n /**\n * @returns {String}\n */\n getDateDelim: function () {\n return window.checkoutConfig.payment.iframe.dateDelim[this.getCode()];\n },\n\n /**\n * @returns {String}\n */\n getCardFieldsMap: function () {\n return window.checkoutConfig.payment.iframe.cardFieldsMap[this.getCode()];\n },\n\n /**\n * @returns {String}\n */\n getExpireYearLength: function () {\n return window.checkoutConfig.payment.iframe.expireYearLength[this.getCode()];\n },\n\n /**\n * @param {Object} parent\n * @returns {Function}\n */\n originalPlaceOrder: function (parent) {\n return parent.placeOrder.bind(parent);\n },\n\n /**\n * @returns {Number}\n */\n getTimeoutTime: function () {\n return window.checkoutConfig.payment.iframe.timeoutTime[this.getCode()];\n },\n\n /**\n * @returns {String}\n */\n getTimeoutMessage: function () {\n return $t(this.timeoutMessage);\n },\n\n /**\n * @override\n */\n placeOrder: function () {\n var self = this;\n\n if (this.validateHandler() &&\n additionalValidators.validate() &&\n this.isPlaceOrderActionAllowed() === true\n ) {\n fullScreenLoader.startLoader();\n\n this.isPlaceOrderActionAllowed(false);\n\n $.when(\n this.setPaymentInformation()\n ).done(\n this.done.bind(this)\n ).fail(\n this.fail.bind(this)\n ).always(\n function () {\n self.isPlaceOrderActionAllowed(true);\n }\n );\n\n this.initTimeoutHandler();\n }\n },\n\n /**\n * {Function}\n */\n setPaymentInformation: function () {\n return setPaymentInformationAction(\n this.messageContainer,\n {\n method: this.getCode()\n }\n );\n },\n\n /**\n * {Function}\n */\n initTimeoutHandler: function () {\n this.timeoutId = setTimeout(\n this.timeoutHandler.bind(this),\n this.getTimeoutTime()\n );\n\n $(window).off('clearTimeout')\n .on('clearTimeout', this.clearTimeout.bind(this));\n },\n\n /**\n * {Function}\n */\n clearTimeout: function () {\n clearTimeout(this.timeoutId);\n this.fail();\n\n return this;\n },\n\n /**\n * {Function}\n */\n timeoutHandler: function () {\n this.clearTimeout();\n\n alert(\n {\n content: this.getTimeoutMessage(),\n actions: {\n\n /**\n * {Function}\n */\n always: this.alertActionHandler.bind(this)\n }\n }\n );\n\n this.fail();\n },\n\n /**\n * {Function}\n */\n alertActionHandler: function () {\n fullScreenLoader.startLoader();\n window.location.reload();\n },\n\n /**\n * {Function}\n */\n fail: function () {\n fullScreenLoader.stopLoader();\n\n return this;\n },\n\n /**\n * {Function}\n */\n done: function () {\n this.placeOrderHandler().fail(function () {\n fullScreenLoader.stopLoader();\n });\n\n return this;\n }\n });\n});\n","Magento_Payment/js/view/payment/method-renderer/free-method.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'Magento_Checkout/js/view/payment/default',\n 'Magento_Checkout/js/model/quote'\n], function (Component, quote) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Payment/payment/free'\n },\n\n /** Returns is method available */\n isAvailable: function () {\n return quote.totals()['grand_total'] <= 0;\n }\n });\n});\n","Magento_Payment/js/model/credit-card-validation/credit-card-number-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'mageUtils',\n 'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator',\n 'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/credit-card-type'\n], function (utils, luhn10, creditCardTypes) {\n 'use strict';\n\n /**\n * @param {*} card\n * @param {*} isPotentiallyValid\n * @param {*} isValid\n * @return {Object}\n */\n function resultWrapper(card, isPotentiallyValid, isValid) {\n return {\n card: card,\n isValid: isValid,\n isPotentiallyValid: isPotentiallyValid\n };\n }\n\n return function (value) {\n var potentialTypes,\n cardType,\n valid,\n i,\n maxLength;\n\n if (utils.isEmpty(value)) {\n return resultWrapper(null, false, false);\n }\n\n value = value.replace(/\\s+/g, '');\n\n if (!/^\\d*$/.test(value)) {\n return resultWrapper(null, false, false);\n }\n\n potentialTypes = creditCardTypes.getCardTypes(value);\n\n if (potentialTypes.length === 0) {\n return resultWrapper(null, false, false);\n } else if (potentialTypes.length !== 1) {\n return resultWrapper(null, true, false);\n }\n\n cardType = potentialTypes[0];\n\n if (cardType.type === 'unionpay') { // UnionPay is not Luhn 10 compliant\n valid = true;\n } else {\n valid = luhn10(value);\n }\n\n for (i = 0; i < cardType.lengths.length; i++) {\n if (cardType.lengths[i] === value.length) {\n return resultWrapper(cardType, valid, valid);\n }\n }\n\n maxLength = Math.max.apply(null, cardType.lengths);\n\n if (value.length < maxLength) {\n return resultWrapper(cardType, true, false);\n }\n\n return resultWrapper(cardType, false, false);\n };\n});\n","Magento_Payment/js/model/credit-card-validation/cvv-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([], function () {\n 'use strict';\n\n /**\n * @param {*} isValid\n * @param {*} isPotentiallyValid\n * @return {Object}\n */\n function resultWrapper(isValid, isPotentiallyValid) {\n return {\n isValid: isValid,\n isPotentiallyValid: isPotentiallyValid\n };\n }\n\n /**\n * CVV number validation.\n * Validate digit count for CVV code.\n *\n * @param {*} value\n * @param {Number} maxLength\n * @return {Object}\n */\n return function (value, maxLength) {\n var DEFAULT_LENGTH = 3;\n\n maxLength = maxLength || DEFAULT_LENGTH;\n\n if (!/^\\d*$/.test(value)) {\n return resultWrapper(false, false);\n }\n\n if (value.length === maxLength) {\n return resultWrapper(true, true);\n }\n\n if (value.length < maxLength) {\n return resultWrapper(false, true);\n }\n\n if (value.length > maxLength) {\n return resultWrapper(false, false);\n }\n };\n});\n","Magento_Payment/js/model/credit-card-validation/validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'jquery',\n 'Magento_Payment/js/model/credit-card-validation/cvv-validator',\n 'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator',\n 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator',\n 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator',\n 'Magento_Payment/js/model/credit-card-validation/credit-card-data',\n 'mage/translate'\n], function ($, cvvValidator, creditCardNumberValidator, yearValidator, monthValidator, creditCardData) {\n 'use strict';\n\n $('.payment-method-content input[type=\"number\"]').on('keyup', function () {\n if ($(this).val() < 0) {\n $(this).val($(this).val().replace(/^-/, ''));\n }\n });\n\n $.each({\n 'validate-card-type': [\n function (number, item, allowedTypes) {\n var cardInfo,\n i,\n l;\n\n if (!creditCardNumberValidator(number).isValid) {\n return false;\n }\n\n cardInfo = creditCardNumberValidator(number).card;\n\n for (i = 0, l = allowedTypes.length; i < l; i++) {\n if (cardInfo.title == allowedTypes[i].type) { //eslint-disable-line eqeqeq\n return true;\n }\n }\n\n return false;\n },\n $.mage.__('Please enter a valid credit card type number.')\n ],\n 'validate-card-number': [\n\n /**\n * Validate credit card number based on mod 10\n *\n * @param {*} number - credit card number\n * @return {Boolean}\n */\n function (number) {\n return creditCardNumberValidator(number).isValid;\n },\n $.mage.__('Please enter a valid credit card number.')\n ],\n 'validate-card-date': [\n\n /**\n * Validate credit card expiration month\n *\n * @param {String} date - month\n * @return {Boolean}\n */\n function (date) {\n return monthValidator(date).isValid;\n },\n $.mage.__('Incorrect credit card expiration month.')\n ],\n 'validate-card-cvv': [\n\n /**\n * Validate cvv\n *\n * @param {String} cvv - card verification value\n * @return {Boolean}\n */\n function (cvv) {\n var maxLength = creditCardData.creditCard ? creditCardData.creditCard.code.size : 3;\n\n return cvvValidator(cvv, maxLength).isValid;\n },\n $.mage.__('Please enter a valid credit card verification number.')\n ],\n 'validate-card-year': [\n\n /**\n * Validate credit card expiration year\n *\n * @param {String} date - year\n * @return {Boolean}\n */\n function (date) {\n return yearValidator(date).isValid;\n },\n $.mage.__('Incorrect credit card expiration year.')\n ]\n\n }, function (i, rule) {\n rule.unshift(i);\n $.validator.addMethod.apply($.validator, rule);\n });\n});\n","Magento_Payment/js/model/credit-card-validation/credit-card-data.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([], function () {\n 'use strict';\n\n return {\n creditCard: null,\n creditCardNumber: null,\n expirationMonth: null,\n expirationYear: null,\n cvvCode: null\n };\n});\n","Magento_Payment/js/model/credit-card-validation/expiration-date-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'mageUtils',\n 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/parse-date',\n 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator',\n 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator'\n], function (utils, parseDate, expirationMonth, expirationYear) {\n 'use strict';\n\n /**\n * @param {*} isValid\n * @param {*} isPotentiallyValid\n * @param {*} month\n * @param {*} year\n * @return {Object}\n */\n function resultWrapper(isValid, isPotentiallyValid, month, year) {\n return {\n isValid: isValid,\n isPotentiallyValid: isPotentiallyValid,\n month: month,\n year: year\n };\n }\n\n return function (value) {\n var date,\n monthValid,\n yearValid;\n\n if (utils.isEmpty(value)) {\n return resultWrapper(false, false, null, null);\n }\n\n value = value.replace(/^(\\d\\d) (\\d\\d(\\d\\d)?)$/, '$1/$2');\n date = parseDate(value);\n monthValid = expirationMonth(date.month);\n yearValid = expirationYear(date.year);\n\n if (monthValid.isValid && yearValid.isValid) {\n return resultWrapper(true, true, date.month, date.year);\n }\n\n if (monthValid.isPotentiallyValid && yearValid.isPotentiallyValid) {\n return resultWrapper(false, true, null, null);\n }\n\n return resultWrapper(false, false, null, null);\n };\n});\n","Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n 'use strict';\n\n /**\n * Luhn algorithm verification\n */\n return function (a, b, c, d, e) {\n for (d = +a[b = a.length - 1], e = 0; b--;) {\n c = +a[b];\n d += ++e % 2 ? 2 * c % 10 + (c > 4) : c;\n }\n\n return !(d % 10);\n };\n});\n","Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* @api */\ndefine([\n 'jquery',\n 'mageUtils'\n], function ($, utils) {\n 'use strict';\n\n var types = [\n {\n title: 'Visa',\n type: 'VI',\n pattern: '^4\\\\d*$',\n gaps: [4, 8, 12],\n lengths: [16],\n code: {\n name: 'CVV',\n size: 3\n }\n },\n {\n title: 'MasterCard',\n type: 'MC',\n pattern: '^(?:5[1-5][0-9]{2}|222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}$',\n gaps: [4, 8, 12],\n lengths: [16],\n code: {\n name: 'CVC',\n size: 3\n }\n },\n {\n title: 'American Express',\n type: 'AE',\n pattern: '^3([47]\\\\d*)?$',\n isAmex: true,\n gaps: [4, 10],\n lengths: [15],\n code: {\n name: 'CID',\n size: 4\n }\n },\n {\n title: 'Diners',\n type: 'DN',\n pattern: '^(3(0[0-5]|095|6|[8-9]))\\\\d*$',\n gaps: [4, 10],\n lengths: [14, 16, 17, 18, 19],\n code: {\n name: 'CVV',\n size: 3\n }\n },\n {\n title: 'Discover',\n type: 'DI',\n pattern: '^(6011(0|[2-4]|74|7[7-9]|8[6-9]|9)|6(4[4-9]|5))\\\\d*$',\n gaps: [4, 8, 12],\n lengths: [16, 17, 18, 19],\n code: {\n name: 'CID',\n size: 3\n }\n },\n {\n title: 'JCB',\n type: 'JCB',\n pattern: '^35(2[8-9]|[3-8])\\\\d*$',\n gaps: [4, 8, 12],\n lengths: [16, 17, 18, 19],\n code: {\n name: 'CVV',\n size: 3\n }\n },\n {\n title: 'UnionPay',\n type: 'UN',\n pattern: '^(622(1(2[6-9]|[3-9])|[3-8]|9([[0-1]|2[0-5]))|62[4-6]|628([2-8]))\\\\d*?$',\n gaps: [4, 8, 12],\n lengths: [16, 17, 18, 19],\n code: {\n name: 'CVN',\n size: 3\n }\n },\n {\n title: 'Maestro International',\n type: 'MI',\n pattern: '^(5(0|[6-9])|63|67(?!59|6770|6774))\\\\d*$',\n gaps: [4, 8, 12],\n lengths: [12, 13, 14, 15, 16, 17, 18, 19],\n code: {\n name: 'CVC',\n size: 3\n }\n },\n {\n title: 'Maestro Domestic',\n type: 'MD',\n pattern: '^6759(?!24|38|40|6[3-9]|70|76)|676770|676774\\\\d*$',\n gaps: [4, 8, 12],\n lengths: [12, 13, 14, 15, 16, 17, 18, 19],\n code: {\n name: 'CVC',\n size: 3\n }\n },\n {\n title: 'Hipercard',\n type: 'HC',\n pattern: '^((606282)|(637095)|(637568)|(637599)|(637609)|(637612))\\\\d*$',\n gaps: [4, 8, 12],\n lengths: [13, 16],\n code: {\n name: 'CVC',\n size: 3\n }\n },\n {\n title: 'Elo',\n type: 'ELO',\n pattern: '^((509091)|(636368)|(636297)|(504175)|(438935)|(40117[8-9])|(45763[1-2])|' +\n '(457393)|(431274)|(50990[0-2])|(5099[7-9][0-9])|(50996[4-9])|(509[1-8][0-9][0-9])|' +\n '(5090(0[0-2]|0[4-9]|1[2-9]|[24589][0-9]|3[1-9]|6[0-46-9]|7[0-24-9]))|' +\n '(5067(0[0-24-8]|1[0-24-9]|2[014-9]|3[0-379]|4[0-9]|5[0-3]|6[0-5]|7[0-8]))|' +\n '(6504(0[5-9]|1[0-9]|2[0-9]|3[0-9]))|' +\n '(6504(8[5-9]|9[0-9])|6505(0[0-9]|1[0-9]|2[0-9]|3[0-8]))|' +\n '(6505(4[1-9]|5[0-9]|6[0-9]|7[0-9]|8[0-9]|9[0-8]))|' +\n '(6507(0[0-9]|1[0-8]))|(65072[0-7])|(6509(0[1-9]|1[0-9]|20))|' +\n '(6516(5[2-9]|6[0-9]|7[0-9]))|(6550(0[0-9]|1[0-9]))|' +\n '(6550(2[1-9]|3[0-9]|4[0-9]|5[0-8])))\\\\d*$',\n gaps: [4, 8, 12],\n lengths: [16],\n code: {\n name: 'CVC',\n size: 3\n }\n },\n {\n title: 'Aura',\n type: 'AU',\n pattern: '^5078\\\\d*$',\n gaps: [4, 8, 12],\n lengths: [19],\n code: {\n name: 'CVC',\n size: 3\n }\n }\n ];\n\n return {\n /**\n * @param {*} cardNumber\n * @return {Array}\n */\n getCardTypes: function (cardNumber) {\n var i, value,\n result = [];\n\n if (utils.isEmpty(cardNumber)) {\n return result;\n }\n\n if (cardNumber === '') {\n return $.extend(true, {}, types);\n }\n\n for (i = 0; i < types.length; i++) {\n value = types[i];\n\n if (new RegExp(value.pattern).test(cardNumber)) {\n result.push($.extend(true, {}, value));\n }\n }\n\n return result;\n }\n };\n});\n","Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n 'use strict';\n\n /**\n * @param {*} isValid\n * @param {*} isPotentiallyValid\n * @return {Object}\n */\n function resultWrapper(isValid, isPotentiallyValid) {\n return {\n isValid: isValid,\n isPotentiallyValid: isPotentiallyValid\n };\n }\n\n return function (value) {\n var month,\n monthValid;\n\n if (value.replace(/\\s/g, '') === '' || value === '0') {\n return resultWrapper(false, true);\n }\n\n if (!/^\\d*$/.test(value)) {\n return resultWrapper(false, false);\n }\n\n if (isNaN(value)) {\n return resultWrapper(false, false);\n }\n\n month = parseInt(value, 10);\n monthValid = month > 0 && month < 13;\n\n return resultWrapper(monthValid, monthValid);\n };\n});\n","Magento_Payment/js/model/credit-card-validation/expiration-date-validator/parse-date.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n 'use strict';\n\n return function (value) {\n var month, len;\n\n if (value.match('/')) {\n value = value.split(/\\s*\\/\\s*/g);\n\n return {\n month: value[0],\n year: value.slice(1).join()\n };\n }\n\n len = value[0] === '0' || value.length > 5 || value.length === 4 || value.length === 3 ? 2 : 1;\n month = value.substr(0, len);\n\n return {\n month: month,\n year: value.substr(month.length, 4)\n };\n };\n});\n","Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n 'use strict';\n\n /**\n * @param {*} isValid\n * @param {*} isPotentiallyValid\n * @return {Object}\n */\n function resultWrapper(isValid, isPotentiallyValid) {\n return {\n isValid: isValid,\n isPotentiallyValid: isPotentiallyValid\n };\n }\n\n return function (value) {\n var currentYear = new Date().getFullYear(),\n len = value.length,\n valid,\n expMaxLifetime = 19;\n\n if (value.replace(/\\s/g, '') === '') {\n return resultWrapper(false, true);\n }\n\n if (!/^\\d*$/.test(value)) {\n return resultWrapper(false, false);\n }\n\n if (len !== 4) {\n return resultWrapper(false, true);\n }\n\n value = parseInt(value, 10);\n valid = value >= currentYear && value <= currentYear + expMaxLifetime;\n\n return resultWrapper(valid, valid);\n };\n});\n","Magento_ReCaptchaStorePickup/js/reCaptchaStorePickup.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['Magento_ReCaptchaFrontendUi/js/reCaptcha'], function (reCaptcha) {\n 'use strict';\n\n return reCaptcha.extend({\n\n /**\n * @inheritdoc\n */\n renderReCaptcha: function () {\n this.captchaInitialized = false;\n this._super();\n }\n });\n});\n","js-cookie/cookie-wrapper.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'js-cookie/js.cookie'\n], function ($, cookie) {\n 'use strict';\n\n window.Cookies = window.Cookies || cookie;\n\n var config = $.cookie = function (key, value, options) {\n if (value !== undefined) {\n options = $.extend({}, config.defaults, options);\n\n return cookie.set(key, value, options);\n }\n\n var result = key ? undefined : {},\n cookies = document.cookie ? document.cookie.split('; ') : [],\n i;\n\n for (i = 0; i < cookies.length; i++) {\n var parts = cookies[i].split('='),\n name = config.raw ? parts.shift() : decodeURIComponent(parts.shift()),\n cookieValue = parts.join('=');\n\n if (key && key === name) {\n result = decodeURIComponent(cookieValue.replace('/\\\\+/g', ' '));\n break;\n }\n\n if (!key && (cookieValue = decodeURIComponent(cookieValue.replace('/\\\\+/g', ' '))) !== undefined) {\n result[name] = cookieValue;\n }\n }\n\n return result;\n };\n\n config.defaults = {};\n\n $.removeCookie = function (key, options) {\n if ($.cookie(key) === undefined) {\n return false;\n }\n\n $.cookie(key, '', $.extend({}, options, { expires: -1 }));\n return !$.cookie(key);\n };\n});\n","js-cookie/js.cookie.js":"/*! js-cookie v3.0.1 | MIT */\n;\n(function (global, factory) {\n typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n typeof define === 'function' && define.amd ? define(factory) :\n (global = global || self, (function () {\n var current = global.Cookies;\n var exports = global.Cookies = factory();\n exports.noConflict = function () { global.Cookies = current; return exports; };\n }()));\n}(this, (function () { 'use strict';\n\n /* eslint-disable no-var */\n function assign (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n for (var key in source) {\n target[key] = source[key];\n }\n }\n return target\n }\n /* eslint-enable no-var */\n\n /* eslint-disable no-var */\n var defaultConverter = {\n read: function (value) {\n if (value[0] === '\"') {\n value = value.slice(1, -1);\n }\n return value.replace(/(%[\\dA-F]{2})+/gi, decodeURIComponent)\n },\n write: function (value) {\n return encodeURIComponent(value).replace(\n /%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,\n decodeURIComponent\n )\n }\n };\n /* eslint-enable no-var */\n\n /* eslint-disable no-var */\n\n function init (converter, defaultAttributes) {\n function set (key, value, attributes) {\n if (typeof document === 'undefined') {\n return\n }\n\n attributes = assign({}, defaultAttributes, attributes);\n\n if (typeof attributes.expires === 'number') {\n attributes.expires = new Date(Date.now() + attributes.expires * 864e5);\n }\n if (attributes.expires) {\n attributes.expires = attributes.expires.toUTCString();\n }\n\n key = encodeURIComponent(key)\n .replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent)\n .replace(/[()]/g, escape);\n\n var stringifiedAttributes = '';\n for (var attributeName in attributes) {\n if (!attributes[attributeName]) {\n continue\n }\n\n stringifiedAttributes += '; ' + attributeName;\n\n if (attributes[attributeName] === true) {\n continue\n }\n\n // Considers RFC 6265 section 5.2:\n // ...\n // 3. If the remaining unparsed-attributes contains a %x3B (\";\")\n // character:\n // Consume the characters of the unparsed-attributes up to,\n // not including, the first %x3B (\";\") character.\n // ...\n stringifiedAttributes += '=' + attributes[attributeName].split(';')[0];\n }\n\n return (document.cookie =\n key + '=' + converter.write(value, key) + stringifiedAttributes)\n }\n\n function get (key) {\n if (typeof document === 'undefined' || (arguments.length && !key)) {\n return\n }\n\n // To prevent the for loop in the first place assign an empty array\n // in case there are no cookies at all.\n var cookies = document.cookie ? document.cookie.split('; ') : [];\n var jar = {};\n for (var i = 0; i < cookies.length; i++) {\n var parts = cookies[i].split('=');\n var value = parts.slice(1).join('=');\n\n try {\n var foundKey = decodeURIComponent(parts[0]);\n jar[foundKey] = converter.read(value, foundKey);\n\n if (key === foundKey) {\n break\n }\n } catch (e) {}\n }\n\n return key ? jar[key] : jar\n }\n\n return Object.create(\n {\n set: set,\n get: get,\n remove: function (key, attributes) {\n set(\n key,\n '',\n assign({}, attributes, {\n expires: -1\n })\n );\n },\n withAttributes: function (attributes) {\n return init(this.converter, assign({}, this.attributes, attributes))\n },\n withConverter: function (converter) {\n return init(assign({}, this.converter, converter), this.attributes)\n }\n },\n {\n attributes: { value: Object.freeze(defaultAttributes) },\n converter: { value: Object.freeze(converter) }\n }\n )\n }\n\n var api = init(defaultConverter, { path: '/' });\n /* eslint-enable no-var */\n\n return api;\n\n})));\n","Magento_InstantPurchase/js/view/instant-purchase.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'ko',\n 'jquery',\n 'underscore',\n 'uiComponent',\n 'Magento_Ui/js/modal/confirm',\n 'Magento_Customer/js/customer-data',\n 'mage/url',\n 'mage/template',\n 'mage/translate',\n 'text!Magento_InstantPurchase/template/confirmation.html',\n 'mage/validation'\n], function (ko, $, _, Component, confirm, customerData, urlBuilder, mageTemplate, $t, confirmationTemplate) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_InstantPurchase/instant-purchase',\n buttonText: $t('Instant Purchase'),\n purchaseUrl: urlBuilder.build('instantpurchase/button/placeOrder'),\n showButton: false,\n paymentToken: null,\n shippingAddress: null,\n billingAddress: null,\n shippingMethod: null,\n productFormSelector: '#product_addtocart_form',\n confirmationTitle: $t('Instant Purchase Confirmation'),\n confirmationData: {\n message: $t('Are you sure you want to place order and pay?'),\n shippingAddressTitle: $t('Shipping Address'),\n billingAddressTitle: $t('Billing Address'),\n paymentMethodTitle: $t('Payment Method'),\n shippingMethodTitle: $t('Shipping Method')\n }\n },\n\n /** @inheritdoc */\n initialize: function () {\n var instantPurchase = customerData.get('instant-purchase');\n\n this._super();\n\n this.setPurchaseData(instantPurchase());\n instantPurchase.subscribe(this.setPurchaseData, this);\n },\n\n /** @inheritdoc */\n initObservable: function () {\n this._super()\n .observe('showButton paymentToken shippingAddress billingAddress shippingMethod');\n\n return this;\n },\n\n /**\n * Set data from customerData.\n *\n * @param {Object} data\n */\n setPurchaseData: function (data) {\n this.showButton(data.available);\n this.paymentToken(data.paymentToken);\n this.shippingAddress(data.shippingAddress);\n this.billingAddress(data.billingAddress);\n this.shippingMethod(data.shippingMethod);\n },\n\n /**\n * Confirmation method\n */\n instantPurchase: function () {\n var form = $(this.productFormSelector),\n confirmTemplate = mageTemplate(confirmationTemplate),\n confirmData = _.extend({}, this.confirmationData, {\n paymentToken: this.paymentToken().summary,\n shippingAddress: this.shippingAddress().summary,\n billingAddress: this.billingAddress().summary,\n shippingMethod: this.shippingMethod().summary\n });\n\n if (!(form.validation() && form.validation('isValid'))) {\n return;\n }\n\n confirm({\n title: this.confirmationTitle,\n content: confirmTemplate({\n data: confirmData\n }),\n actions: {\n /** @inheritdoc */\n confirm: function () {\n $.ajax({\n url: this.purchaseUrl,\n data: form.serialize(),\n type: 'post',\n dataType: 'json',\n\n /** Show loader before send */\n beforeSend: function () {\n $('body').trigger('processStart');\n }\n }).always(function () {\n $('body').trigger('processStop');\n });\n }.bind(this)\n }\n });\n }\n });\n});\n","Magento_Tax/js/price/adjustment.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'Magento_Ui/js/grid/columns/column',\n 'mage/translate'\n], function (Element, $t) {\n 'use strict';\n\n return Element.extend({\n defaults: {\n bodyTmpl: 'Magento_Tax/price/adjustment',\n taxPriceType: 'final_price',\n taxPriceCssClass: 'price-including-tax',\n bothPrices: 3,\n inclTax: 2,\n exclTax: 1,\n modules: {\n price: '${ $.parentName }'\n },\n listens: {\n price: 'initializePriceAttributes'\n }\n },\n\n /**\n * {@inheritdoc}\n */\n initialize: function () {\n this._super()\n .initializePriceAttributes();\n\n return this;\n },\n\n /**\n * Update parent price.\n *\n * @returns {Object} Chainable.\n */\n initializePriceAttributes: function () {\n if (this.displayBothPrices && this.price()) {\n this.price().priceWrapperCssClasses = this.taxPriceCssClass;\n this.price().priceWrapperAttr = {\n 'data-label': $t('Incl. Tax')\n };\n }\n\n return this;\n },\n\n /**\n * Get price tax adjustment.\n *\n * @param {Object} row\n * @return {HTMLElement} tax html\n */\n getTax: function (row) {\n return row['price_info']['extension_attributes']['tax_adjustments']['formatted_prices'][this.taxPriceType];\n },\n\n /**\n * UnsanitizedHtml version of getTax.\n *\n * @param {Object} row\n * @return {HTMLElement} tax html\n */\n getTaxUnsanitizedHtml: function (row) {\n return this.getTax(row);\n },\n\n /**\n * Set price tax type.\n *\n * @param {String} priceType\n * @return {Object}\n */\n setPriceType: function (priceType) {\n this.taxPriceType = priceType;\n\n return this;\n },\n\n /**\n * Return whether display setting is to display\n * both price including tax and price excluding tax.\n *\n * @return {Boolean}\n */\n displayBothPrices: function () {\n return +this.source.data.displayTaxes === this.bothPrices;\n },\n\n /**\n * Return whether display setting is to display price including tax.\n *\n * @return {Boolean}\n */\n displayPriceIncludeTax: function () {\n return +this.source.data.displayTaxes === this.inclTax;\n },\n\n /**\n * Return whether display setting is to display price excluding tax.\n *\n * @return {Boolean}\n */\n displayPriceExclTax: function () {\n return +this.source.data.displayTaxes === this.exclTax;\n }\n });\n});\n","Magento_Tax/js/view/checkout/cart/totals/tax.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'Magento_Tax/js/view/checkout/summary/tax',\n 'Magento_Checkout/js/model/totals'\n], function (Component, totals) {\n 'use strict';\n\n var isFullTaxSummaryDisplayed = window.checkoutConfig.isFullTaxSummaryDisplayed,\n isZeroTaxDisplayed = window.checkoutConfig.isZeroTaxDisplayed;\n\n return Component.extend({\n /**\n * @override\n */\n ifShowValue: function () {\n if (parseInt(this.getPureValue()) === 0) { //eslint-disable-line radix\n return isZeroTaxDisplayed;\n }\n\n return true;\n },\n\n /**\n * @override\n */\n ifShowDetails: function () {\n return this.getPureValue() > 0 && isFullTaxSummaryDisplayed;\n },\n\n /**\n * @override\n */\n isCalculated: function () {\n return this.totals() && totals.getSegment('tax') !== null;\n }\n });\n});\n","Magento_Tax/js/view/checkout/cart/totals/shipping.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'Magento_Tax/js/view/checkout/summary/shipping',\n 'Magento_Checkout/js/model/quote'\n], function (Component, quote) {\n 'use strict';\n\n return Component.extend({\n /**\n * @override\n */\n isCalculated: function () {\n return !!quote.shippingMethod();\n },\n\n /**\n * @override\n */\n getShippingMethodTitle: function () {\n return '(' + this._super() + ')';\n }\n });\n});\n","Magento_Tax/js/view/checkout/cart/totals/grand-total.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'Magento_Tax/js/view/checkout/summary/grand-total'\n], function (Component) {\n 'use strict';\n\n return Component.extend({\n /**\n * @override\n */\n isDisplayed: function () {\n return true;\n }\n });\n});\n","Magento_Tax/js/view/checkout/minicart/subtotal/totals.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'ko',\n 'uiComponent',\n 'Magento_Customer/js/customer-data'\n], function (ko, Component, customerData) {\n 'use strict';\n\n return Component.extend({\n displaySubtotal: ko.observable(true),\n\n /**\n * @override\n */\n initialize: function () {\n this._super();\n this.cart = customerData.get('cart');\n }\n });\n});\n","Magento_Tax/js/view/checkout/summary/tax.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'ko',\n 'Magento_Checkout/js/view/summary/abstract-total',\n 'Magento_Checkout/js/model/quote',\n 'Magento_Checkout/js/model/totals',\n 'mage/translate',\n 'underscore'\n], function (ko, Component, quote, totals, $t, _) {\n 'use strict';\n\n var isTaxDisplayedInGrandTotal = window.checkoutConfig.includeTaxInGrandTotal,\n isFullTaxSummaryDisplayed = window.checkoutConfig.isFullTaxSummaryDisplayed,\n isZeroTaxDisplayed = window.checkoutConfig.isZeroTaxDisplayed,\n taxAmount = 0,\n rates = 0;\n\n return Component.extend({\n defaults: {\n isTaxDisplayedInGrandTotal: isTaxDisplayedInGrandTotal,\n notCalculatedMessage: $t('Not yet calculated'),\n template: 'Magento_Tax/checkout/summary/tax'\n },\n totals: quote.getTotals(),\n isFullTaxSummaryDisplayed: isFullTaxSummaryDisplayed,\n\n /**\n * @return {Boolean}\n */\n ifShowValue: function () {\n if (this.isFullMode() && this.getPureValue() == 0) { //eslint-disable-line eqeqeq\n return isZeroTaxDisplayed;\n }\n\n return true;\n },\n\n /**\n * @return {Boolean}\n */\n ifShowDetails: function () {\n if (!this.isFullMode()) {\n return false;\n }\n\n return this.getPureValue() > 0 && isFullTaxSummaryDisplayed;\n },\n\n /**\n * @return {Number}\n */\n getPureValue: function () {\n var amount = 0,\n taxTotal;\n\n if (this.totals()) {\n taxTotal = totals.getSegment('tax');\n\n if (taxTotal) {\n amount = taxTotal.value;\n }\n }\n\n return amount;\n },\n\n /**\n * @return {*|Boolean}\n */\n isCalculated: function () {\n return this.totals() && this.isFullMode() && totals.getSegment('tax') != null;\n },\n\n /**\n * @return {*}\n */\n getValue: function () {\n var amount;\n\n if (!this.isCalculated()) {\n return this.notCalculatedMessage;\n }\n amount = totals.getSegment('tax').value;\n\n return this.getFormattedPrice(amount);\n },\n\n /**\n * @param {*} amount\n * @return {*|String}\n */\n formatPrice: function (amount) {\n return this.getFormattedPrice(amount);\n },\n\n /**\n * @param {*} parent\n * @param {*} percentage\n * @return {*|String}\n */\n getTaxAmount: function (parent, percentage) {\n var totalPercentage = 0;\n\n taxAmount = parent.amount;\n rates = parent.rates;\n _.each(rates, function (rate) {\n totalPercentage += parseFloat(rate.percent);\n });\n\n return this.getFormattedPrice(this.getPercentAmount(taxAmount, totalPercentage, percentage));\n },\n\n /**\n * @param {*} amount\n * @param {*} totalPercentage\n * @param {*} percentage\n * @return {*|String}\n */\n getPercentAmount: function (amount, totalPercentage, percentage) {\n return parseFloat(amount * percentage / totalPercentage);\n },\n\n /**\n * @return {Array}\n */\n getDetails: function () {\n var taxSegment = totals.getSegment('tax');\n\n if (taxSegment && taxSegment['extension_attributes']) {\n return taxSegment['extension_attributes']['tax_grandtotal_details'];\n }\n\n return [];\n }\n });\n});\n","Magento_Tax/js/view/checkout/summary/subtotal.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'Magento_Checkout/js/view/summary/abstract-total',\n 'Magento_Checkout/js/model/quote'\n], function (Component, quote) {\n 'use strict';\n\n var displaySubtotalMode = window.checkoutConfig.reviewTotalsDisplayMode;\n\n return Component.extend({\n defaults: {\n displaySubtotalMode: displaySubtotalMode,\n template: 'Magento_Tax/checkout/summary/subtotal'\n },\n totals: quote.getTotals(),\n\n /**\n * @return {*|String}\n */\n getValue: function () {\n var price = 0;\n\n if (this.totals()) {\n price = this.totals().subtotal;\n }\n\n return this.getFormattedPrice(price);\n },\n\n /**\n * @return {Boolean}\n */\n isBothPricesDisplayed: function () {\n return this.displaySubtotalMode == 'both'; //eslint-disable-line eqeqeq\n },\n\n /**\n * @return {Boolean}\n */\n isIncludingTaxDisplayed: function () {\n return this.displaySubtotalMode == 'including'; //eslint-disable-line eqeqeq\n },\n\n /**\n * @return {*|String}\n */\n getValueInclTax: function () {\n var price = 0;\n\n if (this.totals()) {\n price = this.totals()['subtotal_incl_tax'];\n }\n\n return this.getFormattedPrice(price);\n }\n });\n});\n","Magento_Tax/js/view/checkout/summary/shipping.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'jquery',\n 'Magento_Checkout/js/view/summary/shipping',\n 'Magento_Checkout/js/model/quote'\n], function ($, Component, quote) {\n 'use strict';\n\n var displayMode = window.checkoutConfig.reviewShippingDisplayMode;\n\n return Component.extend({\n defaults: {\n displayMode: displayMode,\n template: 'Magento_Tax/checkout/summary/shipping'\n },\n\n /**\n * @return {Boolean}\n */\n isBothPricesDisplayed: function () {\n return this.displayMode == 'both'; //eslint-disable-line eqeqeq\n },\n\n /**\n * @return {Boolean}\n */\n isIncludingDisplayed: function () {\n return this.displayMode == 'including'; //eslint-disable-line eqeqeq\n },\n\n /**\n * @return {Boolean}\n */\n isExcludingDisplayed: function () {\n return this.displayMode == 'excluding'; //eslint-disable-line eqeqeq\n },\n\n /**\n * @return {*|Boolean}\n */\n isCalculated: function () {\n return this.totals() && this.isFullMode() && quote.shippingMethod() != null;\n },\n\n /**\n * @return {*}\n */\n getIncludingValue: function () {\n var price;\n\n if (!this.isCalculated()) {\n return this.notCalculatedMessage;\n }\n price = this.totals()['shipping_incl_tax'];\n\n return this.getFormattedPrice(price);\n },\n\n /**\n * @return {*}\n */\n getExcludingValue: function () {\n var price;\n\n if (!this.isCalculated()) {\n return this.notCalculatedMessage;\n }\n price = this.totals()['shipping_amount'];\n\n return this.getFormattedPrice(price);\n }\n });\n});\n","Magento_Tax/js/view/checkout/summary/grand-total.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'Magento_Checkout/js/view/summary/abstract-total',\n 'Magento_Checkout/js/model/quote',\n 'Magento_Catalog/js/price-utils',\n 'Magento_Checkout/js/model/totals'\n], function (Component, quote, priceUtils, totals) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n isFullTaxSummaryDisplayed: window.checkoutConfig.isFullTaxSummaryDisplayed || false,\n template: 'Magento_Tax/checkout/summary/grand-total'\n },\n totals: quote.getTotals(),\n isTaxDisplayedInGrandTotal: window.checkoutConfig.includeTaxInGrandTotal || false,\n\n /**\n * @return {*}\n */\n isDisplayed: function () {\n return this.isFullMode();\n },\n\n /**\n * @return {*|String}\n */\n getValue: function () {\n var price = 0;\n\n if (this.totals()) {\n price = totals.getSegment('grand_total').value;\n }\n\n return this.getFormattedPrice(price);\n },\n\n /**\n * @return {*|String}\n */\n getBaseValue: function () {\n var price = 0;\n\n if (this.totals()) {\n price = this.totals()['base_grand_total'];\n }\n\n return priceUtils.formatPriceLocale(price, quote.getBasePriceFormat());\n },\n\n /**\n * @return {*}\n */\n getGrandTotalExclTax: function () {\n var total = this.totals(),\n amount;\n\n if (!total) {\n return 0;\n }\n\n amount = total['grand_total'] - total['tax_amount'];\n\n if (amount < 0) {\n amount = 0;\n }\n\n return this.getFormattedPrice(amount);\n },\n\n /**\n * @return {Boolean}\n */\n isBaseGrandTotalDisplayNeeded: function () {\n var total = this.totals();\n\n if (!total) {\n return false;\n }\n\n return total['base_currency_code'] != total['quote_currency_code']; //eslint-disable-line eqeqeq\n }\n });\n});\n","Magento_Tax/js/view/checkout/summary/item/details/subtotal.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'Magento_Checkout/js/view/summary/item/details/subtotal'\n], function (subtotal) {\n 'use strict';\n\n var displayPriceMode = window.checkoutConfig.reviewItemPriceDisplayMode || 'including';\n\n return subtotal.extend({\n defaults: {\n displayPriceMode: displayPriceMode,\n template: 'Magento_Tax/checkout/summary/item/details/subtotal'\n },\n\n /**\n * @return {Boolean}\n */\n isPriceInclTaxDisplayed: function () {\n return displayPriceMode == 'both' || displayPriceMode == 'including'; //eslint-disable-line eqeqeq\n },\n\n /**\n * @return {Boolean}\n */\n isPriceExclTaxDisplayed: function () {\n return displayPriceMode == 'both' || displayPriceMode == 'excluding'; //eslint-disable-line eqeqeq\n },\n\n /**\n * @param {Object} quoteItem\n * @return {*|String}\n */\n getValueInclTax: function (quoteItem) {\n return this.getFormattedPrice(quoteItem['row_total_incl_tax']);\n },\n\n /**\n * @param {Object} quoteItem\n * @return {*|String}\n */\n getValueExclTax: function (quoteItem) {\n return this.getFormattedPrice(quoteItem['row_total']);\n }\n\n });\n});\n","Magento_Tax/js/view/checkout/shipping_method/price.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\n\ndefine([\n 'uiComponent',\n 'Magento_Checkout/js/model/quote',\n 'Magento_Catalog/js/price-utils'\n], function (Component, quote, priceUtils) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Tax/checkout/shipping_method/price'\n },\n isDisplayShippingPriceExclTax: window.checkoutConfig.isDisplayShippingPriceExclTax,\n isDisplayShippingBothPrices: window.checkoutConfig.isDisplayShippingBothPrices,\n\n /**\n * @param {Object} item\n * @return {Boolean}\n */\n isPriceEqual: function (item) {\n return item['price_excl_tax'] != item['price_incl_tax']; //eslint-disable-line eqeqeq\n },\n\n /**\n * @param {*} price\n * @return {*|String}\n */\n getFormattedPrice: function (price) {\n //todo add format data\n return priceUtils.formatPriceLocale(price, quote.getPriceFormat());\n }\n });\n});\n","Magento_Translation/js/add-class.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(['jquery'], function ($) {\n 'use strict';\n\n return function (config, element) {\n $(element).addClass(config.class);\n };\n});\n","Magento_Translation/js/i18n-config.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n(function () {\n 'use strict';\n\n require.config({\n config: {\n 'Magento_Ui/js/lib/knockout/bindings/i18n': {\n inlineTranslation: true\n }\n }\n });\n})();\n","Magento_Translation/js/mage-translation-dictionary.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'text!js-translation.json'\n], function (dict) {\n 'use strict';\n\n return JSON.parse(dict);\n});\n","Magento_CatalogSearch/js/search-terms-log.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'mageUtils'\n], function ($, utils) {\n 'use strict';\n\n return function (data) {\n $.ajax({\n method: 'GET',\n url: data.url,\n data: {\n 'q': utils.getUrlParameters(window.location.href).q\n }\n });\n };\n});\n","Amasty_Rewards/js/guest-highlight.js":"define([\n 'uiComponent',\n 'mage/translate',\n], function (Component, $t) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Amasty_Rewards/guest-highlight',\n captionStartText : $t('You can earn'),\n captionAfterText: '',\n captionRegistrationText: $t('for registration!'),\n captionEndText: '',\n frontend_class: '',\n highlight: []\n },\n\n initObservable: function () {\n this._super().observe([ 'highlight' ]);\n if (this.highlight._latestValue.need_to_change_message === 1) {\n this.captionAfterText = $t('for making a purchase! Available for');\n this.captionRegistrationText = $t('registered');\n this.captionEndText = $t('customers only.');\n }\n\n return this;\n }\n });\n});\n","Amasty_Rewards/js/amreward-points.js":"/*jshint browser:true jquery:true*/\ndefine([\n \"jquery\",\n \"Magento_Ui/js/modal/modal\"\n], function($){\n \"use strict\";\n\n $.widget('mage.amrewardPoints', {\n options: {\n },\n _create: function () {\n this.rewardAmount = $(this.options.rewardAmount);\n\n this.removeReward = $(this.options.removeRewardSelector);\n\n $(this.options.applyButton).on('click', $.proxy(function () {\n this.rewardAmount.attr('data-validate', '{required:true}');\n\n this.removeReward.attr('value', '0');\n $(this.element).validation().submit();\n }, this));\n\n $(this.options.cancelButton).on('click', $.proxy(function () {\n this.rewardAmount.removeAttr('data-validate');\n this.removeReward.attr('value', '1');\n this.element.submit();\n }, this));\n\n if (!this.isGreaterThanMinimumBalance()) {\n this.getMinimumRewardNoteDOM().show();\n this.disableRewardInput();\n\n }\n },\n\n /**\n *\n * @returns {boolean}\n */\n isGreaterThanMinimumBalance: function () {\n var realBalance = this.options.customerBalance;\n\n if (this.options.usedPoints) {\n realBalance += this.options.usedPoints;\n }\n\n return !this.options.minimumBalance || (realBalance >= this.options.minimumBalance);\n },\n\n /**\n * @return void\n */\n disableRewardInput: function() {\n $(this.options.applyButton).prop(\"disabled\", true);\n $(this.options.rewardAmount).prop(\"disabled\", true);\n },\n\n /**\n *\n * @returns {*|jQuery|HTMLElement}\n */\n getMinimumRewardNoteDOM: function() {\n return $(this.options.minimumNoteSelector);\n }\n });\n\n return $.mage.amrewardPoints;\n});\n","Amasty_Rewards/js/action/cancel-reward.js":"/**\n * Customer store credit(balance) application\n */\ndefine([\n 'jquery',\n 'Magento_Checkout/js/model/quote',\n 'Magento_Checkout/js/model/url-builder',\n 'Magento_Checkout/js/model/error-processor',\n 'Amasty_Rewards/js/model/payment/reward-messages',\n 'mage/storage',\n 'Magento_Checkout/js/action/get-payment-information',\n 'Magento_Checkout/js/model/totals',\n 'mage/translate',\n 'Magento_Checkout/js/model/full-screen-loader'\n], function ($, quote, urlBuilder, errorProcessor, messageContainer, storage, getPaymentInformationAction, totals, $t,\n fullScreenLoader\n) {\n 'use strict';\n\n return function (isApplied) {\n var url = urlBuilder.createUrl('/carts/mine/points/delete', {}),\n message = $t('You Canceled Reward.');\n\n messageContainer.clear();\n fullScreenLoader.startLoader();\n\n return storage.delete(\n url,\n false\n ).done(function () {\n var deferred = $.Deferred();\n\n totals.isLoading(true);\n getPaymentInformationAction(deferred);\n $.when(deferred).done(function () {\n isApplied(false);\n totals.isLoading(false);\n fullScreenLoader.stopLoader();\n });\n messageContainer.addSuccessMessage({\n 'message': message\n });\n }).fail(function (response) {\n totals.isLoading(false);\n fullScreenLoader.stopLoader();\n errorProcessor.process(response, messageContainer);\n });\n };\n});","Amasty_Rewards/js/action/add-reward.js":"define([\n 'ko',\n 'jquery',\n 'Magento_Checkout/js/model/quote',\n 'Amasty_Rewards/js/model/resource-url-manager',\n 'Magento_Checkout/js/model/error-processor',\n 'Amasty_Rewards/js/model/payment/reward-messages',\n 'mage/storage',\n 'mage/translate',\n 'Magento_Checkout/js/action/get-payment-information',\n 'Magento_Checkout/js/model/totals',\n 'Magento_Checkout/js/model/full-screen-loader'\n ], function (ko, $, quote, urlManager, errorProcessor, messageContainer,\n storage, $t, getPaymentInformationAction, totals, fullScreenLoader\n ) {\n 'use strict';\n return function (points, isApplied, pointsLeftObs, rateForCurrency, noticeMessage) {\n var quoteId = quote.getQuoteId(),\n url = urlManager.getRewardsUrl(points(), quoteId);\n\n messageContainer.clear();\n fullScreenLoader.startLoader();\n\n return storage.put(\n url,\n {},\n false\n ).done(function (response) {\n var deferred,\n pointsUsed = 0;\n\n if (response) {\n pointsUsed = response[1];\n noticeMessage($t(response[0]));\n $('[data-amrewards-js=\"notice-message\"]').show();\n setTimeout(function () {\n $('[data-amrewards-js=\"notice-message\"]').hide('blind', {}, 500);\n }, 5000);\n\n deferred = $.Deferred();\n\n if (pointsUsed > 0) {\n isApplied(true);\n totals.isLoading(true);\n getPaymentInformationAction(deferred);\n\n $.when(deferred).done(function () {\n points((pointsUsed).toFixed(2));\n pointsLeftObs((pointsLeftObs() - points()).toFixed(2));\n $('#amreward_amount').val(points()).change();\n\n fullScreenLoader.stopLoader();\n totals.isLoading(false);\n });\n }\n\n fullScreenLoader.stopLoader();\n }\n }).fail(function (response) {\n fullScreenLoader.stopLoader();\n totals.isLoading(false);\n errorProcessor.process(response, messageContainer);\n });\n };\n }\n);","Amasty_Rewards/js/view/balance.js":"define([\n 'uiComponent',\n 'Magento_Customer/js/customer-data'\n], function (Component, customerData) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n visible: false,\n balance: 0,\n captionText: false\n },\n\n initObservable: function () {\n this._super().observe('visible balance captionText');\n\n return this;\n },\n\n initialize: function () {\n this._super();\n var rewardsData = customerData.get('rewards');\n\n if (rewardsData().balance) {\n this.balance(rewardsData().balance);\n }\n\n rewardsData.subscribe(function (rewardsData) {\n this.balance(rewardsData.balance);\n }.bind(this));\n\n this.visible(true);\n },\n });\n});\n","Amasty_Rewards/js/view/checkout/payment/rewards.js":"define([\n 'jquery',\n 'underscore',\n 'uiComponent',\n 'Magento_Checkout/js/model/quote',\n 'Amasty_Rewards/js/action/add-reward',\n 'Amasty_Rewards/js/action/cancel-reward',\n 'Amasty_Rewards/vendor/tooltipster/js/tooltipster.min',\n 'Magento_Ui/js/model/messageList',\n 'mage/translate'\n], function (\n $,\n _,\n Component,\n quote,\n setRewardPointAction,\n cancelRewardPointAction,\n tooltipster,\n messageList,\n $t\n) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Amasty_Rewards/checkout/payment/rewards',\n isApplied: false,\n pointsUsed: 0,\n pointsLeft: 0,\n noticeMessage: '',\n minimumPointsValue: 0,\n disableElem: false,\n isRewardsTooltipEnabled: false,\n rewardsTooltipContent: '',\n selectors: {\n tooltipElement: '[data-amrewards-js=\"tooltip\"]'\n }\n },\n\n initObservable: function () {\n this._super();\n this.observe(['pointsUsed', 'pointsLeft', 'isApplied', 'noticeMessage', 'disableElem']);\n\n return this;\n },\n\n /**\n * @return {exports}\n */\n initialize: function () {\n this._super();\n this.isApplied(false);\n\n if (this.pointsUsed() > 0) {\n this.isApplied(true);\n }\n\n if (_.isUndefined(Number.parseFloat)) {\n Number.parseFloat = parseFloat;\n }\n\n if (this.getMinimumPointsValue() > this.pointsLeft() + Number.parseFloat(this.pointsUsed())) {\n this.disableElem(true);\n }\n\n this.initTooltip();\n\n return this;\n },\n\n /**\n * @return {*|Boolean}\n */\n isDisplayed: function () {\n return this.customerId;\n },\n\n /**\n * Coupon code application procedure\n */\n apply: function () {\n if (this.validate()) {\n setRewardPointAction(this.pointsUsed, this.isApplied, this.pointsLeft, this.rateForCurrency, this.noticeMessage);\n }\n },\n\n /**\n * Cancel using coupon\n */\n cancel: function () {\n cancelRewardPointAction(this.isApplied);\n this.pointsLeft((Number.parseFloat(this.pointsLeft()) + Number.parseFloat(this.pointsUsed())).toFixed(2));\n },\n\n /**\n *\n * @return {*}\n */\n getRewardsCount: function () {\n return this.pointsLeft();\n },\n\n /**\n *\n * @return {*}\n */\n getPointsRate: function () {\n return this.pointsRate;\n },\n\n /**\n *\n * @return {*}\n */\n getCurrentCurrency: function () {\n return this.currentCurrencyCode;\n },\n\n /**\n *\n * @return {*}\n */\n getRateForCurrency: function () {\n return this.rateForCurrency;\n },\n\n /**\n * @return {*}\n */\n getMinimumPointsValue: function () {\n return Number.parseFloat(this.minimumPointsValue);\n },\n\n /**\n * @return {Boolean}\n */\n canApply: function () {\n return !(this.disableElem() || this.isApplied());\n },\n\n /**\n * Coupon form validation\n *\n * @returns {Boolean}\n */\n validate: function () {\n var form = '#discount-reward-form',\n valueValid = (this.pointsLeft() - this.pointsUsed() >= 0) && this.pointsUsed() > 0;\n\n if ($(form).validation() && $(form).validation('isValid') && valueValid) {\n return true;\n }\n\n messageList.addErrorMessage({\n message: $t('Points \"' + this.pointsUsed() +'\" not valid.')\n });\n\n return false;\n },\n\n initTooltip: function () {\n var tooltipTrigger = this.isTouchDevice() ? 'click' : 'hover';\n\n if (!this.isRewardsTooltipEnabled) {\n return;\n }\n\n $.async(this.selectors.tooltipElement, function () {\n $(this.selectors.tooltipElement).tooltipster({\n position: 'right',\n contentAsHtml: true,\n interactive: true,\n trigger: tooltipTrigger\n });\n }.bind(this));\n },\n\n isTouchDevice: function () {\n return ('ontouchstart' in window)\n || (navigator.maxTouchPoints > 0)\n || (navigator.msMaxTouchPoints > 0);\n }\n });\n});\n","Amasty_Rewards/js/view/checkout/payment/reward-messages.js":"define([\n 'Magento_Ui/js/view/messages',\n 'Amasty_Rewards/js/model/payment/reward-messages'\n], function (Component, messageContainer) {\n 'use strict';\n\n return Component.extend({\n /** @inheritdoc */\n initialize: function (config) {\n return this._super(config, messageContainer);\n }\n });\n});","Amasty_Rewards/js/model/resource-url-manager.js":"define([\n 'Magento_Customer/js/model/customer',\n 'Magento_Checkout/js/model/url-builder',\n 'mageUtils',\n 'mage/url',\n 'mage/translate'\n ], function (customer, urlBuilder, utils, url, $t) {\n 'use strict';\n\n return {\n\n /**\n * @param {String} points\n * @return {*}\n */\n getRewardsUrl: function (points) {\n var params = {},\n url = {\n 'customer': '/carts/mine/points/' + encodeURIComponent(points)\n };\n\n return this.getUrl(url, params);\n },\n\n /**\n * @return {String}\n */\n getCheckoutMethod: function () {\n return 'customer';\n },\n\n /**\n * Get url for service.\n *\n * @param {*} url\n * @param {*} urlParams\n * @return {String|*}\n */\n getUrl: function (url, urlParams) {\n var finalUrl;\n\n if (utils.isEmpty(url)) {\n return $t('Provided service call does not exist.');\n }\n\n if (!utils.isEmpty(url['default'])) {\n finalUrl = url['default'];\n } else {\n finalUrl = url[this.getCheckoutMethod()];\n }\n\n return urlBuilder.createUrl(finalUrl, urlParams);\n }\n };\n }\n);\n","Amasty_Rewards/js/model/totals/highlight.js":"define([\n 'uiComponent',\n 'Magento_Checkout/js/model/totals',\n 'mage/translate',\n], function (Component, totals, $t) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Amasty_Rewards/highlight',\n captionEndText: $t('for completing your purchase!'),\n captionStartText : $t('You can earn'),\n frontend_class: '',\n highlight: []\n },\n\n /**\n * @return {Object}\n */\n initObservable: function () {\n this._super().observe(['highlight']);\n totals.totals.subscribe(this.getHighlightData.bind(this));\n\n return this;\n },\n\n /**\n * @param totals {Object}\n * @return {void}\n */\n getHighlightData: function (totals) {\n let totalsAttributes = totals.extension_attributes;\n\n if (totalsAttributes && totalsAttributes.amasty_rewards_highlight) {\n this.highlight(totalsAttributes.amasty_rewards_highlight);\n } else {\n this.highlight({'visible': false});\n }\n },\n });\n});\n","Amasty_Rewards/js/model/payment/reward-messages.js":"define([\n 'Magento_Ui/js/model/messages'\n], function (Messages) {\n 'use strict';\n\n return new Messages();\n});","Amasty_Rewards/js/model/catalog/highlight-product.js":"define([\n 'jquery',\n 'uiComponent',\n 'mage/translate',\n 'mage/storage',\n], function ($, Component, $t, storage) {\n 'use strict';\n var xhr = null;\n\n return Component.extend({\n defaults: {\n template: 'Amasty_Rewards/highlight',\n captionEndText: $t('for buying this product!'),\n captionStartText : $t('You can earn'),\n productId : 0,\n refreshUrl: false,\n loader: false,\n formSelector: '#product_addtocart_form',\n frontend_class: '',\n highlight: {\n visible: false\n }\n },\n\n initObservable: function () {\n this._super().observe(['highlight', 'loader']);\n this.updateData();\n $(this.formSelector).change(this.updateData.bind(this));\n\n return this;\n },\n\n hide: function () {\n this.highlight({'visible':false});\n\n return this;\n },\n\n updateData: function () {\n if (xhr) {\n xhr.abort();\n }\n this.hide().loader(true);\n\n xhr = storage.post(this.refreshUrl,\n JSON.stringify({\n productId: this.productId,\n attributes: $(this.formSelector).serialize()\n }),\n false\n ).done(function (result) {\n if (result) {\n this.highlight(result);\n }\n }.bind(this)).always(function () {\n this.loader(false);\n xhr = null;\n }.bind(this));\n },\n });\n});\n","Amasty_Rewards/js/model/catalog/highlight-category.js":"define([\n 'jquery',\n 'uiComponent',\n 'mage/translate',\n 'mage/storage',\n], function ($, Component, $t, storage) {\n 'use strict';\n var xhr = {};\n\n return Component.extend({\n defaults: {\n template: 'Amasty_Rewards/highlight-category',\n captionEndText: '',\n captionStartText: $t('Earn'),\n productId: 0,\n refreshUrl: false,\n loader: false,\n formSelector: false,\n frontend_class: '',\n highlight: {\n visible: false\n }\n },\n\n initObservable: function () {\n this._super().observe(['highlight', 'loader']);\n\n if (this.refreshUrl) {\n this.updateData();\n $(this.formSelector).change(this.updateData.bind(this));\n }\n\n return this;\n },\n\n hide: function () {\n this.highlight({'visible': false});\n\n return this;\n },\n\n updateData: function () {\n if (xhr.hasOwnProperty(this.productId)) {\n xhr[this.productId].abort();\n }\n this.hide().loader(true);\n\n xhr[this.productId] = storage.post(this.refreshUrl,\n JSON.stringify({\n productId: this.productId,\n attributes: $(this.formSelector).serialize()\n }),\n false\n ).done(function (result) {\n if (result) {\n this.highlight(result);\n }\n }.bind(this)).always(function () {\n this.loader(false);\n delete xhr[this.productId];\n }.bind(this));\n },\n });\n});\n","Amasty_Rewards/js/model/catalog/guest-highlight-category.js":"define([\n 'jquery',\n 'uiComponent',\n 'mage/translate',\n 'mage/storage',\n], function ($, Component, $t, storage) {\n 'use strict';\n var xhr = {};\n\n return Component.extend({\n defaults: {\n template: 'Amasty_Rewards/guest-highlight',\n captionStartText: $t('You can earn'),\n captionAfterText: '',\n captionRegistrationText: $t('for registration!'),\n captionEndText: '',\n productId: 0,\n refreshUrl: false,\n loader: false,\n formSelector: false,\n frontend_class: '',\n highlight: {\n visible: false\n }\n },\n\n initObservable: function () {\n this._super().observe([ 'highlight', 'loader' ]);\n\n if (this.refreshUrl) {\n this.updateData();\n $(this.formSelector).change(this.updateData.bind(this));\n }\n\n return this;\n },\n\n hide: function () {\n this.highlight({ 'visible': false });\n\n return this;\n },\n\n updateData: function () {\n if (xhr.hasOwnProperty(this.productId)) {\n xhr[this.productId].abort();\n }\n this.hide().loader(true);\n\n xhr[this.productId] = storage.post(this.refreshUrl,\n JSON.stringify({\n page: 3,\n productId: this.productId,\n attributes: $(this.formSelector).serialize()\n }),\n false\n ).done(function (result) {\n if (result) {\n if (result.need_to_change_message === 1) {\n this.captionAfterText = $t('for making a purchase! Available for');\n this.captionRegistrationText = $t('registered');\n this.captionEndText = $t('customers only.');\n }\n this.highlight(result);\n }\n }.bind(this)).always(function () {\n this.loader(false);\n delete xhr[this.productId];\n }.bind(this));\n }\n });\n});\n","Amasty_Rewards/js/model/catalog/guest-highlight-product.js":"define([\n 'jquery',\n 'uiComponent',\n 'mage/translate',\n 'mage/storage',\n], function ($, Component, $t, storage) {\n 'use strict';\n var xhr = null;\n\n return Component.extend({\n defaults: {\n template: 'Amasty_Rewards/guest-highlight',\n captionStartText: $t('You can earn'),\n captionAfterText: '',\n captionRegistrationText: $t('for registration!'),\n captionEndText: '',\n productId: 0,\n refreshUrl: false,\n loader: false,\n formSelector: '#product_addtocart_form',\n frontend_class: '',\n highlight: {\n visible: false\n }\n },\n\n initObservable: function () {\n this._super().observe([ 'highlight', 'loader' ]);\n this.updateData();\n $(this.formSelector).change(this.updateData.bind(this));\n\n return this;\n },\n\n hide: function () {\n this.highlight({ 'visible':false });\n\n return this;\n },\n\n updateData: function () {\n if (xhr) {\n xhr.abort();\n }\n this.hide().loader(true);\n\n xhr = storage.post(this.refreshUrl,\n JSON.stringify({\n page: 0,\n productId: this.productId,\n attributes: $(this.formSelector).serialize()\n }),\n false\n ).done(function (result) {\n if (result) {\n if (result.need_to_change_message === 1) {\n this.captionAfterText = $t('for making a purchase! Available for');\n this.captionRegistrationText = $t('registered');\n this.captionEndText = $t('customers only.');\n }\n this.highlight(result);\n }\n }.bind(this)).always(function () {\n this.loader(false);\n xhr = null;\n }.bind(this));\n }\n });\n});\n","Amasty_Rewards/vendor/tooltipster/js/tooltipster.min.js":"!function(t,i){\"function\"==typeof define&&define.amd?define([\"jquery\"],function(t){return i(t)}):\"object\"==typeof exports?module.exports=i(require(\"jquery\")):i(jQuery)}(0,function(t){var i={animation:\"fade\",animationDuration:350,content:null,contentAsHTML:!1,contentCloning:!1,debug:!0,delay:300,delayTouch:[300,500],functionInit:null,functionBefore:null,functionReady:null,functionAfter:null,functionFormat:null,IEmin:6,interactive:!1,multiple:!1,parent:null,plugins:[\"sideTip\"],repositionOnScroll:!1,restoration:\"none\",selfDestruction:!0,theme:[],timer:0,trackerInterval:500,trackOrigin:!1,trackTooltip:!1,trigger:\"hover\",triggerClose:{click:!1,mouseleave:!1,originClick:!1,scroll:!1,tap:!1,touchleave:!1},triggerOpen:{click:!1,mouseenter:!1,tap:!1,touchstart:!1},updateAnimation:\"rotate\",zIndex:9999999,styles:{backgroundColor:\"\",textColor:\"\"}},o=\"undefined\"!=typeof window?window:null,e={hasTouchCapability:!(!o||!(\"ontouchstart\"in o||o.DocumentTouch&&o.document instanceof o.DocumentTouch||o.navigator.maxTouchPoints)),hasTransitions:function(){if(!o)return!1;var t=(o.document.body||o.document.documentElement).style,i=\"transition\",e=[\"Moz\",\"Webkit\",\"Khtml\",\"O\",\"ms\"];if(\"string\"==typeof t[i])return!0;i=i.charAt(0).toUpperCase()+i.substr(1);for(var n=0;n<e.length;n++)if(\"string\"==typeof t[e[n]+i])return!0;return!1}(),IE:!1,semVer:\"4.2.8\",window:o},n=function(){this.__$emitterPrivate=t({}),this.__$emitterPublic=t({}),this.__instancesLatestArr=[],this.__plugins={},this._env=e};function s(t){this.$container,this.constraints=null,this.__$tooltip,this.__init(t)}function r(i,o){var e=!0;return t.each(i,function(t,n){if(void 0===o[t]||i[t]!==o[t])return e=!1,!1}),e}function _(i){var o=i.attr(\"id\"),n=o?e.window.document.getElementById(o):null;return n?n===i[0]:t.contains(e.window.document.body,i[0])}n.prototype={__bridge:function(o,e,n){if(!e[n]){var s=function(){};s.prototype=o;var r=new s;r.__init&&r.__init(e),t.each(o,function(t,o){0!=t.indexOf(\"__\")&&(e[t]?i.debug&&console.log(\"The \"+t+\" method of the \"+n+\" plugin conflicts with another plugin or native methods\"):(e[t]=function(){return r[t].apply(r,Array.prototype.slice.apply(arguments))},e[t].bridged=r))}),e[n]=r}return this},__setWindow:function(t){return e.window=t,this},_getRuler:function(t){return new s(t)},_off:function(){return this.__$emitterPrivate.off.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_on:function(){return this.__$emitterPrivate.on.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_one:function(){return this.__$emitterPrivate.one.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_plugin:function(i){if(\"string\"==typeof i){var o=i,e=null;return o.indexOf(\".\")>0?e=this.__plugins[o]:t.each(this.__plugins,function(t,i){if(i.name.substring(i.name.length-o.length-1)==\".\"+o)return e=i,!1}),e}if(i.name.indexOf(\".\")<0)throw new Error(\"Plugins must be namespaced\");return this.__plugins[i.name]=i,i.core&&this.__bridge(i.core,this,i.name),this},_trigger:function(){var t=Array.prototype.slice.apply(arguments);return\"string\"==typeof t[0]&&(t[0]={type:t[0]}),this.__$emitterPrivate.trigger.apply(this.__$emitterPrivate,t),this.__$emitterPublic.trigger.apply(this.__$emitterPublic,t),this},instances:function(i){var o=[];return t(i||\".tooltipstered\").each(function(){var i=t(this),e=i.data(\"tooltipster-ns\");e&&t.each(e,function(t,e){o.push(i.data(e))})}),o},instancesLatest:function(){return this.__instancesLatestArr},off:function(){return this.__$emitterPublic.off.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},on:function(){return this.__$emitterPublic.on.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},one:function(){return this.__$emitterPublic.one.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},origins:function(i){return t((i?i+\" \":\"\")+\".tooltipstered\").toArray()},setDefaults:function(o){return t.extend(i,o),this},triggerHandler:function(){return this.__$emitterPublic.triggerHandler.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this}},t.tooltipster=new n,t.Tooltipster=function(i,o){this.__callbacks={close:[],open:[]},this.__closingTime,this.__Content,this.__contentBcr,this.__destroyed=!1,this.__$emitterPrivate=t({}),this.__$emitterPublic=t({}),this.__enabled=!0,this.__garbageCollector,this.__Geometry,this.__lastPosition,this.__namespace=\"tooltipster-\"+Math.round(1e6*Math.random()),this.__options,this.__$originParents,this.__pointerIsOverOrigin=!1,this.__previousThemes=[],this.__state=\"closed\",this.__timeouts={close:[],open:null},this.__touchEvents=[],this.__tracker=null,this._$origin,this._$tooltip,this.__init(i,o)},t.Tooltipster.prototype={__init:function(o,n){var s=this;if(s._$origin=t(o),s.__options=t.extend(!0,{},i,n),s.__optionsFormat(),!e.IE||e.IE>=s.__options.IEmin){var r=null;if(void 0===s._$origin.data(\"tooltipster-initialTitle\")&&(void 0===(r=s._$origin.attr(\"title\"))&&(r=null),s._$origin.data(\"tooltipster-initialTitle\",r)),null!==s.__options.content)s.__contentSet(s.__options.content);else{var _,a=s._$origin.attr(\"data-tooltip-content\");a&&(_=t(a)),_&&_[0]?s.__contentSet(_.first()):s.__contentSet(r)}s._$origin.removeAttr(\"title\").addClass(\"tooltipstered\"),s.__prepareOrigin(),s.__prepareGC(),t.each(s.__options.plugins,function(t,i){s._plug(i)}),e.hasTouchCapability&&t(e.window.document.body).on(\"touchmove.\"+s.__namespace+\"-triggerOpen\",function(t){s._touchRecordEvent(t)}),s._on(\"created\",function(){s.__prepareTooltip()})._on(\"repositioned\",function(t){s.__lastPosition=t.position})}else s.__options.disabled=!0},__contentInsert:function(){var t=this._$tooltip.find(\".tooltipster-content\"),i=this.__Content;return this._trigger({type:\"format\",content:this.__Content,format:function(t){i=t}}),this.__options.functionFormat&&(i=this.__options.functionFormat.call(this,this,{origin:this._$origin[0]},this.__Content)),\"string\"!=typeof i||this.__options.contentAsHTML?t.empty().append(i):t.text(i),this},__contentSet:function(i){return i instanceof t&&this.__options.contentCloning&&(i=i.clone(!0)),this.__Content=i,this._trigger({type:\"updated\",content:i}),this},__destroyError:function(){throw new Error(\"This tooltip has been destroyed and cannot execute your method call.\")},__geometry:function(){var i=this._$origin,o=this._$origin.is(\"area\");if(o){var n=this._$origin.parent().attr(\"name\");i=t('img[usemap=\"#'+n+'\"]')}var s=i[0].getBoundingClientRect(),r=t(e.window.document),_=t(e.window),a=i,l={available:{document:null,window:null},document:{size:{height:r.height(),width:r.width()}},window:{scroll:{left:e.window.scrollX||e.window.document.documentElement.scrollLeft,top:e.window.scrollY||e.window.document.documentElement.scrollTop},size:{height:_.height(),width:_.width()}},origin:{fixedLineage:!1,offset:{},size:{height:s.bottom-s.top,width:s.right-s.left},usemapImage:o?i[0]:null,windowOffset:{bottom:s.bottom,left:s.left,right:s.right,top:s.top}}};if(o){var p=this._$origin.attr(\"shape\"),c=this._$origin.attr(\"coords\");if(c&&(c=c.split(\",\"),t.map(c,function(t,i){c[i]=parseInt(t)})),\"default\"!=p)switch(p){case\"circle\":var h=c[0],d=c[1],u=c[2],g=d-u,f=h-u;l.origin.size.height=2*u,l.origin.size.width=l.origin.size.height,l.origin.windowOffset.left+=f,l.origin.windowOffset.top+=g;break;case\"rect\":var m=c[0],w=c[1],v=c[2],y=c[3];l.origin.size.height=y-w,l.origin.size.width=v-m,l.origin.windowOffset.left+=m,l.origin.windowOffset.top+=w;break;case\"poly\":for(var b=0,$=0,C=0,O=0,T=\"even\",z=0;z<c.length;z++){var E=c[z];\"even\"==T?(E>C&&(C=E,0===z&&(b=C)),E<b&&(b=E),T=\"odd\"):(E>O&&(O=E,1==z&&($=O)),E<$&&($=E),T=\"even\")}l.origin.size.height=O-$,l.origin.size.width=C-b,l.origin.windowOffset.left+=b,l.origin.windowOffset.top+=$}}for(this._trigger({type:\"geometry\",edit:function(t){l.origin.size.height=t.height,l.origin.windowOffset.left=t.left,l.origin.windowOffset.top=t.top,l.origin.size.width=t.width},geometry:{height:l.origin.size.height,left:l.origin.windowOffset.left,top:l.origin.windowOffset.top,width:l.origin.size.width}}),l.origin.windowOffset.right=l.origin.windowOffset.left+l.origin.size.width,l.origin.windowOffset.bottom=l.origin.windowOffset.top+l.origin.size.height,l.origin.offset.left=l.origin.windowOffset.left+l.window.scroll.left,l.origin.offset.top=l.origin.windowOffset.top+l.window.scroll.top,l.origin.offset.bottom=l.origin.offset.top+l.origin.size.height,l.origin.offset.right=l.origin.offset.left+l.origin.size.width,l.available.document={bottom:{height:l.document.size.height-l.origin.offset.bottom,width:l.document.size.width},left:{height:l.document.size.height,width:l.origin.offset.left},right:{height:l.document.size.height,width:l.document.size.width-l.origin.offset.right},top:{height:l.origin.offset.top,width:l.document.size.width}},l.available.window={bottom:{height:Math.max(l.window.size.height-Math.max(l.origin.windowOffset.bottom,0),0),width:l.window.size.width},left:{height:l.window.size.height,width:Math.max(l.origin.windowOffset.left,0)},right:{height:l.window.size.height,width:Math.max(l.window.size.width-Math.max(l.origin.windowOffset.right,0),0)},top:{height:Math.max(l.origin.windowOffset.top,0),width:l.window.size.width}};\"html\"!=a[0].tagName.toLowerCase();){if(\"fixed\"==a.css(\"position\")){l.origin.fixedLineage=!0;break}a=a.parent()}return l},__optionsFormat:function(){return\"number\"==typeof this.__options.animationDuration&&(this.__options.animationDuration=[this.__options.animationDuration,this.__options.animationDuration]),\"number\"==typeof this.__options.delay&&(this.__options.delay=[this.__options.delay,this.__options.delay]),\"number\"==typeof this.__options.delayTouch&&(this.__options.delayTouch=[this.__options.delayTouch,this.__options.delayTouch]),\"string\"==typeof this.__options.theme&&(this.__options.theme=[this.__options.theme]),null===this.__options.parent?this.__options.parent=t(e.window.document.body):\"string\"==typeof this.__options.parent&&(this.__options.parent=t(this.__options.parent)),\"hover\"==this.__options.trigger?(this.__options.triggerOpen={mouseenter:!0,touchstart:!0},this.__options.triggerClose={mouseleave:!0,originClick:!0,touchleave:!0}):\"click\"==this.__options.trigger&&(this.__options.triggerOpen={click:!0,tap:!0},this.__options.triggerClose={click:!0,tap:!0}),this._trigger(\"options\"),this},__prepareGC:function(){var i=this;return i.__options.selfDestruction?i.__garbageCollector=setInterval(function(){var o=(new Date).getTime();i.__touchEvents=t.grep(i.__touchEvents,function(t,i){return o-t.time>6e4}),_(i._$origin)||i.close(function(){i.destroy()})},2e4):clearInterval(i.__garbageCollector),i},__prepareOrigin:function(){var t=this;if(t._$origin.off(\".\"+t.__namespace+\"-triggerOpen\"),e.hasTouchCapability&&t._$origin.on(\"touchstart.\"+t.__namespace+\"-triggerOpen touchend.\"+t.__namespace+\"-triggerOpen touchcancel.\"+t.__namespace+\"-triggerOpen\",function(i){t._touchRecordEvent(i)}),t.__options.triggerOpen.click||t.__options.triggerOpen.tap&&e.hasTouchCapability){var i=\"\";t.__options.triggerOpen.click&&(i+=\"click.\"+t.__namespace+\"-triggerOpen \"),t.__options.triggerOpen.tap&&e.hasTouchCapability&&(i+=\"touchend.\"+t.__namespace+\"-triggerOpen\"),t._$origin.on(i,function(i){t._touchIsMeaningfulEvent(i)&&t._open(i)})}if(t.__options.triggerOpen.mouseenter||t.__options.triggerOpen.touchstart&&e.hasTouchCapability){i=\"\";t.__options.triggerOpen.mouseenter&&(i+=\"mouseenter.\"+t.__namespace+\"-triggerOpen \"),t.__options.triggerOpen.touchstart&&e.hasTouchCapability&&(i+=\"touchstart.\"+t.__namespace+\"-triggerOpen\"),t._$origin.on(i,function(i){!t._touchIsTouchEvent(i)&&t._touchIsEmulatedEvent(i)||(t.__pointerIsOverOrigin=!0,t._openShortly(i))})}if(t.__options.triggerClose.mouseleave||t.__options.triggerClose.touchleave&&e.hasTouchCapability){i=\"\";t.__options.triggerClose.mouseleave&&(i+=\"mouseleave.\"+t.__namespace+\"-triggerOpen \"),t.__options.triggerClose.touchleave&&e.hasTouchCapability&&(i+=\"touchend.\"+t.__namespace+\"-triggerOpen touchcancel.\"+t.__namespace+\"-triggerOpen\"),t._$origin.on(i,function(i){t._touchIsMeaningfulEvent(i)&&(t.__pointerIsOverOrigin=!1)})}return t},__prepareTooltip:function(){var i=this,o=i.__options.interactive?\"auto\":\"\";return i._$tooltip.attr(\"id\",i.__namespace).css({\"pointer-events\":o,zIndex:i.__options.zIndex}),t.each(i.__previousThemes,function(t,o){i._$tooltip.removeClass(o)}),t.each(i.__options.theme,function(t,o){i._$tooltip.addClass(o)}),i.__previousThemes=t.merge([],i.__options.theme),i},__scrollHandler:function(i){if(this.__options.triggerClose.scroll)this._close(i);else if(_(this._$origin)&&_(this._$tooltip)){var o=null;if(i.target===e.window.document)this.__Geometry.origin.fixedLineage||this.__options.repositionOnScroll&&this.reposition(i);else{o=this.__geometry();var n=!1;if(\"fixed\"!=this._$origin.css(\"position\")&&this.__$originParents.each(function(i,e){var s=t(e),r=s.css(\"overflow-x\"),_=s.css(\"overflow-y\");if(\"visible\"!=r||\"visible\"!=_){var a=e.getBoundingClientRect();if(\"visible\"!=r&&(o.origin.windowOffset.left<a.left||o.origin.windowOffset.right>a.right))return n=!0,!1;if(\"visible\"!=_&&(o.origin.windowOffset.top<a.top||o.origin.windowOffset.bottom>a.bottom))return n=!0,!1}if(\"fixed\"==s.css(\"position\"))return!1}),n)this._$tooltip.css(\"visibility\",\"hidden\");else if(this._$tooltip.css(\"visibility\",\"visible\"),this.__options.repositionOnScroll)this.reposition(i);else{var s=o.origin.offset.left-this.__Geometry.origin.offset.left,r=o.origin.offset.top-this.__Geometry.origin.offset.top;this._$tooltip.css({left:this.__lastPosition.coord.left+s,top:this.__lastPosition.coord.top+r})}}this._trigger({type:\"scroll\",event:i,geo:o})}return this},__stateSet:function(t){return this.__state=t,this._trigger({type:\"state\",state:t}),this},__timeoutsClear:function(){return clearTimeout(this.__timeouts.open),this.__timeouts.open=null,t.each(this.__timeouts.close,function(t,i){clearTimeout(i)}),this.__timeouts.close=[],this},__trackerStart:function(){var t=this,i=t._$tooltip.find(\".tooltipster-content\");return t.__options.trackTooltip&&(t.__contentBcr=i[0].getBoundingClientRect()),t.__tracker=setInterval(function(){if(_(t._$origin)&&_(t._$tooltip)){if(t.__options.trackOrigin){var o=t.__geometry(),e=!1;r(o.origin.size,t.__Geometry.origin.size)&&(t.__Geometry.origin.fixedLineage?r(o.origin.windowOffset,t.__Geometry.origin.windowOffset)&&(e=!0):r(o.origin.offset,t.__Geometry.origin.offset)&&(e=!0)),e||(t.__options.triggerClose.mouseleave?t._close():t.reposition())}if(t.__options.trackTooltip){var n=i[0].getBoundingClientRect();n.height===t.__contentBcr.height&&n.width===t.__contentBcr.width||(t.reposition(),t.__contentBcr=n)}}else t._close()},t.__options.trackerInterval),t},_close:function(i,o,n){var s=this,r=!0;if(s._trigger({type:\"close\",event:i,stop:function(){r=!1}}),r||n){o&&s.__callbacks.close.push(o),s.__callbacks.open=[],s.__timeoutsClear();var _=function(){t.each(s.__callbacks.close,function(t,o){o.call(s,s,{event:i,origin:s._$origin[0]})}),s.__callbacks.close=[]};if(\"closed\"!=s.__state){var a=!0,l=(new Date).getTime()+s.__options.animationDuration[1];if(\"disappearing\"==s.__state&&l>s.__closingTime&&s.__options.animationDuration[1]>0&&(a=!1),a){s.__closingTime=l,\"disappearing\"!=s.__state&&s.__stateSet(\"disappearing\");var p=function(){clearInterval(s.__tracker),s._trigger({type:\"closing\",event:i}),s._$tooltip.off(\".\"+s.__namespace+\"-triggerClose\").removeClass(\"tooltipster-dying\"),t(e.window).off(\".\"+s.__namespace+\"-triggerClose\"),s.__$originParents.each(function(i,o){t(o).off(\"scroll.\"+s.__namespace+\"-triggerClose\")}),s.__$originParents=null,t(e.window.document.body).off(\".\"+s.__namespace+\"-triggerClose\"),s._$origin.off(\".\"+s.__namespace+\"-triggerClose\"),s._off(\"dismissable\"),s.__stateSet(\"closed\"),s._trigger({type:\"after\",event:i}),s.__options.functionAfter&&s.__options.functionAfter.call(s,s,{event:i,origin:s._$origin[0]}),_()};e.hasTransitions?(s._$tooltip.css({\"-moz-animation-duration\":s.__options.animationDuration[1]+\"ms\",\"-ms-animation-duration\":s.__options.animationDuration[1]+\"ms\",\"-o-animation-duration\":s.__options.animationDuration[1]+\"ms\",\"-webkit-animation-duration\":s.__options.animationDuration[1]+\"ms\",\"animation-duration\":s.__options.animationDuration[1]+\"ms\",\"transition-duration\":s.__options.animationDuration[1]+\"ms\"}),s._$tooltip.clearQueue().removeClass(\"tooltipster-show\").addClass(\"tooltipster-dying\"),s.__options.animationDuration[1]>0&&s._$tooltip.delay(s.__options.animationDuration[1]),s._$tooltip.queue(p)):s._$tooltip.stop().fadeOut(s.__options.animationDuration[1],p)}}else _()}return s},_off:function(){return this.__$emitterPrivate.off.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_on:function(){return this.__$emitterPrivate.on.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_one:function(){return this.__$emitterPrivate.one.apply(this.__$emitterPrivate,Array.prototype.slice.apply(arguments)),this},_open:function(i,o){var n=this;if(!n.__destroying&&_(n._$origin)&&n.__enabled){var s=!0;if(\"closed\"==n.__state&&(n._trigger({type:\"before\",event:i,stop:function(){s=!1}}),s&&n.__options.functionBefore&&(s=n.__options.functionBefore.call(n,n,{event:i,origin:n._$origin[0]}))),!1!==s&&null!==n.__Content){o&&n.__callbacks.open.push(o),n.__callbacks.close=[],n.__timeoutsClear();var r,a=function(){\"stable\"!=n.__state&&n.__stateSet(\"stable\"),t.each(n.__callbacks.open,function(t,i){i.call(n,n,{origin:n._$origin[0],tooltip:n._$tooltip[0]})}),n.__callbacks.open=[]};if(\"closed\"!==n.__state)r=0,\"disappearing\"===n.__state?(n.__stateSet(\"appearing\"),e.hasTransitions?(n._$tooltip.clearQueue().removeClass(\"tooltipster-dying\").addClass(\"tooltipster-show\"),n.__options.animationDuration[0]>0&&n._$tooltip.delay(n.__options.animationDuration[0]),n._$tooltip.queue(a)):n._$tooltip.stop().fadeIn(a)):\"stable\"==n.__state&&a();else{if(n.__stateSet(\"appearing\"),r=n.__options.animationDuration[0],n.__contentInsert(),n.reposition(i,!0),e.hasTransitions?(n._$tooltip.addClass(\"tooltipster-\"+n.__options.animation).addClass(\"tooltipster-initial\").css({\"-moz-animation-duration\":n.__options.animationDuration[0]+\"ms\",\"-ms-animation-duration\":n.__options.animationDuration[0]+\"ms\",\"-o-animation-duration\":n.__options.animationDuration[0]+\"ms\",\"-webkit-animation-duration\":n.__options.animationDuration[0]+\"ms\",\"animation-duration\":n.__options.animationDuration[0]+\"ms\",\"transition-duration\":n.__options.animationDuration[0]+\"ms\"}),setTimeout(function(){\"closed\"!=n.__state&&(n._$tooltip.addClass(\"tooltipster-show\").removeClass(\"tooltipster-initial\"),n.__options.animationDuration[0]>0&&n._$tooltip.delay(n.__options.animationDuration[0]),n._$tooltip.queue(a))},0)):n._$tooltip.css(\"display\",\"none\").fadeIn(n.__options.animationDuration[0],a),n.__trackerStart(),t(e.window).on(\"resize.\"+n.__namespace+\"-triggerClose\",function(i){var o=t(document.activeElement);(o.is(\"input\")||o.is(\"textarea\"))&&t.contains(n._$tooltip[0],o[0])||n.reposition(i)}).on(\"scroll.\"+n.__namespace+\"-triggerClose\",function(t){n.__scrollHandler(t)}),n.__$originParents=n._$origin.parents(),n.__$originParents.each(function(i,o){t(o).on(\"scroll.\"+n.__namespace+\"-triggerClose\",function(t){n.__scrollHandler(t)})}),n.__options.triggerClose.mouseleave||n.__options.triggerClose.touchleave&&e.hasTouchCapability){n._on(\"dismissable\",function(t){t.dismissable?t.delay?(h=setTimeout(function(){n._close(t.event)},t.delay),n.__timeouts.close.push(h)):n._close(t):clearTimeout(h)});var l=n._$origin,p=\"\",c=\"\",h=null;n.__options.interactive&&(l=l.add(n._$tooltip)),n.__options.triggerClose.mouseleave&&(p+=\"mouseenter.\"+n.__namespace+\"-triggerClose \",c+=\"mouseleave.\"+n.__namespace+\"-triggerClose \"),n.__options.triggerClose.touchleave&&e.hasTouchCapability&&(p+=\"touchstart.\"+n.__namespace+\"-triggerClose\",c+=\"touchend.\"+n.__namespace+\"-triggerClose touchcancel.\"+n.__namespace+\"-triggerClose\"),l.on(c,function(t){if(n._touchIsTouchEvent(t)||!n._touchIsEmulatedEvent(t)){var i=\"mouseleave\"==t.type?n.__options.delay:n.__options.delayTouch;n._trigger({delay:i[1],dismissable:!0,event:t,type:\"dismissable\"})}}).on(p,function(t){!n._touchIsTouchEvent(t)&&n._touchIsEmulatedEvent(t)||n._trigger({dismissable:!1,event:t,type:\"dismissable\"})})}n.__options.triggerClose.originClick&&n._$origin.on(\"click.\"+n.__namespace+\"-triggerClose\",function(t){n._touchIsTouchEvent(t)||n._touchIsEmulatedEvent(t)||n._close(t)}),(n.__options.triggerClose.click||n.__options.triggerClose.tap&&e.hasTouchCapability)&&setTimeout(function(){if(\"closed\"!=n.__state){var i=\"\",o=t(e.window.document.body);n.__options.triggerClose.click&&(i+=\"click.\"+n.__namespace+\"-triggerClose \"),n.__options.triggerClose.tap&&e.hasTouchCapability&&(i+=\"touchend.\"+n.__namespace+\"-triggerClose\"),o.on(i,function(i){n._touchIsMeaningfulEvent(i)&&(n._touchRecordEvent(i),n.__options.interactive&&t.contains(n._$tooltip[0],i.target)||n._close(i))}),n.__options.triggerClose.tap&&e.hasTouchCapability&&o.on(\"touchstart.\"+n.__namespace+\"-triggerClose\",function(t){n._touchRecordEvent(t)})}},0),n._trigger(\"ready\"),n.__options.functionReady&&n.__options.functionReady.call(n,n,{origin:n._$origin[0],tooltip:n._$tooltip[0]})}if(n.__options.timer>0){h=setTimeout(function(){n._close()},n.__options.timer+r);n.__timeouts.close.push(h)}}}return n},_openShortly:function(t){var i=this,o=!0;if(\"stable\"!=i.__state&&\"appearing\"!=i.__state&&!i.__timeouts.open&&(i._trigger({type:\"start\",event:t,stop:function(){o=!1}}),o)){var e=0==t.type.indexOf(\"touch\")?i.__options.delayTouch:i.__options.delay;e[0]?i.__timeouts.open=setTimeout(function(){i.__timeouts.open=null,i.__pointerIsOverOrigin&&i._touchIsMeaningfulEvent(t)?(i._trigger(\"startend\"),i._open(t)):i._trigger(\"startcancel\")},e[0]):(i._trigger(\"startend\"),i._open(t))}return i},_optionsExtract:function(i,o){var e=this,n=t.extend(!0,{},o),s=e.__options[i];return s||(s={},t.each(o,function(t,i){var o=e.__options[t];void 0!==o&&(s[t]=o)})),t.each(n,function(i,o){void 0!==s[i]&&(\"object\"!=typeof o||o instanceof Array||null==o||\"object\"!=typeof s[i]||s[i]instanceof Array||null==s[i]?n[i]=s[i]:t.extend(n[i],s[i]))}),n},_plug:function(i){var o=t.tooltipster._plugin(i);if(!o)throw new Error('The \"'+i+'\" plugin is not defined');return o.instance&&t.tooltipster.__bridge(o.instance,this,o.name),this},_touchIsEmulatedEvent:function(t){for(var i=!1,o=(new Date).getTime(),e=this.__touchEvents.length-1;e>=0;e--){var n=this.__touchEvents[e];if(!(o-n.time<500))break;n.target===t.target&&(i=!0)}return i},_touchIsMeaningfulEvent:function(t){return this._touchIsTouchEvent(t)&&!this._touchSwiped(t.target)||!this._touchIsTouchEvent(t)&&!this._touchIsEmulatedEvent(t)},_touchIsTouchEvent:function(t){return 0==t.type.indexOf(\"touch\")},_touchRecordEvent:function(t){return this._touchIsTouchEvent(t)&&(t.time=(new Date).getTime(),this.__touchEvents.push(t)),this},_touchSwiped:function(t){for(var i=!1,o=this.__touchEvents.length-1;o>=0;o--){var e=this.__touchEvents[o];if(\"touchmove\"==e.type){i=!0;break}if(\"touchstart\"==e.type&&t===e.target)break}return i},_trigger:function(){var i=Array.prototype.slice.apply(arguments);return\"string\"==typeof i[0]&&(i[0]={type:i[0]}),i[0].instance=this,i[0].origin=this._$origin?this._$origin[0]:null,i[0].tooltip=this._$tooltip?this._$tooltip[0]:null,this.__$emitterPrivate.trigger.apply(this.__$emitterPrivate,i),t.tooltipster._trigger.apply(t.tooltipster,i),this.__$emitterPublic.trigger.apply(this.__$emitterPublic,i),this},_unplug:function(i){var o=this;if(o[i]){var e=t.tooltipster._plugin(i);e.instance&&t.each(e.instance,function(t,e){o[t]&&o[t].bridged===o[i]&&delete o[t]}),o[i].__destroy&&o[i].__destroy(),delete o[i]}return o},close:function(t){return this.__destroyed?this.__destroyError():this._close(null,t),this},content:function(t){var i=this;if(void 0===t)return i.__Content;if(i.__destroyed)i.__destroyError();else if(i.__contentSet(t),null!==i.__Content){if(\"closed\"!==i.__state&&(i.__contentInsert(),i.reposition(),i.__options.updateAnimation))if(e.hasTransitions){var o=i.__options.updateAnimation;i._$tooltip.addClass(\"tooltipster-update-\"+o),setTimeout(function(){\"closed\"!=i.__state&&i._$tooltip.removeClass(\"tooltipster-update-\"+o)},1e3)}else i._$tooltip.fadeTo(200,.5,function(){\"closed\"!=i.__state&&i._$tooltip.fadeTo(200,1)})}else i._close();return i},destroy:function(){var i=this;if(i.__destroyed)i.__destroyError();else{\"closed\"!=i.__state?i.option(\"animationDuration\",0)._close(null,null,!0):i.__timeoutsClear(),i._trigger(\"destroy\"),i.__destroyed=!0,i._$origin.removeData(i.__namespace).off(\".\"+i.__namespace+\"-triggerOpen\"),t(e.window.document.body).off(\".\"+i.__namespace+\"-triggerOpen\");var o=i._$origin.data(\"tooltipster-ns\");if(o)if(1===o.length){var n=null;\"previous\"==i.__options.restoration?n=i._$origin.data(\"tooltipster-initialTitle\"):\"current\"==i.__options.restoration&&(n=\"string\"==typeof i.__Content?i.__Content:t(\"<div></div>\").append(i.__Content).html()),n&&i._$origin.attr(\"title\",n),i._$origin.removeClass(\"tooltipstered\"),i._$origin.removeData(\"tooltipster-ns\").removeData(\"tooltipster-initialTitle\")}else o=t.grep(o,function(t,o){return t!==i.__namespace}),i._$origin.data(\"tooltipster-ns\",o);i._trigger(\"destroyed\"),i._off(),i.off(),i.__Content=null,i.__$emitterPrivate=null,i.__$emitterPublic=null,i.__options.parent=null,i._$origin=null,i._$tooltip=null,t.tooltipster.__instancesLatestArr=t.grep(t.tooltipster.__instancesLatestArr,function(t,o){return i!==t}),clearInterval(i.__garbageCollector)}return i},disable:function(){return this.__destroyed?(this.__destroyError(),this):(this._close(),this.__enabled=!1,this)},elementOrigin:function(){if(!this.__destroyed)return this._$origin[0];this.__destroyError()},elementTooltip:function(){return this._$tooltip?this._$tooltip[0]:null},enable:function(){return this.__enabled=!0,this},hide:function(t){return this.close(t)},instance:function(){return this},off:function(){return this.__destroyed||this.__$emitterPublic.off.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},on:function(){return this.__destroyed?this.__destroyError():this.__$emitterPublic.on.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},one:function(){return this.__destroyed?this.__destroyError():this.__$emitterPublic.one.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this},open:function(t){return this.__destroyed?this.__destroyError():this._open(null,t),this},option:function(i,o){return void 0===o?this.__options[i]:(this.__destroyed?this.__destroyError():(this.__options[i]=o,this.__optionsFormat(),t.inArray(i,[\"trigger\",\"triggerClose\",\"triggerOpen\"])>=0&&this.__prepareOrigin(),\"selfDestruction\"===i&&this.__prepareGC()),this)},reposition:function(t,i){return this.__destroyed?this.__destroyError():\"closed\"!=this.__state&&_(this._$origin)&&(i||_(this._$tooltip))&&(i||this._$tooltip.detach(),this.__Geometry=this.__geometry(),this._trigger({type:\"reposition\",event:t,helper:{geo:this.__Geometry}})),this},show:function(t){return this.open(t)},status:function(){return{destroyed:this.__destroyed,enabled:this.__enabled,open:\"closed\"!==this.__state,state:this.__state}},triggerHandler:function(){return this.__destroyed?this.__destroyError():this.__$emitterPublic.triggerHandler.apply(this.__$emitterPublic,Array.prototype.slice.apply(arguments)),this}},t.fn.tooltipster=function(){var o=Array.prototype.slice.apply(arguments),e=\"You are using a single HTML element as content for several tooltips. You probably want to set the contentCloning option to TRUE.\";if(0===this.length)return this;if(\"string\"==typeof o[0]){var n=\"#*$~&\";return this.each(function(){var i=t(this).data(\"tooltipster-ns\"),s=i?t(this).data(i[0]):null;if(!s)throw new Error(\"You called Tooltipster's \\\"\"+o[0]+'\" method on an uninitialized element');if(\"function\"!=typeof s[o[0]])throw new Error('Unknown method \"'+o[0]+'\"');this.length>1&&\"content\"==o[0]&&(o[1]instanceof t||\"object\"==typeof o[1]&&null!=o[1]&&o[1].tagName)&&!s.__options.contentCloning&&s.__options.debug&&console.log(e);var r=s[o[0]](o[1],o[2]);if(r!==s||\"instance\"===o[0])return n=r,!1}),\"#*$~&\"!==n?n:this}t.tooltipster.__instancesLatestArr=[];var s=o[0]&&void 0!==o[0].multiple,r=s&&o[0].multiple||!s&&i.multiple,_=o[0]&&void 0!==o[0].content,a=_&&o[0].content||!_&&i.content,l=o[0]&&void 0!==o[0].contentCloning,p=l&&o[0].contentCloning||!l&&i.contentCloning,c=o[0]&&void 0!==o[0].debug,h=c&&o[0].debug||!c&&i.debug;return this.length>1&&(a instanceof t||\"object\"==typeof a&&null!=a&&a.tagName)&&!p&&h&&console.log(e),this.each(function(){var i=!1,e=t(this),n=e.data(\"tooltipster-ns\"),s=null;n?r?i=!0:h&&(console.log(\"Tooltipster: one or more tooltips are already attached to the element below. Ignoring.\"),console.log(this)):i=!0,i&&(s=new t.Tooltipster(this,o[0]),n||(n=[]),n.push(s.__namespace),e.data(\"tooltipster-ns\",n),e.data(s.__namespace,s),s.__options.functionInit&&s.__options.functionInit.call(s,s,{origin:this}),s._trigger(\"init\")),t.tooltipster.__instancesLatestArr.push(s)}),this},s.prototype={__init:function(i){this.__$tooltip=i,this.__$tooltip.css({left:0,overflow:\"hidden\",position:\"absolute\",top:0}).find(\".tooltipster-content\").css(\"overflow\",\"auto\"),this.$container=t('<div class=\"tooltipster-ruler\"></div>').append(this.__$tooltip).appendTo(e.window.document.body)},__forceRedraw:function(){var t=this.__$tooltip.parent();this.__$tooltip.detach(),this.__$tooltip.appendTo(t)},constrain:function(t,i){return this.constraints={width:t,height:i},this.__$tooltip.css({display:\"block\",height:\"\",overflow:\"auto\",width:t}),this},destroy:function(){this.__$tooltip.detach().find(\".tooltipster-content\").css({display:\"\",overflow:\"\"}),this.$container.remove()},free:function(){return this.constraints=null,this.__$tooltip.css({display:\"\",height:\"\",overflow:\"visible\",width:\"\"}),this},measure:function(){this.__forceRedraw();var t=this.__$tooltip[0].getBoundingClientRect(),i={size:{height:t.height||t.bottom-t.top,width:t.width||t.right-t.left}};if(this.constraints){var o=this.__$tooltip.find(\".tooltipster-content\"),n=this.__$tooltip.outerHeight(),s=o[0].getBoundingClientRect(),r={height:n<=this.constraints.height,width:t.width<=this.constraints.width&&s.width>=o[0].scrollWidth-1};i.fits=r.height&&r.width}return e.IE&&e.IE<=11&&i.size.width!==e.window.document.documentElement.clientWidth&&(i.size.width=Math.ceil(i.size.width)+1),i}};var a=navigator.userAgent.toLowerCase();-1!=a.indexOf(\"msie\")?e.IE=parseInt(a.split(\"msie\")[1]):-1!==a.toLowerCase().indexOf(\"trident\")&&-1!==a.indexOf(\" rv:11\")?e.IE=11:-1!=a.toLowerCase().indexOf(\"edge/\")&&(e.IE=parseInt(a.toLowerCase().split(\"edge/\")[1]));return t.tooltipster._plugin({name:\"tooltipster.sideTip\",instance:{__defaults:function(){return{arrow:!0,distance:6,functionPosition:null,maxWidth:null,minIntersection:16,minWidth:0,position:null,side:\"top\",viewportAware:!0,defaultStyles:{backgroundColor:\"#fff\",textColor:\"#000\"}}},__init:function(t){var i=this;i.__instance=t,i.__namespace=\"tooltipster-sideTip-\"+Math.round(1e6*Math.random()),i.__previousState=\"closed\",i.__options,i.__optionsFormat(),i.__instance._on(\"state.\"+i.__namespace,function(t){\"closed\"==t.state?i.__close():\"appearing\"==t.state&&\"closed\"==i.__previousState&&i.__create(),i.__previousState=t.state}),i.__instance._on(\"options.\"+i.__namespace,function(){i.__optionsFormat()}),i.__instance._on(\"reposition.\"+i.__namespace,function(t){i.__reposition(t.event,t.helper)})},__close:function(){this.__instance.content()instanceof t&&this.__instance.content().detach(),this.__instance._$tooltip.remove(),this.__instance._$tooltip=null},__create:function(){var i=this.__instance.__options.styles,o=t('<div class=\"tooltipster-base tooltipster-sidetip\"><div class=\"tooltipster-box\"><div class=\"tooltipster-content\"></div></div><div class=\"tooltipster-arrow\"><div class=\"tooltipster-arrow-uncropped\"><div class=\"tooltipster-arrow-border\"></div><div class=\"tooltipster-arrow-background\"></div></div></div></div>');o.find(\".tooltipster-box\").css({color:i.textColor?i.textColor:this.__options.defaultStyles.textColor,backgroundColor:i.backgroundColor?i.backgroundColor:this.__options.defaultStyles.backgroundColor}),o.find(\".tooltipster-arrow-border\").css({backgroundColor:i.backgroundColor?i.backgroundColor:this.__options.defaultStyles.backgroundColor}),this.__options.arrow||o.find(\".tooltipster-box\").css(\"margin\",0).end().find(\".tooltipster-arrow\").hide(),this.__options.minWidth&&o.css(\"min-width\",this.__options.minWidth+\"px\"),this.__options.maxWidth&&o.css(\"max-width\",this.__options.maxWidth+\"px\"),this.__instance._$tooltip=o,this.__instance._trigger(\"created\")},__destroy:function(){this.__instance._off(\".\"+self.__namespace)},__optionsFormat:function(){if(this.__options=this.__instance._optionsExtract(\"tooltipster.sideTip\",this.__defaults()),this.__options.position&&(this.__options.side=this.__options.position),\"object\"!=typeof this.__options.distance&&(this.__options.distance=[this.__options.distance]),this.__options.distance.length<4&&(void 0===this.__options.distance[1]&&(this.__options.distance[1]=this.__options.distance[0]),void 0===this.__options.distance[2]&&(this.__options.distance[2]=this.__options.distance[0]),void 0===this.__options.distance[3]&&(this.__options.distance[3]=this.__options.distance[1])),this.__options.distance={top:this.__options.distance[0],right:this.__options.distance[1],bottom:this.__options.distance[2],left:this.__options.distance[3]},\"string\"==typeof this.__options.side){this.__options.side=[this.__options.side,{top:\"bottom\",right:\"left\",bottom:\"top\",left:\"right\"}[this.__options.side]],\"left\"==this.__options.side[0]||\"right\"==this.__options.side[0]?this.__options.side.push(\"top\",\"bottom\"):this.__options.side.push(\"right\",\"left\")}6===t.tooltipster._env.IE&&!0!==this.__options.arrow&&(this.__options.arrow=!1)},__reposition:function(i,o){var e,n=this,s=n.__targetFind(o),r=[];n.__instance._$tooltip.detach();var _=n.__instance._$tooltip.clone(),a=t.tooltipster._getRuler(_),l=!1,p=n.__instance.option(\"animation\");switch(p&&_.removeClass(\"tooltipster-\"+p),t.each([\"window\",\"document\"],function(e,p){var c=null;if(n.__instance._trigger({container:p,helper:o,satisfied:l,takeTest:function(t){c=t},results:r,type:\"positionTest\"}),1==c||0!=c&&0==l&&(\"window\"!=p||n.__options.viewportAware))for(e=0;e<n.__options.side.length;e++){var h={horizontal:0,vertical:0},d=n.__options.side[e];\"top\"==d||\"bottom\"==d?h.vertical=n.__options.distance[d]:h.horizontal=n.__options.distance[d],n.__sideChange(_,d),t.each([\"natural\",\"constrained\"],function(t,e){if(c=null,n.__instance._trigger({container:p,event:i,helper:o,mode:e,results:r,satisfied:l,side:d,takeTest:function(t){c=t},type:\"positionTest\"}),1==c||0!=c&&0==l){var _={container:p,distance:h,fits:null,mode:e,outerSize:null,side:d,size:null,target:s[d],whole:null},u=(\"natural\"==e?a.free():a.constrain(o.geo.available[p][d].width-h.horizontal,o.geo.available[p][d].height-h.vertical)).measure();if(_.size=u.size,_.outerSize={height:u.size.height+h.vertical,width:u.size.width+h.horizontal},\"natural\"==e?o.geo.available[p][d].width>=_.outerSize.width&&o.geo.available[p][d].height>=_.outerSize.height?_.fits=!0:_.fits=!1:_.fits=u.fits,\"window\"==p&&(_.fits?_.whole=\"top\"==d||\"bottom\"==d?o.geo.origin.windowOffset.right>=n.__options.minIntersection&&o.geo.window.size.width-o.geo.origin.windowOffset.left>=n.__options.minIntersection:o.geo.origin.windowOffset.bottom>=n.__options.minIntersection&&o.geo.window.size.height-o.geo.origin.windowOffset.top>=n.__options.minIntersection:_.whole=!1),r.push(_),_.whole)l=!0;else if(\"natural\"==_.mode&&(_.fits||_.size.width<=o.geo.available[p][d].width))return!1}})}}),n.__instance._trigger({edit:function(t){r=t},event:i,helper:o,results:r,type:\"positionTested\"}),r.sort(function(t,i){return t.whole&&!i.whole?-1:!t.whole&&i.whole?1:t.whole&&i.whole?(o=n.__options.side.indexOf(t.side))<(e=n.__options.side.indexOf(i.side))?-1:o>e?1:\"natural\"==t.mode?-1:1:t.fits&&!i.fits?-1:!t.fits&&i.fits?1:t.fits&&i.fits?(o=n.__options.side.indexOf(t.side))<(e=n.__options.side.indexOf(i.side))?-1:o>e?1:\"natural\"==t.mode?-1:1:\"document\"==t.container&&\"bottom\"==t.side&&\"natural\"==t.mode?-1:1;var o,e}),(e=r[0]).coord={},e.side){case\"left\":case\"right\":e.coord.top=Math.floor(e.target-e.size.height/2);break;case\"bottom\":case\"top\":e.coord.left=Math.floor(e.target-e.size.width/2)}switch(e.side){case\"left\":e.coord.left=o.geo.origin.windowOffset.left-e.outerSize.width;break;case\"right\":e.coord.left=o.geo.origin.windowOffset.right+e.distance.horizontal;break;case\"top\":e.coord.top=o.geo.origin.windowOffset.top-e.outerSize.height;break;case\"bottom\":e.coord.top=o.geo.origin.windowOffset.bottom+e.distance.vertical}\"window\"==e.container?\"top\"==e.side||\"bottom\"==e.side?e.coord.left<0?o.geo.origin.windowOffset.right-this.__options.minIntersection>=0?e.coord.left=0:e.coord.left=o.geo.origin.windowOffset.right-this.__options.minIntersection-1:e.coord.left>o.geo.window.size.width-e.size.width&&(o.geo.origin.windowOffset.left+this.__options.minIntersection<=o.geo.window.size.width?e.coord.left=o.geo.window.size.width-e.size.width:e.coord.left=o.geo.origin.windowOffset.left+this.__options.minIntersection+1-e.size.width):e.coord.top<0?o.geo.origin.windowOffset.bottom-this.__options.minIntersection>=0?e.coord.top=0:e.coord.top=o.geo.origin.windowOffset.bottom-this.__options.minIntersection-1:e.coord.top>o.geo.window.size.height-e.size.height&&(o.geo.origin.windowOffset.top+this.__options.minIntersection<=o.geo.window.size.height?e.coord.top=o.geo.window.size.height-e.size.height:e.coord.top=o.geo.origin.windowOffset.top+this.__options.minIntersection+1-e.size.height):(e.coord.left>o.geo.window.size.width-e.size.width&&(e.coord.left=o.geo.window.size.width-e.size.width),e.coord.left<0&&(e.coord.left=0)),n.__sideChange(_,e.side),o.tooltipClone=_[0],o.tooltipParent=n.__instance.option(\"parent\").parent[0],o.mode=e.mode,o.whole=e.whole,o.origin=n.__instance._$origin[0],o.tooltip=n.__instance._$tooltip[0],delete e.container,delete e.fits,delete e.mode,delete e.outerSize,delete e.whole,e.distance=e.distance.horizontal||e.distance.vertical;var c,h,d,u=t.extend(!0,{},e);if(n.__instance._trigger({edit:function(t){e=t},event:i,helper:o,position:u,type:\"position\"}),n.__options.functionPosition){var g=n.__options.functionPosition.call(n,n.__instance,o,u);g&&(e=g)}a.destroy(),\"top\"==e.side||\"bottom\"==e.side?(c={prop:\"left\",val:e.target-e.coord.left},h=e.size.width-this.__options.minIntersection):(c={prop:\"top\",val:e.target-e.coord.top},h=e.size.height-this.__options.minIntersection),c.val<this.__options.minIntersection?c.val=this.__options.minIntersection:c.val>h&&(c.val=h),d=o.geo.origin.fixedLineage?o.geo.origin.windowOffset:{left:o.geo.origin.windowOffset.left+o.geo.window.scroll.left,top:o.geo.origin.windowOffset.top+o.geo.window.scroll.top},e.coord={left:d.left+(e.coord.left-o.geo.origin.windowOffset.left),top:d.top+(e.coord.top-o.geo.origin.windowOffset.top)},n.__sideChange(n.__instance._$tooltip,e.side),o.geo.origin.fixedLineage?n.__instance._$tooltip.css(\"position\",\"fixed\"):n.__instance._$tooltip.css(\"position\",\"\"),n.__instance._$tooltip.css({left:e.coord.left,top:e.coord.top,height:e.size.height,width:e.size.width}).find(\".tooltipster-arrow\").css({left:\"\",top:\"\"}).css(c.prop,c.val),n.__instance._$tooltip.appendTo(n.__instance.option(\"parent\")),n.__instance._trigger({type:\"repositioned\",event:i,position:e})},__sideChange:function(t,i){t.removeClass(\"tooltipster-bottom\").removeClass(\"tooltipster-left\").removeClass(\"tooltipster-right\").removeClass(\"tooltipster-top\").addClass(\"tooltipster-\"+i)},__targetFind:function(t){var i={},o=this.__instance._$origin[0].getClientRects();o.length>1&&(1==this.__instance._$origin.css(\"opacity\")&&(this.__instance._$origin.css(\"opacity\",.99),o=this.__instance._$origin[0].getClientRects(),this.__instance._$origin.css(\"opacity\",1)));if(o.length<2)i.top=Math.floor(t.geo.origin.windowOffset.left+t.geo.origin.size.width/2),i.bottom=i.top,i.left=Math.floor(t.geo.origin.windowOffset.top+t.geo.origin.size.height/2),i.right=i.left;else{var e=o[0];i.top=Math.floor(e.left+(e.right-e.left)/2),e=o.length>2?o[Math.ceil(o.length/2)-1]:o[0],i.right=Math.floor(e.top+(e.bottom-e.top)/2),e=o[o.length-1],i.bottom=Math.floor(e.left+(e.right-e.left)/2),e=o.length>2?o[Math.ceil((o.length+1)/2)-1]:o[o.length-1],i.left=Math.floor(e.top+(e.bottom-e.top)/2)}return i}}}),t});\n","Magento_ConfigurableProduct/js/catalog-add-to-cart-mixin.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'underscore',\n 'jquery',\n 'Magento_ConfigurableProduct/js/product/view/product-info-resolver'\n], function (_, $, productInfoResolver) {\n 'use strict';\n\n return function (widget) {\n\n $.widget('mage.catalogAddToCart', widget, {\n /**\n * @param {jQuery} form\n */\n ajaxSubmit: function (form) {\n var isConfigurable = !!_.find(form.serializeArray(), function (item) {\n return item.name.indexOf('super_attribute') !== -1;\n });\n\n if (isConfigurable) {\n this.options.productInfoResolver = productInfoResolver;\n }\n\n return this._super(form);\n }\n });\n\n return $.mage.catalogAddToCart;\n };\n});\n","Magento_ConfigurableProduct/js/configurable-customer-data.js":"require([\n 'jquery',\n 'Magento_ConfigurableProduct/js/options-updater'\n], function ($, Updater) {\n 'use strict';\n\n var selectors = {\n formSelector: '#product_addtocart_form'\n },\n configurableWidgetName = 'mageConfigurable',\n widgetInitEvent = 'configurable.initialized',\n\n /**\n * Sets all configurable attribute's selected values\n */\n updateConfigurableOptions = function () {\n var configurableWidget = $(selectors.formSelector).data(configurableWidgetName);\n\n if (!configurableWidget) {\n return;\n }\n configurableWidget.options.values = this.productOptions || {};\n configurableWidget._configureForValues();\n },\n updater = new Updater(widgetInitEvent, updateConfigurableOptions);\n\n updater.listen();\n});\n","Magento_ConfigurableProduct/js/options-updater.js":"define([\n 'jquery',\n 'underscore',\n 'Magento_Customer/js/customer-data',\n 'domReady!'\n], function ($, _, customerData) {\n 'use strict';\n\n var selectors = {\n formSelector: '#product_addtocart_form',\n productIdSelector: '#product_addtocart_form [name=\"product\"]',\n itemIdSelector: '#product_addtocart_form [name=\"item\"]'\n },\n cartData = customerData.get('cart'),\n productId = $(selectors.productIdSelector).val(),\n itemId = $(selectors.itemIdSelector).val(),\n\n /**\n * set productOptions according to cart data from customer-data\n *\n * @param {Object} data - cart data from customer-data\n * @returns {Boolean} - whether the new options differ from previous\n */\n setProductOptions = function (data) {\n var changedProductOptions;\n\n if (!(data && data.items && data.items.length && productId)) {\n return false;\n }\n changedProductOptions = _.find(data.items, function (item) {\n if (item['item_id'] === itemId) {\n return item['product_id'] === productId;\n }\n });\n changedProductOptions = changedProductOptions && changedProductOptions.options &&\n changedProductOptions.options.reduce(function (obj, val) {\n obj[val['option_id']] = val['option_value'];\n\n return obj;\n }, {});\n\n if (JSON.stringify(this.productOptions || {}) === JSON.stringify(changedProductOptions || {})) {\n return false;\n }\n\n this.productOptions = changedProductOptions;\n\n return true;\n },\n\n /**\n * Listens to update of cart data or options initialization and update selected option according to customer data\n *\n */\n listen = function () {\n cartData.subscribe(function (updateCartData) {\n if (this.setProductOptions(updateCartData)) {\n this.updateOptions();\n }\n }.bind(this));\n $(selectors.formSelector).on(this.eventName, function () {\n this.setProductOptions(cartData());\n this.updateOptions();\n }.bind(this));\n },\n\n /**\n * Updater constructor function\n *\n */\n Updater = function (eventName, updateOptionsCallback) {\n if (this instanceof Updater) {\n this.eventName = eventName;\n this.updateOptions = updateOptionsCallback;\n this.productOptions = {};\n }\n };\n\n Updater.prototype.setProductOptions = setProductOptions;\n Updater.prototype.listen = listen;\n\n return Updater;\n});\n","Magento_ConfigurableProduct/js/configurable.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/**\n * @api\n */\ndefine([\n 'jquery',\n 'underscore',\n 'mage/template',\n 'mage/translate',\n 'priceUtils',\n 'priceBox',\n 'jquery-ui-modules/widget',\n 'jquery/jquery.parsequery',\n 'fotoramaVideoEvents'\n], function ($, _, mageTemplate, $t, priceUtils) {\n 'use strict';\n\n $.widget('mage.configurable', {\n options: {\n superSelector: '.super-attribute-select',\n selectSimpleProduct: '[name=\"selected_configurable_option\"]',\n priceHolderSelector: '.price-box',\n spConfig: {},\n state: {},\n priceFormat: {},\n optionTemplate: '<%- data.label %>' +\n '<% if (typeof data.finalPrice.value !== \"undefined\") { %>' +\n ' <%- data.finalPrice.formatted %>' +\n '<% } %>',\n mediaGallerySelector: '[data-gallery-role=gallery-placeholder]',\n mediaGalleryInitial: null,\n slyOldPriceSelector: '.sly-old-price',\n normalPriceLabelSelector: '.product-info-main .normal-price .price-label',\n\n /**\n * Defines the mechanism of how images of a gallery should be\n * updated when user switches between configurations of a product.\n *\n * As for now value of this option can be either 'replace' or 'prepend'.\n *\n * @type {String}\n */\n gallerySwitchStrategy: 'replace',\n tierPriceTemplateSelector: '#tier-prices-template',\n tierPriceBlockSelector: '[data-role=\"tier-price-block\"]',\n tierPriceTemplate: '',\n selectorProduct: '.product-info-main',\n selectorProductPrice: '[data-role=priceBox]',\n qtyInfo: '#qty'\n },\n\n /**\n * Creates widget\n * @private\n */\n _create: function () {\n // Initial setting of various option values\n this._initializeOptions();\n\n // Override defaults with URL query parameters and/or inputs values\n this._overrideDefaults();\n\n // Change events to check select reloads\n this._setupChangeEvents();\n\n // Fill state\n this._fillState();\n\n // Setup child and prev/next settings\n this._setChildSettings();\n\n // Setup/configure values to inputs\n this._configureForValues();\n\n $(this.element).trigger('configurable.initialized');\n $(this.options.qtyInfo).on('input', this._reloadPrice.bind(this));\n },\n\n /**\n * Initialize tax configuration, initial settings, and options values.\n * @private\n */\n _initializeOptions: function () {\n var options = this.options,\n gallery = $(options.mediaGallerySelector),\n priceBoxOptions = $(this.options.priceHolderSelector).priceBox('option').priceConfig || null;\n\n if (priceBoxOptions && priceBoxOptions.optionTemplate) {\n options.optionTemplate = priceBoxOptions.optionTemplate;\n }\n\n if (priceBoxOptions && priceBoxOptions.priceFormat) {\n options.priceFormat = priceBoxOptions.priceFormat;\n }\n options.optionTemplate = mageTemplate(options.optionTemplate);\n options.tierPriceTemplate = $(this.options.tierPriceTemplateSelector).html();\n\n options.settings = options.spConfig.containerId ?\n $(options.spConfig.containerId).find(options.superSelector) :\n $(options.superSelector);\n\n options.values = options.spConfig.defaultValues || {};\n options.parentImage = $('[data-role=base-image-container] img').attr('src');\n\n this.inputSimpleProduct = this.element.find(options.selectSimpleProduct);\n\n gallery.data('gallery') ?\n this._onGalleryLoaded(gallery) :\n gallery.on('gallery:loaded', this._onGalleryLoaded.bind(this, gallery));\n\n },\n\n /**\n * Override default options values settings with either URL query parameters or\n * initialized inputs values.\n * @private\n */\n _overrideDefaults: function () {\n var hashIndex = window.location.href.indexOf('#');\n\n if (hashIndex !== -1) {\n this._parseQueryParams(window.location.href.substr(hashIndex + 1));\n }\n\n if (this.options.spConfig.inputsInitialized) {\n this._setValuesByAttribute();\n }\n\n this._setInitialOptionsLabels();\n },\n\n /**\n * Parse query parameters from a query string and set options values based on the\n * key value pairs of the parameters.\n * @param {*} queryString - URL query string containing query parameters.\n * @private\n */\n _parseQueryParams: function (queryString) {\n var queryParams = $.parseQuery({\n query: queryString\n });\n\n $.each(queryParams, $.proxy(function (key, value) {\n if (this.options.spConfig.attributes[key] !== undefined &&\n _.find(this.options.spConfig.attributes[key].options, function (element) {\n return element.id === value;\n })) {\n this.options.values[key] = value;\n }\n }, this));\n },\n\n /**\n * Override default options values with values based on each element's attribute\n * identifier.\n * @private\n */\n _setValuesByAttribute: function () {\n this.options.values = {};\n $.each(this.options.settings, $.proxy(function (index, element) {\n var attributeId;\n\n if (element.value) {\n attributeId = element.id.replace(/[a-z]*/, '');\n\n if (this.options.spConfig.attributes[attributeId] !== undefined &&\n _.find(this.options.spConfig.attributes[attributeId].options, function (optionElement) {\n return optionElement.id === element.value;\n })) {\n this.options.values[attributeId] = element.value;\n }\n }\n }, this));\n },\n\n /**\n * Set additional field with initial label to be used when switching between options with different prices.\n * @private\n */\n _setInitialOptionsLabels: function () {\n $.each(this.options.spConfig.attributes, $.proxy(function (index, element) {\n $.each(element.options, $.proxy(function (optIndex, optElement) {\n this.options.spConfig.attributes[index].options[optIndex].initialLabel = optElement.label;\n }, this));\n }, this));\n },\n\n /**\n * Set up .on('change') events for each option element to configure the option.\n * @private\n */\n _setupChangeEvents: function () {\n $.each(this.options.settings, $.proxy(function (index, element) {\n $(element).on('change', this, this._configure);\n }, this));\n },\n\n /**\n * Iterate through the option settings and set each option's element configuration,\n * attribute identifier. Set the state based on the attribute identifier.\n * @private\n */\n _fillState: function () {\n $.each(this.options.settings, $.proxy(function (index, element) {\n var attributeId = element.id.replace(/[a-z]*/, '');\n\n if (attributeId && this.options.spConfig.attributes[attributeId]) {\n element.config = this.options.spConfig.attributes[attributeId];\n element.attributeId = attributeId;\n this.options.state[attributeId] = false;\n }\n }, this));\n },\n\n /**\n * Set each option's child settings, and next/prev option setting. Fill (initialize)\n * an option's list of selections as needed or disable an option's setting.\n * @private\n */\n _setChildSettings: function () {\n var childSettings = [],\n settings = this.options.settings,\n index = settings.length,\n option;\n\n while (index--) {\n option = settings[index];\n\n if (index) {\n option.disabled = true;\n } else {\n this._fillSelect(option);\n }\n\n _.extend(option, {\n childSettings: childSettings.slice(),\n prevSetting: settings[index - 1],\n nextSetting: settings[index + 1]\n });\n\n childSettings.push(option);\n }\n },\n\n /**\n * Setup for all configurable option settings. Set the value of the option and configure\n * the option, which sets its state, and initializes the option's choices, etc.\n * @private\n */\n _configureForValues: function () {\n if (this.options.values) {\n this.options.settings.each($.proxy(function (index, element) {\n var attributeId = element.attributeId;\n\n element.value = this.options.values[attributeId] || '';\n this._configureElement(element);\n }, this));\n }\n },\n\n /**\n * Event handler for configuring an option.\n * @private\n * @param {Object} event - Event triggered to configure an option.\n */\n _configure: function (event) {\n event.data._configureElement(this);\n },\n\n /**\n * Configure an option, initializing it's state and enabling related options, which\n * populates the related option's selection and resets child option selections.\n * @private\n * @param {*} element - The element associated with a configurable option.\n */\n _configureElement: function (element) {\n this.simpleProduct = this._getSimpleProductId(element);\n\n if (element.value) {\n this.options.state[element.config.id] = element.value;\n\n if (element.nextSetting) {\n element.nextSetting.disabled = false;\n this._fillSelect(element.nextSetting);\n this._resetChildren(element.nextSetting);\n } else {\n if (!!document.documentMode) { //eslint-disable-line\n this.inputSimpleProduct.val(element.options[element.selectedIndex].config.allowedProducts[0]);\n } else {\n this.inputSimpleProduct.val(element.selectedOptions[0].config.allowedProducts[0]);\n }\n }\n } else {\n this._resetChildren(element);\n }\n\n this._reloadPrice();\n this._displayRegularPriceBlock(this.simpleProduct);\n this._displayTierPriceBlock(this.simpleProduct);\n this._displayNormalPriceLabel();\n this._changeProductImage();\n },\n\n /**\n * Change displayed product image according to chosen options of configurable product\n *\n * @private\n */\n _changeProductImage: function () {\n var images,\n initialImages = this.options.mediaGalleryInitial,\n gallery = $(this.options.mediaGallerySelector).data('gallery');\n\n if (_.isUndefined(gallery)) {\n $(this.options.mediaGallerySelector).on('gallery:loaded', function () {\n this._changeProductImage();\n }.bind(this));\n\n return;\n }\n\n images = this.options.spConfig.images[this.simpleProduct];\n\n if (images) {\n images = this._sortImages(images);\n\n if (this.options.gallerySwitchStrategy === 'prepend') {\n images = images.concat(initialImages);\n }\n\n images = $.extend(true, [], images);\n images = this._setImageIndex(images);\n\n gallery.updateData(images);\n this._addFotoramaVideoEvents(false);\n } else {\n gallery.updateData(initialImages);\n this._addFotoramaVideoEvents(true);\n }\n },\n\n /**\n * Add video events\n *\n * @param {Boolean} isInitial\n * @private\n */\n _addFotoramaVideoEvents: function (isInitial) {\n if (_.isUndefined($.mage.AddFotoramaVideoEvents)) {\n return;\n }\n\n if (isInitial) {\n $(this.options.mediaGallerySelector).AddFotoramaVideoEvents();\n\n return;\n }\n\n $(this.options.mediaGallerySelector).AddFotoramaVideoEvents({\n selectedOption: this.simpleProduct,\n dataMergeStrategy: this.options.gallerySwitchStrategy\n });\n },\n\n /**\n * Sorting images array\n *\n * @private\n */\n _sortImages: function (images) {\n return _.sortBy(images, function (image) {\n return image.position;\n });\n },\n\n /**\n * Set correct indexes for image set.\n *\n * @param {Array} images\n * @private\n */\n _setImageIndex: function (images) {\n var length = images.length,\n i;\n\n for (i = 0; length > i; i++) {\n images[i].i = i + 1;\n }\n\n return images;\n },\n\n /**\n * For a given option element, reset all of its selectable options. Clear any selected\n * index, disable the option choice, and reset the option's state if necessary.\n * @private\n * @param {*} element - The element associated with a configurable option.\n */\n _resetChildren: function (element) {\n if (element.childSettings) {\n _.each(element.childSettings, function (set) {\n set.selectedIndex = 0;\n set.disabled = true;\n });\n\n if (element.config) {\n this.options.state[element.config.id] = false;\n }\n }\n },\n\n /**\n * Populates an option's selectable choices.\n * @private\n * @param {*} element - Element associated with a configurable option.\n */\n _fillSelect: function (element) {\n var attributeId = element.id.replace(/[a-z]*/, ''),\n options = this._getAttributeOptions(attributeId),\n prevConfig,\n index = 1,\n allowedProducts,\n allowedProductsByOption,\n allowedProductsAll,\n i,\n j,\n finalPrice = parseFloat(this.options.spConfig.prices.finalPrice.amount),\n optionFinalPrice,\n optionPriceDiff,\n optionPrices = this.options.spConfig.optionPrices,\n allowedOptions = [],\n indexKey,\n allowedProductMinPrice,\n allowedProductsAllMinPrice,\n canDisplayOutOfStockProducts = false,\n filteredSalableProducts;\n\n this._clearSelect(element);\n element.options[0] = new Option('', '');\n element.options[0].innerHTML = this.options.spConfig.chooseText;\n prevConfig = false;\n\n if (element.prevSetting) {\n prevConfig = element.prevSetting.options[element.prevSetting.selectedIndex];\n }\n\n if (options) {\n for (indexKey in this.options.spConfig.index) {\n /* eslint-disable max-depth */\n if (this.options.spConfig.index.hasOwnProperty(indexKey)) {\n allowedOptions = allowedOptions.concat(_.values(this.options.spConfig.index[indexKey]));\n }\n }\n\n if (prevConfig) {\n allowedProductsByOption = {};\n allowedProductsAll = [];\n\n for (i = 0; i < options.length; i++) {\n /* eslint-disable max-depth */\n for (j = 0; j < options[i].products.length; j++) {\n // prevConfig.config can be undefined\n if (prevConfig.config &&\n prevConfig.config.allowedProducts &&\n prevConfig.config.allowedProducts.indexOf(options[i].products[j]) > -1) {\n if (!allowedProductsByOption[i]) {\n allowedProductsByOption[i] = [];\n }\n allowedProductsByOption[i].push(options[i].products[j]);\n allowedProductsAll.push(options[i].products[j]);\n }\n }\n }\n\n if (typeof allowedProductsAll[0] !== 'undefined' &&\n typeof optionPrices[allowedProductsAll[0]] !== 'undefined') {\n allowedProductsAllMinPrice = this._getAllowedProductWithMinPrice(allowedProductsAll);\n finalPrice = parseFloat(optionPrices[allowedProductsAllMinPrice].finalPrice.amount);\n }\n }\n\n for (i = 0; i < options.length; i++) {\n if (prevConfig && typeof allowedProductsByOption[i] === 'undefined') {\n continue; //jscs:ignore disallowKeywords\n }\n\n allowedProducts = prevConfig ? allowedProductsByOption[i] : options[i].products.slice(0);\n optionPriceDiff = 0;\n\n if (typeof allowedProducts[0] !== 'undefined' &&\n typeof optionPrices[allowedProducts[0]] !== 'undefined') {\n allowedProductMinPrice = this._getAllowedProductWithMinPrice(allowedProducts);\n optionFinalPrice = parseFloat(optionPrices[allowedProductMinPrice].finalPrice.amount);\n optionPriceDiff = optionFinalPrice - finalPrice;\n options[i].label = options[i].initialLabel;\n\n if (optionPriceDiff !== 0) {\n options[i].label += ' ' + priceUtils.formatPriceLocale(\n optionPriceDiff,\n this.options.priceFormat,\n true\n );\n }\n }\n\n if (allowedProducts.length > 0 || _.include(allowedOptions, options[i].id)) {\n options[i].allowedProducts = allowedProducts;\n element.options[index] = new Option(this._getOptionLabel(options[i]), options[i].id);\n\n if (this.options.spConfig.canDisplayShowOutOfStockStatus) {\n filteredSalableProducts = $(this.options.spConfig.salable[attributeId][options[i].id]).\n filter(options[i].allowedProducts);\n canDisplayOutOfStockProducts = filteredSalableProducts.length === 0;\n }\n\n if (typeof options[i].price !== 'undefined') {\n element.options[index].setAttribute('price', options[i].price);\n }\n\n if (allowedProducts.length === 0 || canDisplayOutOfStockProducts) {\n element.options[index].disabled = true;\n }\n\n element.options[index].config = options[i];\n index++;\n }\n\n /* eslint-enable max-depth */\n }\n }\n },\n\n /**\n * Generate the label associated with a configurable option. This includes the option's\n * label or value and the option's price.\n * @private\n * @param {*} option - A single choice among a group of choices for a configurable option.\n * @return {String} The option label with option value and price (e.g. Black +1.99)\n */\n _getOptionLabel: function (option) {\n return option.label;\n },\n\n /**\n * Removes an option's selections.\n * @private\n * @param {*} element - The element associated with a configurable option.\n */\n _clearSelect: function (element) {\n var i;\n\n for (i = element.options.length - 1; i >= 0; i--) {\n element.remove(i);\n }\n },\n\n /**\n * Retrieve the attribute options associated with a specific attribute Id.\n * @private\n * @param {Number} attributeId - The id of the attribute whose configurable options are sought.\n * @return {Object} Object containing the attribute options.\n */\n _getAttributeOptions: function (attributeId) {\n if (this.options.spConfig.attributes[attributeId]) {\n return this.options.spConfig.attributes[attributeId].options;\n }\n },\n\n /**\n * Reload the price of the configurable product incorporating the prices of all of the\n * configurable product's option selections.\n */\n _reloadPrice: function () {\n $(this.options.priceHolderSelector).trigger('updatePrice', this._getPrices());\n },\n\n /**\n * Get product various prices\n * @returns {{}}\n * @private\n */\n _getPrices: function () {\n var prices = {},\n elements = _.toArray(this.options.settings),\n allowedProduct;\n\n _.each(elements, function (element) {\n var selected = element.options[element.selectedIndex],\n config = selected && selected.config,\n priceValue = this._calculatePrice({});\n\n if (config && config.allowedProducts.length === 1) {\n priceValue = this._calculatePrice(config);\n } else if (element.value) {\n allowedProduct = this._getAllowedProductWithMinPrice(config.allowedProducts);\n priceValue = this._calculatePrice({\n 'allowedProducts': [\n allowedProduct\n ]\n });\n }\n\n if (!_.isEmpty(priceValue)) {\n prices.prices = priceValue;\n }\n }, this);\n\n return prices;\n },\n\n /**\n * Get product with minimum price from selected options.\n *\n * @param {Array} allowedProducts\n * @returns {String}\n * @private\n */\n _getAllowedProductWithMinPrice: function (allowedProducts) {\n var optionPrices = this.options.spConfig.optionPrices,\n product = {},\n optionMinPrice, optionFinalPrice;\n\n _.each(allowedProducts, function (allowedProduct) {\n optionFinalPrice = parseFloat(optionPrices[allowedProduct].finalPrice.amount);\n\n if (_.isEmpty(product) || optionFinalPrice < optionMinPrice) {\n optionMinPrice = optionFinalPrice;\n product = allowedProduct;\n }\n }, this);\n\n return product;\n },\n\n /**\n * Returns prices for configured products\n *\n * @param {*} config - Products configuration\n * @returns {*}\n * @private\n */\n _calculatePrice: function (config) {\n var displayPrices = $(this.options.priceHolderSelector).priceBox('option').prices,\n newPrices = this.options.spConfig.optionPrices[_.first(config.allowedProducts)] || {};\n\n _.each(displayPrices, function (price, code) {\n displayPrices[code].amount = newPrices[code] ? newPrices[code].amount - displayPrices[code].amount : 0;\n });\n\n return displayPrices;\n },\n\n /**\n * Returns Simple product Id\n * depending on current selected option.\n *\n * @private\n * @param {HTMLElement} element\n * @returns {String|undefined}\n */\n _getSimpleProductId: function (element) {\n // TODO: Rewrite algorithm. It should return ID of\n // simple product based on selected options.\n var allOptions = element.config.options,\n value = element.value,\n config;\n\n config = _.filter(allOptions, function (option) {\n return option.id === value;\n });\n config = _.first(config);\n\n return _.isEmpty(config) ?\n undefined :\n _.first(config.allowedProducts);\n\n },\n\n /**\n * Show or hide regular price block\n *\n * @param {*} optionId\n * @private\n */\n _displayRegularPriceBlock: function (optionId) {\n var shouldBeShown = true,\n $priceBox = this.element.parents(this.options.selectorProduct)\n .find(this.options.selectorProductPrice);\n\n _.each(this.options.settings, function (element) {\n if (element.value === '') {\n shouldBeShown = false;\n }\n });\n\n if (shouldBeShown &&\n this.options.spConfig.optionPrices[optionId].oldPrice.amount !==\n this.options.spConfig.optionPrices[optionId].finalPrice.amount\n ) {\n $(this.options.slyOldPriceSelector).show();\n } else {\n $(this.options.slyOldPriceSelector).hide();\n }\n\n $(document).trigger('updateMsrpPriceBlock',\n [\n optionId,\n this.options.spConfig.optionPrices,\n $priceBox\n ]\n );\n },\n\n /**\n * Show or hide normal price label\n *\n * @private\n */\n _displayNormalPriceLabel: function () {\n var shouldBeShown = false;\n\n _.each(this.options.settings, function (element) {\n if (element.value === '') {\n shouldBeShown = true;\n }\n });\n\n if (shouldBeShown) {\n $(this.options.normalPriceLabelSelector).show();\n } else {\n $(this.options.normalPriceLabelSelector).hide();\n }\n },\n\n /**\n * Callback which fired after gallery gets initialized.\n *\n * @param {HTMLElement} element - DOM element associated with gallery.\n */\n _onGalleryLoaded: function (element) {\n var galleryObject = element.data('gallery');\n\n this.options.mediaGalleryInitial = galleryObject.returnCurrentImages();\n },\n\n /**\n * Show or hide tier price block\n *\n * @param {*} optionId\n * @private\n */\n _displayTierPriceBlock: function (optionId) {\n var tierPrices = typeof optionId != 'undefined' && this.options.spConfig.optionPrices[optionId].tierPrices;\n\n if (_.isArray(tierPrices) && tierPrices.length > 0) {\n\n if (this.options.tierPriceTemplate) {\n $(this.options.tierPriceBlockSelector).html(\n mageTemplate(this.options.tierPriceTemplate, {\n 'tierPrices': tierPrices,\n '$t': $t,\n 'currencyFormat': this.options.spConfig.currencyFormat,\n 'priceUtils': priceUtils\n })\n ).show();\n }\n } else {\n $(this.options.tierPriceBlockSelector).hide();\n }\n }\n });\n\n return $.mage.configurable;\n});\n","Magento_ConfigurableProduct/js/catalog-add-to-cart.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\nrequire([\n 'jquery'\n], function ($) {\n 'use strict';\n\n /**\n * Add selected configurable attributes to redirect url\n *\n * @see Magento_Catalog/js/catalog-add-to-cart\n */\n $('body').on('catalogCategoryAddToCartRedirect', function (event, data) {\n $(data.form).find('select[name*=\"super\"]').each(function (index, item) {\n data.redirectParameters.push(item.config.id + '=' + $(item).val());\n });\n });\n});\n","Magento_ConfigurableProduct/js/product/view/product-info-resolver.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'underscore',\n 'Magento_Catalog/js/product/view/product-info'\n], function (_, productInfo) {\n 'use strict';\n\n /**\n * Returns info about configurable products in form.\n *\n * @param {jQuery} $form\n * @return {Array}\n */\n return function ($form) {\n var optionValues = [],\n product = _.findWhere($form.serializeArray(), {\n name: 'product'\n }),\n productId;\n\n if (!_.isUndefined(product)) {\n productId = product.value;\n _.each($form.serializeArray(), function (item) {\n if (item.name.indexOf('super_attribute') !== -1) {\n optionValues.push(item.value);\n }\n });\n optionValues.sort();\n productInfo().push(\n {\n 'id': productId,\n 'optionValues': optionValues\n }\n );\n }\n\n return _.uniq(productInfo(), function (item) {\n var optionValuesStr = item.optionValues ? item.optionValues.join() : '';\n\n return item.id + optionValuesStr;\n });\n };\n});\n\n","Magento_ReCaptchaCheckoutSalesRule/js/checkout-sales-rule.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/* global grecaptcha */\ndefine(\n [\n 'Magento_ReCaptchaWebapiUi/js/webapiReCaptcha',\n 'Magento_ReCaptchaWebapiUi/js/webapiReCaptchaRegistry',\n 'jquery',\n 'Magento_SalesRule/js/action/set-coupon-code',\n 'Magento_SalesRule/js/action/cancel-coupon',\n 'Magento_Checkout/js/model/quote',\n 'ko'\n ], function (Component, recaptchaRegistry, $, setCouponCodeAction, cancelCouponAction, quote, ko) {\n 'use strict';\n\n var totals = quote.getTotals(),\n couponCode = ko.observable(null),\n isApplied;\n\n if (totals()) {\n couponCode(totals()['coupon_code']);\n }\n //Captcha can only be required for adding a coupon so we need to know if one was added already.\n isApplied = ko.observable(couponCode() != null);\n\n return Component.extend({\n\n /**\n * Initialize parent form.\n *\n * @param {Object} parentForm\n * @param {String} widgetId\n */\n initParentForm: function (parentForm, widgetId) {\n var self = this,\n xRecaptchaValue,\n captchaId = this.getReCaptchaId();\n\n this._super();\n\n if (couponCode() != null) {\n if (isApplied) {\n self.validateReCaptcha(true);\n $('#' + captchaId).hide();\n }\n }\n\n if (recaptchaRegistry.triggers.hasOwnProperty('recaptcha-checkout-coupon-apply')) {\n recaptchaRegistry.addListener('recaptcha-checkout-coupon-apply', function (token) {\n //Add reCaptcha value to coupon request\n xRecaptchaValue = token;\n });\n }\n\n setCouponCodeAction.registerDataModifier(function (headers) {\n headers['X-ReCaptcha'] = xRecaptchaValue;\n });\n\n if (self.getIsInvisibleRecaptcha()) {\n grecaptcha.execute(widgetId);\n self.validateReCaptcha(true);\n }\n //Refresh reCaptcha after failed request.\n setCouponCodeAction.registerFailCallback(function () {\n if (self.getIsInvisibleRecaptcha()) {\n grecaptcha.execute(widgetId);\n self.validateReCaptcha(true);\n } else {\n self.validateReCaptcha(false);\n grecaptcha.reset(widgetId);\n $('#' + captchaId).show();\n }\n });\n //Hide captcha when a coupon has been applied.\n setCouponCodeAction.registerSuccessCallback(function () {\n self.validateReCaptcha(true);\n $('#' + captchaId).hide();\n });\n //Show captcha again if it was canceled.\n cancelCouponAction.registerSuccessCallback(function () {\n self.validateReCaptcha(false);\n grecaptcha.reset(widgetId);\n $('#' + captchaId).show();\n });\n }\n });\n });\n","Magento_Bundle/js/price-bundle.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'jquery',\n 'underscore',\n 'mage/template',\n 'priceUtils',\n 'priceBox'\n], function ($, _, mageTemplate, utils) {\n 'use strict';\n\n var globalOptions = {\n optionConfig: null,\n productBundleSelector: 'input.bundle.option, select.bundle.option, textarea.bundle.option',\n qtyFieldSelector: 'input.qty',\n priceBoxSelector: '.price-box',\n optionHandlers: {},\n optionTemplate: '<%- data.label %>' +\n '<% if (data.finalPrice.value) { %>' +\n ' +<%- data.finalPrice.formatted %>' +\n '<% } %>',\n controlContainer: 'dd', // should be eliminated\n priceFormat: {},\n isFixedPrice: false,\n optionTierPricesBlocksSelector: '#option-tier-prices-{1} [data-role=\"selection-tier-prices\"]',\n isOptionsInitialized: false\n };\n\n $.widget('mage.priceBundle', {\n options: globalOptions,\n\n /**\n * @private\n */\n _init: function initPriceBundle() {\n var form = this.element,\n options = $(this.options.productBundleSelector, form);\n\n options.trigger('change');\n },\n\n /**\n * @private\n */\n _create: function createPriceBundle() {\n var form = this.element,\n options = $(this.options.productBundleSelector, form),\n priceBox = $(this.options.priceBoxSelector, form),\n qty = $(this.options.qtyFieldSelector, form);\n\n this._updatePriceBox();\n priceBox.on('price-box-initialized', this._updatePriceBox.bind(this));\n options.on('change', this._onBundleOptionChanged.bind(this));\n qty.on('change', this._onQtyFieldChanged.bind(this));\n },\n\n /**\n * Update price box config with bundle option prices\n * @private\n */\n _updatePriceBox: function () {\n var form = this.element,\n options = $(this.options.productBundleSelector, form),\n priceBox = $(this.options.priceBoxSelector, form);\n\n if (!this.options.isOptionsInitialized) {\n if (priceBox.data('magePriceBox') &&\n priceBox.priceBox('option') &&\n priceBox.priceBox('option').priceConfig\n ) {\n if (priceBox.priceBox('option').priceConfig.optionTemplate) { //eslint-disable-line max-depth\n this._setOption('optionTemplate', priceBox.priceBox('option').priceConfig.optionTemplate);\n }\n this._setOption('priceFormat', priceBox.priceBox('option').priceConfig.priceFormat);\n priceBox.priceBox('setDefault', this.options.optionConfig.prices);\n this.options.isOptionsInitialized = true;\n }\n this._applyOptionNodeFix(options);\n }\n\n return this;\n },\n\n /**\n * Handle change on bundle option inputs\n * @param {jQuery.Event} event\n * @private\n */\n _onBundleOptionChanged: function onBundleOptionChanged(event) {\n var changes,\n bundleOption = $(event.target),\n priceBox = $(this.options.priceBoxSelector, this.element),\n handler = this.options.optionHandlers[bundleOption.data('role')];\n\n bundleOption.data('optionContainer', bundleOption.closest(this.options.controlContainer));\n bundleOption.data('qtyField', bundleOption.data('optionContainer').find(this.options.qtyFieldSelector));\n\n if (handler && handler instanceof Function) {\n changes = handler(bundleOption, this.options.optionConfig, this);\n } else {\n changes = defaultGetOptionValue(bundleOption, this.options.optionConfig);//eslint-disable-line\n }\n\n // eslint-disable-next-line no-use-before-define\n if (isValidQty(bundleOption)) {\n if (changes) {\n priceBox.trigger('updatePrice', changes);\n }\n\n this._displayTierPriceBlock(bundleOption);\n this.updateProductSummary();\n }\n },\n\n /**\n * Handle change on qty inputs near bundle option\n * @param {jQuery.Event} event\n * @private\n */\n _onQtyFieldChanged: function onQtyFieldChanged(event) {\n var field = $(event.target),\n optionInstance,\n optionConfig;\n\n if (field.data('optionId') && field.data('optionValueId')) {\n optionInstance = field.data('option');\n optionConfig = this.options.optionConfig\n .options[field.data('optionId')]\n .selections[field.data('optionValueId')];\n optionConfig.qty = field.val();\n\n // eslint-disable-next-line no-use-before-define\n if (isValidQty(optionInstance)) {\n optionInstance.trigger('change');\n }\n }\n },\n\n /**\n * Helper to fix backend behavior:\n * - if default qty large than 1 then backend multiply price in config\n *\n * @deprecated\n * @private\n */\n _applyQtyFix: function applyQtyFix() {\n var config = this.options.optionConfig;\n\n if (config.isFixedPrice) {\n _.each(config.options, function (option) {\n _.each(option.selections, function (item) {\n if (item.qty && item.qty !== 1) {\n _.each(item.prices, function (price) {\n price.amount /= item.qty;\n });\n }\n });\n });\n }\n },\n\n /**\n * Helper to fix issue with option nodes:\n * - you can't place any html in option ->\n * so you can't style it via CSS\n * @param {jQuery} options\n * @private\n */\n _applyOptionNodeFix: function applyOptionNodeFix(options) {\n var config = this.options,\n format = config.priceFormat,\n template = config.optionTemplate;\n\n template = mageTemplate(template);\n options.filter('select').each(function (index, element) {\n var $element = $(element),\n optionId = utils.findOptionId($element),\n optionConfig = config.optionConfig && config.optionConfig.options[optionId].selections,\n value;\n\n $element.find('option').each(function (idx, option) {\n var $option,\n optionValue,\n toTemplate,\n prices;\n\n $option = $(option);\n optionValue = $option.val();\n\n if (!optionValue && optionValue !== 0) {\n return;\n }\n\n toTemplate = {\n data: {\n label: optionConfig[optionValue] && optionConfig[optionValue].name\n }\n };\n prices = optionConfig[optionValue].prices;\n\n _.each(prices, function (price, type) {\n value = +price.amount;\n value += _.reduce(price.adjustments, function (sum, x) {//eslint-disable-line\n return sum + x;\n }, 0);\n toTemplate.data[type] = {\n value: value,\n formatted: utils.formatPriceLocale(value, format)\n };\n });\n\n $option.html(template(toTemplate));\n });\n });\n },\n\n /**\n * Custom behavior on getting options:\n * now widget able to deep merge accepted configuration with instance options.\n * @param {Object} options\n * @return {$.Widget}\n */\n _setOptions: function setOptions(options) {\n $.extend(true, this.options, options);\n\n this._super(options);\n\n return this;\n },\n\n /**\n * Show or hide option tier prices block\n *\n * @param {Object} optionElement\n * @private\n */\n _displayTierPriceBlock: function (optionElement) {\n var optionType = optionElement.prop('type'),\n optionId,\n optionValue,\n optionTierPricesElements;\n\n if (optionType === 'select-one') {\n optionId = utils.findOptionId(optionElement[0]);\n optionValue = optionElement.val() || null;\n optionTierPricesElements = $(this.options.optionTierPricesBlocksSelector.replace('{1}', optionId));\n\n _.each(optionTierPricesElements, function (tierPriceElement) {\n var selectionId = $(tierPriceElement).data('selection-id') + '';\n\n if (selectionId === optionValue) {\n $(tierPriceElement).show();\n } else {\n $(tierPriceElement).hide();\n }\n });\n }\n },\n\n /**\n * Handler to update productSummary box\n */\n updateProductSummary: function updateProductSummary() {\n this.element.trigger('updateProductSummary', {\n config: this.options.optionConfig\n });\n }\n });\n\n return $.mage.priceBundle;\n\n /**\n * Converts option value to priceBox object\n *\n * @param {jQuery} element\n * @param {Object} config\n * @returns {Object|null} - priceBox object with additional prices\n */\n function defaultGetOptionValue(element, config) {\n var changes = {},\n optionHash,\n tempChanges,\n qtyField,\n optionId = utils.findOptionId(element[0]),\n optionValue = element.val() || null,\n optionName = element.prop('name'),\n optionType = element.prop('type'),\n optionConfig = config.options[optionId].selections,\n optionQty = 0,\n canQtyCustomize = false,\n selectedIds = config.selected;\n\n switch (optionType) {\n case 'radio':\n case 'select-one':\n\n if (optionType === 'radio' && !element.is(':checked')) {\n return null;\n }\n\n qtyField = element.data('qtyField');\n qtyField.data('option', element);\n\n if (optionValue) {\n optionQty = optionConfig[optionValue].qty || 0;\n canQtyCustomize = optionConfig[optionValue].customQty === '1';\n toggleQtyField(qtyField, optionQty, optionId, optionValue, canQtyCustomize);//eslint-disable-line\n tempChanges = utils.deepClone(optionConfig[optionValue].prices);\n tempChanges = applyTierPrice(//eslint-disable-line\n tempChanges,\n optionQty,\n optionConfig[optionValue]\n );\n tempChanges = applyQty(tempChanges, optionQty);//eslint-disable-line\n } else {\n tempChanges = {};\n toggleQtyField(qtyField, '0', optionId, optionValue, false);//eslint-disable-line\n }\n optionHash = 'bundle-option-' + optionName;\n changes[optionHash] = tempChanges;\n selectedIds[optionId] = [optionValue];\n break;\n\n case 'select-multiple':\n optionValue = _.compact(optionValue);\n\n _.each(optionConfig, function (row, optionValueCode) {\n optionHash = 'bundle-option-' + optionName + '##' + optionValueCode;\n optionQty = row.qty || 0;\n tempChanges = utils.deepClone(row.prices);\n tempChanges = applyTierPrice(tempChanges, optionQty, optionConfig);//eslint-disable-line\n tempChanges = applyQty(tempChanges, optionQty);//eslint-disable-line\n changes[optionHash] = _.contains(optionValue, optionValueCode) ? tempChanges : {};\n });\n\n selectedIds[optionId] = optionValue || [];\n break;\n\n case 'checkbox':\n optionHash = 'bundle-option-' + optionName + '##' + optionValue;\n optionQty = optionConfig[optionValue].qty || 0;\n tempChanges = utils.deepClone(optionConfig[optionValue].prices);\n tempChanges = applyTierPrice(tempChanges, optionQty, optionConfig);//eslint-disable-line\n tempChanges = applyQty(tempChanges, optionQty);//eslint-disable-line\n changes[optionHash] = element.is(':checked') ? tempChanges : {};\n\n selectedIds[optionId] = selectedIds[optionId] || [];\n\n if (!_.contains(selectedIds[optionId], optionValue) && element.is(':checked')) {\n selectedIds[optionId].push(optionValue);\n } else if (!element.is(':checked')) {\n selectedIds[optionId] = _.without(selectedIds[optionId], optionValue);\n }\n break;\n\n case 'hidden':\n optionHash = 'bundle-option-' + optionName + '##' + optionValue;\n optionQty = optionConfig[optionValue].qty || 0;\n canQtyCustomize = optionConfig[optionValue].customQty === '1';\n qtyField = element.data('qtyField');\n qtyField.data('option', element);\n toggleQtyField(qtyField, optionQty, optionId, optionValue, canQtyCustomize);//eslint-disable-line\n tempChanges = utils.deepClone(optionConfig[optionValue].prices);\n tempChanges = applyTierPrice(tempChanges, optionQty, optionConfig);//eslint-disable-line\n tempChanges = applyQty(tempChanges, optionQty);//eslint-disable-line\n\n optionHash = 'bundle-option-' + optionName;\n changes[optionHash] = tempChanges;\n selectedIds[optionId] = [optionValue];\n break;\n }\n\n return changes;\n }\n\n /**\n * Check the quantity field if negative value occurs.\n *\n * @param {Object} bundleOption\n */\n function isValidQty(bundleOption) {\n var isValid = true,\n qtyElem = bundleOption.data('qtyField'),\n bundleOptionType = bundleOption.prop('type');\n\n if (['radio', 'select-one'].includes(bundleOptionType) && qtyElem.val() < 0) {\n isValid = false;\n }\n\n return isValid;\n }\n\n /**\n * Helper to toggle qty field\n * @param {jQuery} element\n * @param {String|Number} value\n * @param {String|Number} optionId\n * @param {String|Number} optionValueId\n * @param {Boolean} canEdit\n */\n function toggleQtyField(element, value, optionId, optionValueId, canEdit) {\n element\n .val(value)\n .data('optionId', optionId)\n .data('optionValueId', optionValueId)\n .attr('disabled', !canEdit);\n\n if (canEdit) {\n element.removeClass('qty-disabled');\n } else {\n element.addClass('qty-disabled');\n }\n }\n\n /**\n * Helper to multiply on qty\n *\n * @param {Object} prices\n * @param {Number} qty\n * @returns {Object}\n */\n function applyQty(prices, qty) {\n _.each(prices, function (everyPrice) {\n everyPrice.amount *= qty;\n _.each(everyPrice.adjustments, function (el, index) {\n everyPrice.adjustments[index] *= qty;\n });\n });\n\n return prices;\n }\n\n /**\n * Helper to limit price with tier price\n *\n * @param {Object} oneItemPrice\n * @param {Number} qty\n * @param {Object} optionConfig\n * @returns {Object}\n */\n function applyTierPrice(oneItemPrice, qty, optionConfig) {\n var tiers = optionConfig.tierPrice,\n magicKey = _.keys(oneItemPrice)[0],\n tiersFirstKey = _.keys(optionConfig)[0],\n lowest = false;\n\n if (!tiers) {//tiers is undefined when options has only one option\n tiers = optionConfig[tiersFirstKey].tierPrice;\n }\n\n tiers.sort(function (a, b) {//sorting based on \"price_qty\"\n return a['price_qty'] - b['price_qty'];\n });\n\n _.each(tiers, function (tier, index) {\n if (tier['price_qty'] > qty) {\n return;\n }\n\n if (tier.prices[magicKey].amount < oneItemPrice[magicKey].amount) {\n lowest = index;\n }\n });\n\n if (lowest !== false) {\n oneItemPrice = utils.deepClone(tiers[lowest].prices);\n }\n\n return oneItemPrice;\n }\n});\n","Magento_Bundle/js/product-summary.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'jquery',\n 'mage/template',\n 'jquery-ui-modules/widget',\n 'Magento_Bundle/js/price-bundle'\n], function ($, mageTemplate) {\n 'use strict';\n\n /**\n * Widget product Summary:\n * Handles rendering of Bundle options and displays them in the Summary box\n */\n $.widget('mage.productSummary', {\n options: {\n mainContainer: '#product_addtocart_form',\n templates: {\n summaryBlock: '[data-template=\"bundle-summary\"]',\n optionBlock: '[data-template=\"bundle-option\"]'\n },\n optionSelector: '[data-container=\"options\"]',\n summaryContainer: '[data-container=\"product-summary\"]',\n bundleSummaryContainer: '.bundle-summary'\n },\n cache: {},\n\n /**\n * Method attaches event observer to the product form\n * @private\n */\n _create: function () {\n this.element\n .closest(this.options.mainContainer)\n .on('updateProductSummary', $.proxy(this._renderSummaryBox, this))\n .priceBundle({})\n ;\n },\n\n /**\n * Method extracts data from the event and renders Summary box\n * using jQuery template mechanism\n * @param {Event} event\n * @param {Object} data\n * @private\n */\n _renderSummaryBox: function (event, data) {\n this.cache.currentElement = data.config;\n this.cache.currentElementCount = 0;\n\n // Clear Summary box\n this.element.html('');\n this.cache.currentElement.positions.forEach(function (optionId) {\n this._renderOption(optionId, this.cache.currentElement.selected[optionId]);\n }, this);\n this.element\n .parents(this.options.bundleSummaryContainer)\n .toggleClass('empty', !this.cache.currentElementCount); // Zero elements equal '.empty' container\n },\n\n /**\n * @param {String} key\n * @param {String} row\n * @private\n */\n _renderOption: function (key, row) {\n var template;\n\n if (row && row.length > 0 && row[0] !== null) {\n template = this.element\n .closest(this.options.summaryContainer)\n .find(this.options.templates.summaryBlock)\n .html();\n template = mageTemplate(template.trim(), {\n data: {\n _label_: this.cache.currentElement.options[key].title\n }\n });\n\n this.cache.currentKey = key;\n this.cache.summaryContainer = $(template);\n this.element.append(this.cache.summaryContainer);\n\n $.each(row, this._renderOptionRow.bind(this));\n this.cache.currentElementCount += row.length;\n\n //Reset Cache\n this.cache.currentKey = null;\n }\n },\n\n /**\n * @param {String} key\n * @param {String} optionIndex\n * @private\n */\n _renderOptionRow: function (key, optionIndex) {\n var template;\n\n template = this.element\n .closest(this.options.summaryContainer)\n .find(this.options.templates.optionBlock)\n .html();\n template = mageTemplate(template.trim(), {\n data: {\n _quantity_: this.cache.currentElement.options[this.cache.currentKey].selections[optionIndex].qty,\n _label_: this.cache.currentElement.options[this.cache.currentKey].selections[optionIndex].name\n }\n });\n this.cache.summaryContainer\n .find(this.options.optionSelector)\n .append(template);\n }\n });\n\n return $.mage.productSummary;\n});\n","Magento_Bundle/js/slide.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'jquery',\n 'jquery-ui-modules/widget'\n], function ($) {\n 'use strict';\n\n $.widget('mage.slide', {\n options: {\n slideSpeed: 1500,\n slideSelector: '#bundle-slide',\n slideBackSelector: '.bundle-slide-back',\n bundleProductSelector: '#bundleProduct',\n bundleOptionsContainer: '#options-container',\n productViewContainer: '#productView',\n slidedown: true\n\n },\n\n /** @inheritdoc */\n _create: function () {\n if (this.options.slidedown === true) {\n $(this.options.slideSelector).on('click', $.proxy(this._show, this));\n $(this.options.slideBackSelector).on('click', $.proxy(this._hide, this));\n this.options.autostart && this._show();\n } else {\n $(this.options.slideSelector).on('click', $.proxy(this._slide, this));\n $(this.options.slideBackSelector).on('click', $.proxy(this._slideBack, this));\n this.options.autostart && this._slide();\n }\n },\n\n /**\n * slide bundleOptionsContainer over to the main view area\n * @private\n */\n _slide: function () {\n $(this.options.bundleProductSelector).css('top', '0px');\n $(this.options.bundleOptionsContainer).show();\n this.element.css('height', $(this.options.productViewContainer).height() + 'px');\n $(this.options.bundleProductSelector).css('left', '0px').animate(\n {\n 'left': '-' + this.element.width() + 'px'\n },\n this.options.slideSpeed,\n $.proxy(function () {\n this.element.css('height', 'auto');\n $(this.options.productViewContainer).hide();\n }, this)\n );\n },\n\n /**\n * slideback productViewContainer to main view area\n * @private\n */\n _slideBack: function () {\n $(this.options.bundleProductSelector).css('top', '0px');\n $(this.options.productViewContainer).show();\n this.element.css('height', $(this.options.bundleOptionsContainer).height() + 'px');\n $(this.options.bundleProductSelector).animate(\n {\n 'left': '0px'\n },\n this.options.slideSpeed,\n $.proxy(function () {\n $(this.options.bundleOptionsContainer).hide();\n this.element.css('height', 'auto');\n }, this)\n );\n },\n\n /**\n * @private\n */\n _show: function () {\n $(this.options.bundleOptionsContainer).slideDown(800);\n $('html, body').animate({\n scrollTop: $(this.options.bundleOptionsContainer).offset().top\n }, 600);\n $('#product-options-wrapper > fieldset').trigger('focus');\n },\n\n /**\n * @private\n */\n _hide: function () {\n $('html, body').animate({\n scrollTop: 0\n }, 600);\n $(this.options.bundleOptionsContainer).slideUp(800);\n }\n });\n\n return $.mage.slide;\n});\n","Magento_Newsletter/js/subscription-status-resolver.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'mage/url'\n], function ($, urlBuilder) {\n 'use strict';\n\n return function (email, deferred) {\n return $.getJSON(\n urlBuilder.build('newsletter/ajax/status'),\n {\n email: email\n }\n ).done(function (response) {\n if (response.errors) {\n deferred.reject();\n } else {\n deferred.resolve(response.subscribed);\n }\n }).fail(function () {\n deferred.reject();\n });\n };\n});\n","Magento_Newsletter/js/newsletter-sign-up.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'uiElement',\n 'mage/url',\n 'subscriptionStatusResolver',\n 'mage/validation'\n], function ($, Component, urlBuilder, subscriptionStatusResolver) {\n 'use strict';\n\n return Component.extend({\n\n defaults: {\n signUpElement: '',\n submitButton: '',\n element: null\n },\n\n /** @inheritdoc */\n initialize: function (config, element) {\n this._super();\n this.element = element;\n $(element).on('change', $.proxy(this.updateSignUpStatus, this));\n this.updateSignUpStatus();\n },\n\n /**\n * Send status request and update subscription element according to result.\n */\n updateSignUpStatus: function () {\n var element = $(this.element),\n email = element.val(),\n self = this,\n newsletterSubscription;\n\n if ($(self.signUpElement).is(':checked')) {\n return;\n }\n\n if (!email || !$.validator.methods['validate-email'].call(this, email, element)) {\n return;\n }\n\n newsletterSubscription = $.Deferred();\n\n $(self.submitButton).prop('disabled', true);\n\n subscriptionStatusResolver(email, newsletterSubscription);\n\n $.when(newsletterSubscription).done(function (isSubscribed) {\n if (isSubscribed) {\n $(self.signUpElement).prop('checked', true);\n }\n }).always(function () {\n $(self.submitButton).prop('disabled', false);\n });\n }\n });\n});\n","Magento_Ui/js/block-loader.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'ko',\n 'jquery',\n 'Magento_Ui/js/lib/knockout/template/loader',\n 'mage/template'\n], function (ko, $, templateLoader, template) {\n 'use strict';\n\n var blockLoaderTemplatePath = 'ui/block-loader',\n blockContentLoadingClass = '_block-content-loading',\n blockLoader,\n blockLoaderClass,\n blockLoaderElement = $.Deferred(),\n loaderImageHref = $.Deferred();\n\n templateLoader.loadTemplate(blockLoaderTemplatePath).done(function (blockLoaderTemplate) {\n loaderImageHref.done(function (loaderHref) {\n blockLoader = template(blockLoaderTemplate.trim(), {\n loaderImageHref: loaderHref\n });\n blockLoader = $(blockLoader);\n blockLoaderClass = '.' + blockLoader.attr('class');\n blockLoaderElement.resolve();\n });\n });\n\n /**\n * Helper function to check if blockContentLoading class should be applied.\n * @param {Object} element\n * @returns {Boolean}\n */\n function isLoadingClassRequired(element) {\n var position = element.css('position');\n\n if (position === 'absolute' || position === 'fixed') {\n return false;\n }\n\n return true;\n }\n\n /**\n * Add loader to block.\n * @param {Object} element\n */\n function addBlockLoader(element) {\n element.find(':focus').trigger('blur');\n element.find('input:disabled, select:disabled').addClass('_disabled');\n element.find('input, select').prop('disabled', true);\n\n if (isLoadingClassRequired(element)) {\n element.addClass(blockContentLoadingClass);\n }\n element.append(blockLoader.clone());\n }\n\n /**\n * Remove loader from block.\n * @param {Object} element\n */\n function removeBlockLoader(element) {\n if (!element.has(blockLoaderClass).length) {\n return;\n }\n element.find(blockLoaderClass).remove();\n element.find('input:not(\"._disabled\"), select:not(\"._disabled\")').prop('disabled', false);\n element.find('input:disabled, select:disabled').removeClass('_disabled');\n element.removeClass(blockContentLoadingClass);\n }\n\n return function (loaderHref) {\n loaderImageHref.resolve(loaderHref);\n ko.bindingHandlers.blockLoader = {\n /**\n * Process loader for block\n * @param {String} element\n * @param {Boolean} displayBlockLoader\n */\n update: function (element, displayBlockLoader) {\n element = $(element);\n\n if (ko.unwrap(displayBlockLoader())) {\n blockLoaderElement.done(addBlockLoader(element));\n } else {\n blockLoaderElement.done(removeBlockLoader(element));\n }\n }\n };\n };\n});\n","Magento_Ui/js/form/button-adapter.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'uiClass',\n 'jquery',\n 'underscore',\n 'uiRegistry'\n], function (Class, $, _, registry) {\n 'use strict';\n\n return Class.extend({\n\n /**\n * Initialize actions and adapter.\n *\n * @param {Object} config\n * @param {Element} elem\n * @returns {Object}\n */\n initialize: function (config, elem) {\n return this._super()\n .initActions()\n .initAdapter(elem);\n },\n\n /**\n * Creates callback from declared actions.\n *\n * @returns {Object}\n */\n initActions: function () {\n var callbacks = [];\n\n _.each(this.actions, function (action) {\n callbacks.push({\n action: registry.async(action.targetName),\n args: _.union([action.actionName], action.params)\n });\n });\n\n /**\n * Callback function.\n */\n this.callback = function () {\n _.each(callbacks, function (callback) {\n callback.action.apply(callback.action, callback.args);\n });\n };\n\n return this;\n },\n\n /**\n * Attach callback handler on button.\n *\n * @param {Element} elem\n */\n initAdapter: function (elem) {\n $(elem).on('click', this.callback);\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/switcher.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'uiRegistry',\n 'uiClass'\n], function (_, registry, Class) {\n 'use strict';\n\n return Class.extend({\n defaults: {\n rules: []\n },\n\n /**\n * Initializes instance of a DataSwitcher.\n *\n * @returns {DataSwitcher} Chainable.\n */\n initialize: function () {\n this._super()\n .initRules();\n\n return this;\n },\n\n /**\n *\n * @returns {DataSwitcher} Chainable.\n */\n initRules: function () {\n this.rules.forEach(this.initRule, this);\n\n return this;\n },\n\n /**\n *\n * @param {Object} rule - Rule definition.\n * @returns {DataSwitcher} Chainable.\n */\n initRule: function (rule) {\n var handler = this.onValueChange.bind(this, rule);\n\n if (!rule.target) {\n rule.target = this.target;\n }\n\n if (!rule.property) {\n rule.property = this.property;\n }\n\n registry.get(rule.target, function (target) {\n this.applyRule(rule, target.get(rule.property));\n target.on(rule.property, handler);\n }.bind(this));\n\n return this;\n },\n\n /**\n *\n * @param {Object} rule - Rule definition.\n * @returns {DataSwitcher} Chainable.\n */\n addRule: function (rule) {\n this.rules.push(rule);\n this.initRule(rule);\n\n return this;\n },\n\n /**\n *\n * @param {Object} rule - Rule object.\n * @param {*} value - Current value associated with a rule.\n */\n applyRule: function (rule, value) {\n var actions = rule.actions;\n\n //TODO Refactor this logic in scope of MAGETWO-48585\n /* eslint-disable eqeqeq */\n if (rule.value != value) {\n return;\n } else if (rule.strict) {\n return;\n }\n\n /* eslint-enable eqeqeq */\n actions.forEach(this.applyAction, this);\n },\n\n /**\n *\n * @param {Object} action - Action object.\n */\n applyAction: function (action) {\n registry.get(action.target, function (target) {\n var callback = target[action.callback];\n\n callback.apply(target, action.params || []);\n });\n },\n\n /**\n *\n * @param {Object} rule - Rules object.\n * @param {*} value - Current value associated with a rule.\n */\n onValueChange: function (rule, value) {\n this.applyRule(rule, value);\n }\n });\n});\n","Magento_Ui/js/form/form.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'Magento_Ui/js/lib/spinner',\n 'rjsResolver',\n './adapter',\n 'uiCollection',\n 'mageUtils',\n 'jquery',\n 'Magento_Ui/js/core/app',\n 'mage/validation'\n], function (_, loader, resolver, adapter, Collection, utils, $, app) {\n 'use strict';\n\n /**\n * Format params\n *\n * @param {Object} params\n * @returns {Array}\n */\n function prepareParams(params) {\n var result = '?';\n\n _.each(params, function (value, key) {\n result += key + '=' + value + '&';\n });\n\n return result.slice(0, -1);\n }\n\n /**\n * Collect form data.\n *\n * @param {Array} items\n * @returns {Object}\n */\n function collectData(items) {\n var result = {},\n name;\n\n items = Array.prototype.slice.call(items);\n\n items.forEach(function (item) {\n switch (item.type) {\n case 'checkbox':\n result[item.name] = +!!item.checked;\n break;\n\n case 'radio':\n if (item.checked) {\n result[item.name] = item.value;\n }\n break;\n\n case 'select-multiple':\n name = item.name.substring(0, item.name.length - 2); //remove [] from the name ending\n result[name] = _.pluck(item.selectedOptions, 'value');\n break;\n\n default:\n result[item.name] = item.value;\n }\n });\n\n return result;\n }\n\n /**\n * Makes ajax request\n *\n * @param {Object} params\n * @param {Object} data\n * @param {String} url\n * @returns {*}\n */\n function makeRequest(params, data, url) {\n var save = $.Deferred();\n\n data = utils.serialize(data);\n data['form_key'] = window.FORM_KEY;\n\n if (!url) {\n save.resolve();\n }\n\n $('body').trigger('processStart');\n\n $.ajax({\n url: url + prepareParams(params),\n data: data,\n dataType: 'json',\n\n /**\n * Success callback.\n * @param {Object} resp\n * @returns {Boolean}\n */\n success: function (resp) {\n if (resp.ajaxExpired) {\n window.location.href = resp.ajaxRedirect;\n }\n\n if (!resp.error) {\n save.resolve(resp);\n\n return true;\n }\n\n $('body').notification('clear');\n $.each(resp.messages, function (key, message) {\n $('body').notification('add', {\n error: resp.error,\n message: message,\n\n /**\n * Inserts message on page\n * @param {String} msg\n */\n insertMethod: function (msg) {\n $('.page-main-actions').after(msg);\n }\n });\n });\n },\n\n /**\n * Complete callback.\n */\n complete: function () {\n $('body').trigger('processStop');\n }\n });\n\n return save.promise();\n }\n\n /**\n * Check if fields is valid.\n *\n * @param {Array}items\n * @returns {Boolean}\n */\n function isValidFields(items) {\n var result = true;\n\n _.each(items, function (item) {\n if (!$.validator.validateSingleElement(item)) {\n result = false;\n }\n });\n\n return result;\n }\n\n return Collection.extend({\n defaults: {\n additionalFields: [],\n additionalInvalid: false,\n selectorPrefix: '.page-content',\n messagesClass: 'messages',\n errorClass: '.admin__field._error',\n eventPrefix: '.${ $.index }',\n ajaxSave: false,\n ajaxSaveType: 'default',\n imports: {\n reloadUrl: '${ $.provider}:reloadUrl'\n },\n listens: {\n selectorPrefix: 'destroyAdapter initAdapter',\n '${ $.name }.${ $.reloadItem }': 'params.set reload'\n },\n exports: {\n selectorPrefix: '${ $.provider }:client.selectorPrefix',\n messagesClass: '${ $.provider }:client.messagesClass'\n }\n },\n\n /** @inheritdoc */\n initialize: function () {\n this._super()\n .initAdapter();\n\n resolver(this.hideLoader, this);\n\n return this;\n },\n\n /** @inheritdoc */\n initObservable: function () {\n return this._super()\n .observe([\n 'responseData',\n 'responseStatus'\n ]);\n },\n\n /** @inheritdoc */\n initConfig: function () {\n this._super();\n\n this.selector = '[data-form-part=' + this.namespace + ']';\n\n return this;\n },\n\n /**\n * Initialize adapter handlers.\n *\n * @returns {Object}\n */\n initAdapter: function () {\n adapter.on({\n 'reset': this.reset.bind(this),\n 'save': this.save.bind(this, true, {}),\n 'saveAndContinue': this.save.bind(this, false, {})\n }, this.selectorPrefix, this.eventPrefix);\n\n return this;\n },\n\n /**\n * Destroy adapter handlers.\n *\n * @returns {Object}\n */\n destroyAdapter: function () {\n adapter.off([\n 'reset',\n 'save',\n 'saveAndContinue'\n ], this.eventPrefix);\n\n return this;\n },\n\n /**\n * Hide loader.\n *\n * @returns {Object}\n */\n hideLoader: function () {\n loader.get(this.name).hide();\n\n return this;\n },\n\n /**\n * Validate and save form.\n *\n * @param {String} redirect\n * @param {Object} data\n */\n save: function (redirect, data) {\n this.validate();\n\n if (!this.additionalInvalid && !this.source.get('params.invalid')) {\n this.setAdditionalData(data)\n .submit(redirect);\n } else {\n this.focusInvalid();\n }\n },\n\n /**\n * Tries to set focus on first invalid form field.\n *\n * @returns {Object}\n */\n focusInvalid: function () {\n var invalidField = _.find(this.delegate('checkInvalid'));\n\n if (!_.isUndefined(invalidField) && _.isFunction(invalidField.focused)) {\n invalidField.focused(true);\n }\n\n return this;\n },\n\n /**\n * Set additional data to source before form submit and after validation.\n *\n * @param {Object} data\n * @returns {Object}\n */\n setAdditionalData: function (data) {\n _.each(data, function (value, name) {\n this.source.set('data.' + name, value);\n }, this);\n\n return this;\n },\n\n /**\n * Submits form\n *\n * @param {String} redirect\n */\n submit: function (redirect) {\n var additional = collectData(this.additionalFields),\n source = this.source;\n\n _.each(additional, function (value, name) {\n source.set('data.' + name, value);\n });\n\n source.save({\n redirect: redirect,\n ajaxSave: this.ajaxSave,\n ajaxSaveType: this.ajaxSaveType,\n response: {\n data: this.responseData,\n status: this.responseStatus\n },\n attributes: {\n id: this.namespace\n }\n });\n },\n\n /**\n * Validates each element and returns true, if all elements are valid.\n */\n validate: function () {\n this.additionalFields = document.querySelectorAll(this.selector);\n this.source.set('params.invalid', false);\n this.source.trigger('data.validate');\n this.set('additionalInvalid', !isValidFields(this.additionalFields));\n },\n\n /**\n * Trigger reset form data.\n */\n reset: function () {\n this.source.trigger('data.reset');\n $('[data-bind*=datepicker]').val('');\n },\n\n /**\n * Trigger overload form data.\n */\n overload: function () {\n this.source.trigger('data.overload');\n },\n\n /**\n * Updates data from server.\n */\n reload: function () {\n makeRequest(this.params, this.data, this.reloadUrl).then(function (data) {\n app(data, true);\n });\n }\n });\n});\n","Magento_Ui/js/form/client.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'underscore',\n 'mageUtils',\n 'uiClass'\n], function ($, _, utils, Class) {\n 'use strict';\n\n /**\n * Before save validate request.\n *\n * @param {Object} data\n * @param {String} url\n * @param {String} selectorPrefix\n * @param {String} messagesClass\n * @returns {*}\n */\n function beforeSave(data, url, selectorPrefix, messagesClass) {\n var save = $.Deferred();\n\n data = utils.serialize(utils.filterFormData(data));\n data['form_key'] = window.FORM_KEY;\n\n if (!url || url === 'undefined') {\n return save.resolve();\n }\n\n $('body').trigger('processStart');\n\n $.ajax({\n url: url,\n data: data,\n\n /**\n * Success callback.\n * @param {Object} resp\n * @returns {Boolean}\n */\n success: function (resp) {\n if (!resp.error) {\n save.resolve();\n\n return true;\n }\n\n $('body').notification('clear');\n $.each(resp.messages || [resp.message] || [], function (key, message) {\n $('body').notification('add', {\n error: resp.error,\n message: message,\n\n /**\n * Insert method.\n *\n * @param {String} msg\n */\n insertMethod: function (msg) {\n var $wrapper = $('<div></div>').addClass(messagesClass).html(msg);\n\n $('.page-main-actions', selectorPrefix).after($wrapper);\n $('html, body').animate({\n scrollTop: $('.page-main-actions', selectorPrefix).offset().top\n });\n }\n });\n });\n },\n\n /**\n * Complete callback.\n */\n complete: function () {\n $('body').trigger('processStop');\n }\n });\n\n return save.promise();\n }\n\n return Class.extend({\n\n /**\n * Assembles data and submits it using 'utils.submit' method\n */\n save: function (data, options) {\n var url = this.urls.beforeSave,\n save = this._save.bind(this, data, options);\n\n beforeSave(data, url, this.selectorPrefix, this.messagesClass).then(save);\n\n return this;\n },\n\n /**\n * Save data.\n *\n * @param {Object} data\n * @param {Object} options\n * @returns {Object}\n * @private\n */\n _save: function (data, options) {\n var url = this.urls.save;\n\n $('body').trigger('processStart');\n options = options || {};\n\n if (!options.redirect) {\n url += 'back/edit';\n }\n\n if (options.ajaxSave) {\n utils.ajaxSubmit({\n url: url,\n data: data\n }, options);\n\n $('body').trigger('processStop');\n\n return this;\n }\n\n utils.submit({\n url: url,\n data: data\n }, options.attributes);\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/adapter.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'jquery',\n 'underscore',\n 'Magento_Ui/js/form/adapter/buttons'\n], function ($, _, buttons) {\n 'use strict';\n\n var selectorPrefix = '',\n eventPrefix;\n\n /**\n * Initialize listener.\n *\n * @param {Function} callback\n * @param {String} action\n */\n function initListener(callback, action) {\n var selector = selectorPrefix ? selectorPrefix + ' ' + buttons[action] : buttons[action],\n elem = $(selector)[0];\n\n if (!elem) {\n return;\n }\n\n if (elem.onclick) {\n elem.onclick = null;\n }\n\n $(elem).on('click' + eventPrefix, callback);\n }\n\n /**\n * Destroy listener.\n *\n * @param {String} action\n */\n function destroyListener(action) {\n var selector = selectorPrefix ? selectorPrefix + ' ' + buttons[action] : buttons[action],\n elem = $(selector)[0];\n\n if (!elem) {\n return;\n }\n\n if (elem.onclick) {\n elem.onclick = null;\n }\n\n $(elem).off('click' + eventPrefix);\n }\n\n return {\n\n /**\n * Attaches events handlers.\n *\n * @param {Object} handlers\n * @param {String} selectorPref\n * @param {String} eventPref\n */\n on: function (handlers, selectorPref, eventPref) {\n selectorPrefix = selectorPrefix || selectorPref;\n eventPrefix = eventPref;\n _.each(handlers, initListener);\n selectorPrefix = '';\n },\n\n /**\n * Removes events handlers.\n *\n * @param {Object} handlers\n * @param {String} eventPref\n */\n off: function (handlers, eventPref) {\n eventPrefix = eventPref;\n _.each(handlers, destroyListener);\n }\n };\n});\n","Magento_Ui/js/form/provider.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'uiElement',\n './client',\n 'mageUtils'\n], function (_, Element, Client, utils) {\n 'use strict';\n\n return Element.extend({\n defaults: {\n clientConfig: {\n urls: {\n save: '${ $.submit_url }',\n beforeSave: '${ $.validate_url }'\n }\n },\n ignoreTmpls: {\n data: true\n }\n },\n\n /**\n * Initializes provider component.\n *\n * @returns {Provider} Chainable.\n */\n initialize: function () {\n this._super()\n .initClient();\n\n return this;\n },\n\n /**\n * Initializes client component.\n *\n * @returns {Provider} Chainable.\n */\n initClient: function () {\n this.client = new Client(this.clientConfig);\n\n return this;\n },\n\n /**\n * Saves currently available data.\n *\n * @param {Object} [options] - Addtitional request options.\n * @returns {Provider} Chainable.\n */\n save: function (options) {\n var data = this.get('data');\n\n this.client.save(data, options);\n\n return this;\n },\n\n /**\n * Update data that stored in provider.\n *\n * @param {Boolean} isProvider\n * @param {Object} newData\n * @param {Object} oldData\n *\n * @returns {Provider}\n */\n updateConfig: function (isProvider, newData, oldData) {\n if (isProvider === true) {\n this.setData(oldData, newData, this);\n }\n\n return this;\n },\n\n /**\n * Set data to provider based on current data.\n *\n * @param {Object} oldData\n * @param {Object} newData\n * @param {Provider} current\n * @param {String} parentPath\n */\n setData: function (oldData, newData, current, parentPath) {\n _.each(newData, function (val, key) {\n if (_.isObject(val) || _.isArray(val)) {\n this.setData(oldData[key], val, current[key], utils.fullPath(parentPath, key));\n } else if (val != oldData[key] && oldData[key] == current[key]) {//eslint-disable-line eqeqeq\n this.set(utils.fullPath(parentPath, key), val);\n }\n }, this);\n }\n });\n});\n","Magento_Ui/js/form/adapter/buttons.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine(function () {\n 'use strict';\n\n return {\n 'reset': '#reset',\n 'save': '#save',\n 'saveAndContinue': '#save_and_continue'\n };\n});\n","Magento_Ui/js/form/components/fieldset.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'Magento_Ui/js/lib/collapsible',\n 'underscore'\n], function (Collapsible, _) {\n 'use strict';\n\n return Collapsible.extend({\n defaults: {\n template: 'ui/form/fieldset',\n collapsible: false,\n changed: false,\n loading: false,\n error: false,\n opened: false,\n level: 0,\n visible: true,\n initializeFieldsetDataByDefault: false, /* Data in some fieldsets should be initialized before open */\n disabled: false,\n listens: {\n 'opened': 'onVisibilityChange'\n },\n additionalClasses: {}\n },\n\n /**\n * Extends instance with defaults. Invokes parent initialize method.\n * Calls initListeners and pushParams methods.\n */\n initialize: function () {\n _.bindAll(this, 'onChildrenUpdate', 'onChildrenError', 'onContentLoading');\n\n return this._super()\n ._setClasses();\n },\n\n /**\n * Initializes components' configuration.\n *\n * @returns {Fieldset} Chainable.\n */\n initConfig: function () {\n this._super();\n this._wasOpened = this.opened || !this.collapsible;\n\n return this;\n },\n\n /**\n * Calls initObservable of parent class.\n * Defines observable properties of instance.\n *\n * @returns {Object} Reference to instance\n */\n initObservable: function () {\n this._super()\n .observe('changed loading error visible');\n\n return this;\n },\n\n /**\n * Calls parent's initElement method.\n * Assigns callbacks on various events of incoming element.\n *\n * @param {Object} elem\n * @return {Object} - reference to instance\n */\n initElement: function (elem) {\n elem.initContainer(this);\n\n elem.on({\n 'update': this.onChildrenUpdate,\n 'loading': this.onContentLoading,\n 'error': this.onChildrenError\n });\n\n if (this.disabled) {\n try {\n elem.disabled(true);\n }\n catch (e) {\n\n }\n }\n\n return this;\n },\n\n /**\n * Is being invoked on children update.\n * Sets changed property to one incoming.\n *\n * @param {Boolean} hasChanged\n */\n onChildrenUpdate: function (hasChanged) {\n if (!hasChanged) {\n hasChanged = _.some(this.delegate('hasChanged'));\n }\n\n this.bubble('update', hasChanged);\n this.changed(hasChanged);\n },\n\n /**\n * Extends 'additionalClasses' object.\n *\n * @returns {Group} Chainable.\n */\n _setClasses: function () {\n var additional = this.additionalClasses,\n classes;\n\n if (_.isString(additional)) {\n additional = this.additionalClasses.split(' ');\n classes = this.additionalClasses = {};\n\n additional.forEach(function (name) {\n classes[name] = true;\n }, this);\n }\n\n _.extend(this.additionalClasses, {\n 'admin__collapsible-block-wrapper': this.collapsible,\n _show: this.opened,\n _hide: !this.opened,\n _disabled: this.disabled\n });\n\n return this;\n },\n\n /**\n * Handler of the \"opened\" property changes.\n *\n * @param {Boolean} isOpened\n */\n onVisibilityChange: function (isOpened) {\n if (!this._wasOpened) {\n this._wasOpened = isOpened;\n }\n },\n\n /**\n * Is being invoked on children validation error.\n * Sets error property to one incoming.\n *\n * @param {String} message - error message.\n */\n onChildrenError: function (message) {\n var hasErrors = false;\n\n if (!message) {\n hasErrors = this._isChildrenHasErrors(hasErrors, this);\n }\n\n this.error(hasErrors || message);\n\n if (hasErrors || message) {\n this.open();\n }\n },\n\n /**\n * Returns errors of children if exist\n *\n * @param {Boolean} hasErrors\n * @param {*} container\n * @return {Boolean}\n * @private\n */\n _isChildrenHasErrors: function (hasErrors, container) {\n var self = this;\n\n if (hasErrors === false && container.hasOwnProperty('elems')) {\n hasErrors = container.elems.some('error');\n\n if (hasErrors === false && container.hasOwnProperty('_elems')) {\n container._elems.forEach(function (child) {\n\n if (hasErrors === false) {\n hasErrors = self._isChildrenHasErrors(hasErrors, child);\n }\n });\n }\n }\n\n return hasErrors;\n },\n\n /**\n * Callback that sets loading property to true.\n */\n onContentLoading: function (isLoading) {\n this.loading(isLoading);\n }\n });\n});\n","Magento_Ui/js/form/components/button.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'uiElement',\n 'uiRegistry',\n 'uiLayout',\n 'mageUtils',\n 'underscore'\n], function (Element, registry, layout, utils, _) {\n 'use strict';\n\n return Element.extend({\n defaults: {\n buttonClasses: {},\n additionalClasses: {},\n displayArea: 'outsideGroup',\n displayAsLink: false,\n elementTmpl: 'ui/form/element/button',\n template: 'ui/form/components/button/simple',\n visible: true,\n disabled: false,\n title: '',\n buttonTextId: '',\n ariLabelledby: ''\n },\n\n /**\n * Initializes component.\n *\n * @returns {Object} Chainable.\n */\n initialize: function () {\n return this._super()\n ._setClasses()\n ._setButtonClasses();\n },\n\n /** @inheritdoc */\n initObservable: function () {\n return this._super()\n .observe([\n 'visible',\n 'disabled',\n 'title',\n 'childError'\n ]);\n },\n\n /**\n * Performs configured actions\n */\n action: function () {\n this.actions.forEach(this.applyAction, this);\n },\n\n /**\n * Apply action on target component,\n * but previously create this component from template if it is not existed\n *\n * @param {Object} action - action configuration\n */\n applyAction: function (action) {\n var targetName = action.targetName,\n params = utils.copy(action.params) || [],\n actionName = action.actionName,\n target;\n\n if (!registry.has(targetName)) {\n this.getFromTemplate(targetName);\n }\n target = registry.async(targetName);\n\n if (target && typeof target === 'function' && actionName) {\n params.unshift(actionName);\n target.apply(target, params);\n }\n },\n\n /**\n * Create target component from template\n *\n * @param {Object} targetName - name of component,\n * that supposed to be a template and need to be initialized\n */\n getFromTemplate: function (targetName) {\n var parentName = targetName.split('.'),\n index = parentName.pop(),\n child;\n\n parentName = parentName.join('.');\n child = utils.template({\n parent: parentName,\n name: index,\n nodeTemplate: targetName\n });\n layout([child]);\n },\n\n /**\n * Extends 'additionalClasses' object.\n *\n * @returns {Object} Chainable.\n */\n _setClasses: function () {\n if (typeof this.additionalClasses === 'string') {\n if (this.additionalClasses === '') {\n this.additionalClasses = {};\n\n return this;\n }\n\n this.additionalClasses = this.additionalClasses\n .trim()\n .split(' ')\n .reduce(function (classes, name) {\n classes[name] = true;\n\n return classes;\n }, {}\n );\n }\n\n return this;\n },\n\n /**\n * Extends 'buttonClasses' object.\n *\n * @returns {Object} Chainable.\n */\n _setButtonClasses: function () {\n var additional = this.buttonClasses;\n\n if (_.isString(additional)) {\n this.buttonClasses = {};\n\n if (additional.trim().length) {\n additional = additional.trim().split(' ');\n\n additional.forEach(function (name) {\n if (name.length) {\n this.buttonClasses[name] = true;\n }\n }, this);\n }\n }\n\n _.extend(this.buttonClasses, {\n 'action-basic': !this.displayAsLink,\n 'action-additional': this.displayAsLink\n });\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/components/tab.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'uiCollection'\n], function (Collection) {\n 'use strict';\n\n return Collection.extend({\n defaults: {\n uniqueProp: 'active',\n active: false,\n wasActivated: false\n },\n\n /**\n * Extends instance with defaults. Invokes parent initialize method.\n * Calls initListeners and pushParams methods.\n */\n initialize: function () {\n this._super()\n .setUnique();\n },\n\n /**\n * Calls initObservable of parent class.\n * Defines observable properties of instance.\n * @return {Object} - reference to instance\n */\n initObservable: function () {\n this._super()\n .observe('active wasActivated');\n\n return this;\n },\n\n /**\n * Sets active property to true, then invokes pushParams method.\n */\n activate: function () {\n this.active(true);\n this.wasActivated(true);\n\n this.setUnique();\n\n return true;\n }\n });\n});\n","Magento_Ui/js/form/components/html.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'jquery',\n 'underscore',\n 'uiComponent'\n], function ($, _, Component) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n content: '',\n showSpinner: false,\n loading: false,\n visible: true,\n template: 'ui/content/content',\n additionalClasses: {},\n ignoreTmpls: {\n content: true\n }\n },\n\n /**\n * Extends instance with default config, calls 'initialize' method of\n * parent, calls 'initAjaxConfig'\n */\n initialize: function () {\n _.bindAll(this, 'onContainerToggle', 'onDataLoaded');\n\n this._super()\n ._setClasses()\n .initAjaxConfig();\n\n return this;\n },\n\n /**\n * Calls 'initObservable' method of parent, initializes observable\n * properties of instance\n *\n * @return {Object} - reference to instance\n */\n initObservable: function () {\n this._super()\n .observe('content loading visible');\n\n return this;\n },\n\n /**\n * Extends 'additionalClasses' object.\n *\n * @returns {Group} Chainable.\n */\n _setClasses: function () {\n var additional = this.additionalClasses,\n classes;\n\n if (_.isString(additional)) {\n additional = this.additionalClasses.split(' ');\n classes = this.additionalClasses = {};\n\n additional.forEach(function (name) {\n classes[name] = true;\n }, this);\n }\n\n _.extend(this.additionalClasses, {\n 'admin__scope-old': !!additional\n });\n\n return this;\n },\n\n /** @inheritdoc */\n initContainer: function (parent) {\n this._super();\n\n parent.on('active', this.onContainerToggle);\n\n return this;\n },\n\n /**\n * Initializes default ajax config on instance\n *\n * @return {Object} - reference to instance\n */\n initAjaxConfig: function () {\n this.ajaxConfig = {\n url: this.url,\n data: {\n FORM_KEY: window.FORM_KEY\n },\n success: this.onDataLoaded\n };\n\n return this;\n },\n\n /**\n * Calls 'loadData' if both 'active' variable and 'shouldLoad'\n * property are truthy\n *\n * @param {Boolean} active\n */\n onContainerToggle: function (active) {\n if (active && this.shouldLoad()) {\n this.loadData();\n }\n },\n\n /**\n * Defines if instance has 'content' property defined.\n *\n * @return {Boolean} [description]\n */\n hasData: function () {\n return !!this.content();\n },\n\n /**\n * Defines if instance should load external data\n *\n * @return {Boolean}\n */\n shouldLoad: function () {\n return this.url && !this.hasData() && !this.loading();\n },\n\n /**\n * Sets loading property to true, makes ajax call\n *\n * @return {Object} - reference to instance\n */\n loadData: function () {\n this.loading(true);\n\n $.ajax(this.ajaxConfig);\n\n return this;\n },\n\n /**\n * Ajax's request success handler. Calls 'updateContent' passing 'data'\n * to it, then sets 'loading' property to false.\n *\n * @param {String} data\n */\n onDataLoaded: function (data) {\n this.updateContent(data)\n .loading(false);\n },\n\n /**\n * Sets incoming data 'content' property's value\n *\n * @param {String} content\n * @return {Object} - reference to instance\n */\n updateContent: function (content) {\n this.content(content);\n\n return this;\n },\n\n /**\n * Content getter\n *\n * @returns {String}\n */\n getContentUnsanitizedHtml: function () {\n return this.content();\n }\n });\n});\n","Magento_Ui/js/form/components/multiline.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n './group'\n], function (Group) {\n 'use strict';\n\n return Group.extend({\n defaults: {\n links: {\n value: '${ $.provider }:${ $.dataScope }'\n }\n },\n\n /**\n * Initialize Multiline component.\n *\n * @returns {Object}\n */\n initialize: function () {\n return this._super()\n ._prepareValue();\n },\n\n /**\n * {@inheritdoc}\n */\n initObservable: function () {\n this._super()\n .observe('value');\n\n return this;\n },\n\n /**\n * Prepare value for Multiline options.\n *\n * @returns {Object} Chainable.\n * @private\n */\n _prepareValue: function () {\n var value = this.value();\n\n if (typeof value === 'string') {\n this.value(value.split('\\n'));\n }\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/components/collection.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'mageUtils',\n 'uiRegistry',\n 'uiComponent',\n 'uiLayout',\n 'Magento_Ui/js/modal/confirm'\n], function (_, utils, registry, Component, layout, confirm) {\n 'use strict';\n\n var childTemplate = {\n parent: '${ $.$data.name }',\n name: '${ $.$data.childIndex }',\n dataScope: '${ $.name }',\n nodeTemplate: '${ $.$data.name }.${ $.$data.itemTemplate }'\n };\n\n return Component.extend({\n defaults: {\n lastIndex: 0,\n template: 'ui/form/components/collection'\n },\n\n /**\n * Extends instance with default config, calls initialize of parent\n * class, calls initChildren method.\n */\n initialize: function () {\n this._super()\n .initChildren();\n\n return this;\n },\n\n /**\n * Activates the incoming child and triggers the update event.\n *\n * @param {Object} elem - Incoming child.\n */\n initElement: function (elem) {\n this._super();\n\n elem.activate();\n\n this.bubble('update');\n\n return this;\n },\n\n /**\n * Loops over corresponding data in data storage,\n * creates child for each and pushes it's identifier to initialItems array.\n *\n * @returns {Collection} Chainable.\n */\n initChildren: function () {\n var children = this.source.get(this.dataScope),\n initial = this.initialItems = [];\n\n _.each(children, function (item, index) {\n initial.push(index);\n this.addChild(index);\n }, this);\n\n return this;\n },\n\n /**\n * Creates new item of collection, based on incoming 'index'.\n * If not passed creates one with 'new_' prefix.\n *\n * @param {String|Object} [index] - Index of a child.\n * @returns {Collection} Chainable.\n */\n addChild: function (index) {\n this.childIndex = !_.isString(index) ?\n 'new_' + this.lastIndex++ :\n index;\n\n layout([utils.template(childTemplate, this)]);\n\n return this;\n },\n\n /**\n * Returns true if current set of items differ from initial one,\n * or if some child has been changed.\n *\n * @returns {Boolean}\n */\n hasChanged: function () {\n var initial = this.initialItems,\n current = this.elems.pluck('index'),\n changed = !utils.equalArrays(initial, current);\n\n return changed || this.elems.some(function (elem) {\n return _.some(elem.delegate('hasChanged'));\n });\n },\n\n /**\n * Initiates validation of its' children components.\n *\n * @returns {Array} An array of validation results.\n */\n validate: function () {\n var elems;\n\n this.allValid = true;\n\n elems = this.elems.sortBy(function (elem) {\n return !elem.active();\n });\n\n elems = elems.map(this._validate, this);\n\n return _.flatten(elems);\n },\n\n /**\n * Iterator function for components validation.\n * Activates first invalid child component.\n *\n * @param {Object} elem - Element to run validation on.\n * @returns {Array} An array of validation results.\n */\n _validate: function (elem) {\n var result = elem.delegate('validate'),\n invalid;\n\n invalid = _.some(result, function (item) {\n return !item.valid;\n });\n\n if (this.allValid && invalid) {\n this.allValid = false;\n\n elem.activate();\n }\n\n return result;\n },\n\n /**\n * Creates function that removes element\n * from collection using '_removeChild' method.\n * @param {Object} elem - Element that should be removed.\n * @deprecated Not used anymore\n */\n removeAddress: function (elem) {\n var self = this;\n\n confirm({\n content: this.removeMessage,\n actions: {\n /** @inheritdoc */\n confirm: function () {\n self._removeAddress(elem);\n }\n }\n });\n },\n\n /**\n * Removes element from both collection and data storage,\n * activates first element if removed one was active,\n * triggers 'update' event.\n *\n * @param {Object} elem - Element to remove.\n */\n _removeAddress: function (elem) {\n var isActive = elem.active(),\n first;\n\n elem.destroy();\n\n first = this.elems.first();\n\n if (first && isActive) {\n first.activate();\n }\n\n this.bubble('update');\n }\n });\n});\n","Magento_Ui/js/form/components/area.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n './tab'\n], function (_, Tab) {\n 'use strict';\n\n return Tab.extend({\n defaults: {\n uniqueNs: 'params.activeArea',\n template: 'ui/area',\n changed: false,\n loading: false\n },\n\n /**\n * Extends instance with defaults. Invokes parent initialize method.\n * Calls initListeners and pushParams methods.\n */\n initialize: function () {\n _.bindAll(this, 'onChildrenUpdate', 'onContentLoading');\n\n return this._super();\n },\n\n /**\n * Calls initObservable of parent class.\n * Defines observable properties of instance.\n * @return {Object} - reference to instance\n */\n initObservable: function () {\n this._super()\n .observe('changed loading');\n\n return this;\n },\n\n /**\n * Calls parent's initElement method.\n * Assigns callbacks on various events of incoming element.\n * @param {Object} elem\n * @return {Object} - reference to instance\n */\n initElement: function (elem) {\n this._super();\n\n elem.on({\n 'update': this.onChildrenUpdate,\n 'loading': this.onContentLoading\n });\n\n return this;\n },\n\n /**\n * Is being invoked on children update.\n * Sets changed property to one incoming.\n * Invokes setActive method if settings\n * contain makeVisible property set to true.\n *\n * @param {Boolean} hasChanged\n */\n onChildrenUpdate: function (hasChanged) {\n if (!hasChanged) {\n hasChanged = _.some(this.delegate('hasChanged'));\n }\n\n this.changed(hasChanged);\n },\n\n /**\n * Callback that sets loading property to true.\n */\n onContentLoading: function (isLoading) {\n this.loading(isLoading);\n }\n });\n});\n","Magento_Ui/js/form/components/insert-form.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n './insert',\n 'mageUtils',\n 'jquery'\n], function (Insert, utils, $) {\n 'use strict';\n\n /**\n * Get page actions element.\n *\n * @param {String} elem\n * @param {String} actionsClass\n * @returns {String}\n */\n function getPageActions(elem, actionsClass) {\n var el = document.createElement('div');\n\n el.innerHTML = elem;\n\n return el.getElementsByClassName(actionsClass)[0];\n }\n\n /**\n * Return element without page actions toolbar\n *\n * @param {String} elem\n * @param {String} actionsClass\n * @returns {String}\n */\n function removePageActions(elem, actionsClass) {\n var el = document.createElement('div'),\n actions;\n\n el.innerHTML = elem;\n actions = el.getElementsByClassName(actionsClass)[0];\n\n if (actions) {\n el.removeChild(actions);\n }\n\n return el.innerHTML;\n }\n\n return Insert.extend({\n defaults: {\n externalFormName: '${ $.ns }.${ $.ns }',\n pageActionsClass: 'page-actions',\n actionsContainerClass: 'page-main-actions',\n exports: {\n prefix: '${ $.externalFormName }:selectorPrefix'\n },\n imports: {\n toolbarSection: '${ $.toolbarContainer }:toolbarSection',\n prefix: '${ $.toolbarContainer }:rootSelector',\n messagesClass: '${ $.externalFormName }:messagesClass'\n },\n settings: {\n ajax: {\n ajaxSave: true,\n exports: {\n ajaxSave: '${ $.externalFormName }:ajaxSave'\n },\n imports: {\n responseStatus: '${ $.externalFormName }:responseStatus',\n responseData: '${ $.externalFormName }:responseData'\n }\n }\n },\n modules: {\n externalForm: '${ $.externalFormName }'\n }\n },\n\n /** @inheritdoc */\n initObservable: function () {\n return this._super()\n .observe('responseStatus');\n },\n\n /** @inheritdoc */\n initConfig: function (config) {\n var defaults = this.constructor.defaults;\n\n utils.extend(defaults, defaults.settings[config.formSubmitType] || {});\n\n return this._super();\n },\n\n /** @inheritdoc*/\n destroyInserted: function () {\n if (this.isRendered && this.externalForm()) {\n this.externalForm().delegate('destroy');\n this.removeActions();\n this.responseStatus(undefined);\n this.responseData = {};\n }\n\n return this._super();\n },\n\n /** @inheritdoc */\n onRender: function (data) {\n var actions = getPageActions(data, this.pageActionsClass);\n\n if (!data.length) {\n return this;\n }\n data = removePageActions(data, this.pageActionsClass);\n this.renderActions(actions);\n this._super(data);\n },\n\n /**\n * Insert actions in toolbar.\n *\n * @param {String} actions\n */\n renderActions: function (actions) {\n var $container = $('<div></div>');\n\n $container\n .addClass(this.actionsContainerClass)\n .append(actions);\n\n this.formHeader = $container;\n\n $(this.toolbarSection).append(this.formHeader);\n },\n\n /**\n * Remove actions toolbar.\n */\n removeActions: function () {\n $(this.formHeader).siblings('.' + this.messagesClass).remove();\n $(this.formHeader).remove();\n this.formHeader = $();\n },\n\n /**\n * Reset external form data.\n */\n resetForm: function () {\n if (this.externalSource()) {\n this.externalSource().trigger('data.reset');\n this.responseStatus(undefined);\n }\n }\n });\n});\n","Magento_Ui/js/form/components/tab_group.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'Magento_Ui/js/lib/collapsible'\n], function (_, Collapsible) {\n 'use strict';\n\n return Collapsible.extend({\n defaults: {\n listens: {\n '${ $.provider }:data.validate': 'onValidate'\n },\n collapsible: false,\n opened: true\n },\n\n /**\n * Invokes initElement method of parent class, calls 'initActivation' method\n * passing element to it.\n * @param {Object} elem\n * @returns {Object} - reference to instance\n */\n initElement: function (elem) {\n this._super()\n .initActivation(elem);\n\n return this;\n },\n\n /**\n * Activates element if one is first or if one has 'active' propert\n * set to true.\n *\n * @param {Object} elem\n * @returns {Object} - reference to instance\n */\n initActivation: function (elem) {\n var elems = this.elems(),\n isFirst = !elems.indexOf(elem);\n\n if (isFirst || elem.active()) {\n elem.activate();\n }\n\n return this;\n },\n\n /**\n * Delegates 'validate' method on element, then reads 'invalid' property\n * of params storage, and if defined, activates element, sets\n * 'allValid' property of instance to false and sets invalid's\n * 'focused' property to true.\n *\n * @param {Object} elem\n */\n validate: function (elem) {\n var result = elem.delegate('validate'),\n invalid;\n\n invalid = _.find(result, function (item) {\n return typeof item !== 'undefined' && !item.valid;\n });\n\n if (invalid) {\n elem.activate();\n invalid.target.focused(true);\n }\n\n return invalid;\n },\n\n /**\n * Sets 'allValid' property of instance to true, then calls 'validate' method\n * of instance for each element.\n */\n onValidate: function () {\n this.elems.sortBy(function (elem) {\n return !elem.active();\n }).some(this.validate, this);\n }\n });\n});\n","Magento_Ui/js/form/components/group.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'uiCollection'\n], function (_, Collection) {\n 'use strict';\n\n return Collection.extend({\n defaults: {\n visible: true,\n label: '',\n showLabel: true,\n required: false,\n template: 'ui/group/group',\n fieldTemplate: 'ui/form/field',\n breakLine: true,\n validateWholeGroup: false,\n additionalClasses: {}\n },\n\n /**\n * Extends this with defaults and config.\n * Then calls initObservable, iniListenes and extractData methods.\n */\n initialize: function () {\n this._super()\n ._setClasses();\n\n return this;\n },\n\n /**\n * Calls initObservable of parent class.\n * Defines observable properties of instance.\n *\n * @return {Object} - reference to instance\n */\n initObservable: function () {\n this._super()\n .observe('visible')\n .observe({\n required: !!+this.required\n });\n\n return this;\n },\n\n /**\n * Extends 'additionalClasses' object.\n *\n * @returns {Group} Chainable.\n */\n _setClasses: function () {\n var additional = this.additionalClasses,\n classes;\n\n if (_.isString(additional)) {\n additional = this.additionalClasses.split(' ');\n classes = this.additionalClasses = {};\n\n additional.forEach(function (name) {\n classes[name] = true;\n }, this);\n }\n\n _.extend(this.additionalClasses, {\n 'admin__control-grouped': !this.breakLine,\n 'admin__control-fields': this.breakLine,\n required: this.required,\n _error: this.error,\n _disabled: this.disabled\n });\n\n return this;\n },\n\n /**\n * Defines if group has only one element.\n * @return {Boolean}\n */\n isSingle: function () {\n return this.elems.getLength() === 1;\n },\n\n /**\n * Defines if group has multiple elements.\n * @return {Boolean}\n */\n isMultiple: function () {\n return this.elems.getLength() > 1;\n },\n\n /**\n * Returns an array of child components previews.\n *\n * @returns {Array}\n */\n getPreview: function () {\n return this.elems.map('getPreview');\n }\n });\n});\n","Magento_Ui/js/form/components/collection/item.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'mageUtils',\n '../tab'\n], function (_, utils, Tab) {\n 'use strict';\n\n var previewConfig = {\n separator: ' ',\n prefix: ''\n };\n\n /**\n * Parses incoming data and returns result merged with default preview config\n *\n * @param {Object|String} data\n * @return {Object}\n */\n function parsePreview(data) {\n if (typeof data == 'string') {\n data = {\n items: data\n };\n }\n\n data.items = utils.stringToArray(data.items);\n\n return _.defaults(data, previewConfig);\n }\n\n return Tab.extend({\n defaults: {\n label: '',\n uniqueNs: 'activeCollectionItem',\n previewTpl: 'ui/form/components/collection/preview'\n },\n\n /**\n * Extends instance with default config, calls initializes of parent class\n */\n initialize: function () {\n _.bindAll(this, 'buildPreview', 'hasPreview');\n\n return this._super();\n },\n\n /**\n * Calls initProperties of parent class, initializes properties\n * of instance.\n *\n * @return {Object} - reference to instance\n */\n initConfig: function () {\n this._super();\n\n this.displayed = [];\n\n return this;\n },\n\n /**\n * Calls initObservable of parent class, initializes observable\n * properties of instance.\n *\n * @return {Object} - reference to instance\n */\n initObservable: function () {\n this._super()\n .observe({\n noPreview: true,\n indexed: {}\n });\n\n return this;\n },\n\n /**\n * Is being called when child element has been initialized,\n * calls initElement of parent class, binds to element's update event,\n * calls insertToArea and insertToIndexed methods passing element to it\n *\n * @param {Object} elem\n */\n initElement: function (elem) {\n this._super()\n .insertToIndexed(elem);\n\n return this;\n },\n\n /**\n * Adds element to observable indexed object of instance\n *\n * @param {Object} elem\n * @return {Object} - reference to instance\n */\n insertToIndexed: function (elem) {\n var indexed = this.indexed();\n\n indexed[elem.index] = elem;\n\n this.indexed(indexed);\n\n return this;\n },\n\n /**\n * Destroys current instance along with all of its' children.\n * Overrides base method to clear data when this method is called.\n */\n destroy: function () {\n this._super();\n this._clearData();\n },\n\n /**\n * Clears all data associated with component.\n * @private\n *\n * @returns {Item} Chainable.\n */\n _clearData: function () {\n this.source.remove(this.dataScope);\n\n return this;\n },\n\n /**\n * Formats incoming previews array via parsePreview function.\n *\n * @param {Array} previews\n * @return {Array} - formatted previews\n */\n formatPreviews: function (previews) {\n return previews.map(parsePreview);\n },\n\n /**\n * Creates string view of previews\n *\n * @param {Object} data\n * @return {Strict} - formatted preview string\n */\n buildPreview: function (data) {\n var preview = this.getPreview(data.items),\n prefix = data.prefix;\n\n return prefix + preview.join(data.separator);\n },\n\n /**\n * Defines if instance has preview for incoming data\n *\n * @param {Object} data\n * @return {Boolean}\n */\n hasPreview: function (data) {\n return !!this.getPreview(data.items).length;\n },\n\n /**\n * Creates an array of previews for elements specified in incoming\n * items array, calls updatePreview afterwards.\n *\n * @param {Array} items - An array of element's indexes.\n * @returns {Array} An array of previews.\n */\n getPreview: function (items) {\n var elems = this.indexed(),\n displayed = this.displayed,\n preview;\n\n items = items.map(function (index) {\n var elem = elems[index];\n\n preview = elem && elem.visible() ? elem.getPreview() : '';\n\n preview = Array.isArray(preview) ?\n _.compact(preview).join(', ') :\n preview;\n\n utils.toggle(displayed, index, !!preview);\n\n return preview;\n });\n\n this.noPreview(!displayed.length);\n\n return _.compact(items);\n }\n });\n});\n","Magento_Ui/js/form/element/multiselect.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'mageUtils',\n './select'\n], function (_, utils, Select) {\n 'use strict';\n\n return Select.extend({\n defaults: {\n size: 5,\n elementTmpl: 'ui/form/element/multiselect',\n listens: {\n value: 'setDifferedFromDefault setPrepareToSendData'\n }\n },\n\n /**\n * @inheritdoc\n */\n setInitialValue: function () {\n this._super();\n\n this.initialValue = utils.copy(this.initialValue);\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n normalizeData: function (value) {\n if (utils.isEmpty(value)) {\n value = [];\n }\n\n return _.isString(value) ? value.split(',') : value;\n },\n\n /**\n * Sets the prepared data to dataSource\n * by path, where key is component link to dataSource with\n * suffix \"-prepared-for-send\"\n *\n * @param {Array} data - current component value\n */\n setPrepareToSendData: function (data) {\n if (_.isUndefined(data) || !data.length) {\n data = '';\n }\n\n this.source.set(this.dataScope + '-prepared-for-send', data);\n },\n\n /**\n * @inheritdoc\n */\n getInitialValue: function () {\n var values = [\n this.normalizeData(this.source.get(this.dataScope)),\n this.normalizeData(this.default)\n ],\n value;\n\n values.some(function (v) {\n return _.isArray(v) && (value = utils.copy(v)) && !_.isEmpty(v);\n });\n\n return value;\n },\n\n /**\n * @inheritdoc\n */\n hasChanged: function () {\n var value = this.value(),\n initial = this.initialValue;\n\n return !utils.equalArrays(value, initial);\n },\n\n /**\n * @inheritdoc\n */\n reset: function () {\n this.value(utils.copy(this.initialValue));\n this.error(false);\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n clear: function () {\n this.value([]);\n this.error(false);\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/element/url-input.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'uiLayout',\n 'mage/translate',\n 'Magento_Ui/js/form/element/abstract'\n], function (_, layout, $t, Abstract) {\n 'use strict';\n\n return Abstract.extend({\n defaults: {\n linkedElement: {},\n settingTemplate: 'ui/form/element/urlInput/setting',\n typeSelectorTemplate: 'ui/form/element/urlInput/typeSelector',\n options: [],\n linkedElementInstances: {},\n //checkbox\n isDisplayAdditionalSettings: true,\n settingValue: false,\n settingLabel: $t('Open in new tab'),\n tracks: {\n linkedElement: true\n },\n baseLinkSetting: {\n namePrefix: '${$.name}.',\n dataScopePrefix: '${$.dataScope}.',\n provider: '${$.provider}'\n },\n urlTypes: {},\n listens: {\n settingValue: 'checked',\n disabled: 'hideLinkedElement',\n linkType: 'createChildUrlInputComponent'\n },\n links: {\n linkType: '${$.provider}:${$.dataScope}.type',\n settingValue: '${$.provider}:${$.dataScope}.setting'\n }\n },\n\n /** @inheritdoc */\n initConfig: function (config) {\n var processedLinkTypes = {},\n baseLinkType = this.constructor.defaults.baseLinkSetting;\n\n _.each(config.urlTypes, function (linkSettingsArray, linkName) {\n //add link name by link type\n linkSettingsArray.name = baseLinkType.namePrefix + linkName;\n linkSettingsArray.dataScope = baseLinkType.dataScopePrefix + linkName;\n linkSettingsArray.type = linkName;\n linkSettingsArray.disabled = config.disabled;\n linkSettingsArray.visible = config.visible;\n processedLinkTypes[linkName] = {};\n _.extend(processedLinkTypes[linkName], baseLinkType, linkSettingsArray);\n });\n _.extend(this.constructor.defaults.urlTypes, processedLinkTypes);\n\n this._super();\n },\n\n /**\n * Initializes observable properties of instance\n *\n * @returns {Abstract} Chainable.\n */\n initObservable: function () {\n this._super()\n .observe('componentTemplate options value linkType settingValue checked isDisplayAdditionalSettings')\n .setOptions();\n\n return this;\n },\n\n /**\n * Set options to select based on link types configuration\n *\n * @return {Object}\n */\n setOptions: function () {\n var result = [];\n\n _.each(this.urlTypes, function (option, key) {\n result.push({\n value: key,\n label: option.label,\n sortOrder: option.sortOrder || 0\n });\n });\n\n //sort options by sortOrder\n result.sort(function (a, b) {\n return a.sortOrder > b.sortOrder ? 1 : -1;\n });\n\n this.options(result);\n\n return this;\n },\n\n /** @inheritdoc */\n setPreview: function (visible) {\n this.linkedElement().visible(visible);\n },\n\n /**\n * Initializes observable properties of instance\n *\n * @param {Boolean} disabled\n */\n hideLinkedElement: function (disabled) {\n this.linkedElement().disabled(disabled);\n },\n\n /** @inheritdoc */\n destroy: function () {\n _.each(this.linkedElementInstances, function (value) {\n value().destroy();\n });\n this._super();\n },\n\n /**\n * Create child component by value\n *\n * @param {String} value\n * @return void\n */\n createChildUrlInputComponent: function (value) {\n var elementConfig;\n\n if (!_.isEmpty(value) && _.isUndefined(this.linkedElementInstances[value])) {\n elementConfig = this.urlTypes[value];\n layout([elementConfig]);\n this.linkedElementInstances[value] = this.requestModule(elementConfig.name);\n }\n this.linkedElement = this.linkedElementInstances[value];\n\n },\n\n /**\n * Returns linked element to display related field in template\n * @return String\n */\n getLinkedElementName: function () {\n return this.linkedElement;\n },\n\n /**\n * Add ability to choose check box by clicking on label\n */\n checkboxClick: function () {\n if (!this.disabled()) {\n this.settingValue(!this.settingValue());\n }\n }\n });\n});\n","Magento_Ui/js/form/element/media.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'mageUtils',\n './abstract'\n], function (utils, Abstract) {\n 'use strict';\n\n return Abstract.extend({\n defaults: {\n links: {\n value: ''\n }\n },\n\n /**\n * Initializes file component.\n *\n * @returns {Media} Chainable.\n */\n initialize: function () {\n this._super()\n .initFormId();\n\n return this;\n },\n\n /**\n * Defines form ID with which file input will be associated.\n *\n * @returns {Media} Chainable.\n */\n initFormId: function () {\n var namespace;\n\n if (this.formId) {\n return this;\n }\n\n namespace = this.name.split('.');\n this.formId = namespace[0];\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/element/abstract.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'mageUtils',\n 'uiLayout',\n 'uiElement',\n 'Magento_Ui/js/lib/validation/validator'\n], function (_, utils, layout, Element, validator) {\n 'use strict';\n\n return Element.extend({\n defaults: {\n visible: true,\n preview: '',\n focused: false,\n required: false,\n disabled: false,\n valueChangedByUser: false,\n elementTmpl: 'ui/form/element/input',\n tooltipTpl: 'ui/form/element/helper/tooltip',\n fallbackResetTpl: 'ui/form/element/helper/fallback-reset',\n 'input_type': 'input',\n placeholder: false,\n description: '',\n labelVisible: true,\n label: '',\n error: '',\n warn: '',\n notice: '',\n customScope: '',\n default: '',\n isDifferedFromDefault: false,\n showFallbackReset: false,\n additionalClasses: {},\n isUseDefault: '',\n serviceDisabled: false,\n valueUpdate: false, // ko binding valueUpdate\n\n switcherConfig: {\n component: 'Magento_Ui/js/form/switcher',\n name: '${ $.name }_switcher',\n target: '${ $.name }',\n property: 'value'\n },\n listens: {\n visible: 'setPreview',\n value: 'setDifferedFromDefault',\n '${ $.provider }:data.reset': 'reset',\n '${ $.provider }:data.overload': 'overload',\n '${ $.provider }:${ $.customScope ? $.customScope + \".\" : \"\"}data.validate': 'validate',\n 'isUseDefault': 'toggleUseDefault'\n },\n ignoreTmpls: {\n value: true\n },\n\n links: {\n value: '${ $.provider }:${ $.dataScope }'\n }\n },\n\n /**\n * Invokes initialize method of parent class,\n * contains initialization logic\n */\n initialize: function () {\n _.bindAll(this, 'reset');\n\n this._super()\n .setInitialValue()\n ._setClasses()\n .initSwitcher();\n\n return this;\n },\n\n /**\n * Checks if component has error.\n *\n * @returns {Object}\n */\n checkInvalid: function () {\n return this.error() && this.error().length ? this : null;\n },\n\n /**\n * Initializes observable properties of instance\n *\n * @returns {Abstract} Chainable.\n */\n initObservable: function () {\n var rules = this.validation = this.validation || {};\n\n this._super();\n\n this.observe('error disabled focused preview visible value warn notice isDifferedFromDefault')\n .observe('isUseDefault serviceDisabled')\n .observe({\n 'required': !!rules['required-entry']\n });\n\n return this;\n },\n\n /**\n * Initializes regular properties of instance.\n *\n * @returns {Abstract} Chainable.\n */\n initConfig: function () {\n var uid = utils.uniqueid(),\n name,\n valueUpdate,\n scope;\n\n this._super();\n\n scope = this.dataScope.split('.');\n name = scope.length > 1 ? scope.slice(1) : scope;\n\n valueUpdate = this.showFallbackReset ? 'afterkeydown' : this.valueUpdate;\n\n _.extend(this, {\n uid: uid,\n noticeId: 'notice-' + uid,\n errorId: 'error-' + uid,\n tooltipId: 'tooltip-' + uid,\n inputName: utils.serializeName(name.join('.')),\n valueUpdate: valueUpdate\n });\n\n return this;\n },\n\n /**\n * Initializes switcher element instance.\n *\n * @returns {Abstract} Chainable.\n */\n initSwitcher: function () {\n if (this.switcherConfig.enabled) {\n layout([this.switcherConfig]);\n }\n\n return this;\n },\n\n /**\n * Sets initial value of the element and subscribes to it's changes.\n *\n * @returns {Abstract} Chainable.\n */\n setInitialValue: function () {\n this.initialValue = this.getInitialValue();\n\n if (this.value.peek() !== this.initialValue) {\n this.value(this.initialValue);\n }\n\n this.on('value', this.onUpdate.bind(this));\n this.isUseDefault(this.disabled());\n\n return this;\n },\n\n /**\n * Extends 'additionalClasses' object.\n *\n * @returns {Abstract} Chainable.\n */\n _setClasses: function () {\n var additional = this.additionalClasses;\n\n if (_.isString(additional)) {\n this.additionalClasses = {};\n\n if (additional.trim().length) {\n additional = additional.trim().split(' ');\n\n additional.forEach(function (name) {\n if (name.length) {\n this.additionalClasses[name] = true;\n }\n }, this);\n }\n }\n\n _.extend(this.additionalClasses, {\n _required: this.required,\n _error: this.error,\n _warn: this.warn,\n _disabled: this.disabled\n });\n\n return this;\n },\n\n /**\n * Gets initial value of element\n *\n * @returns {*} Elements' value.\n */\n getInitialValue: function () {\n var values = [this.value(), this.default],\n value;\n\n values.some(function (v) {\n if (v !== null && v !== undefined) {\n value = v;\n\n return true;\n }\n\n return false;\n });\n\n return this.normalizeData(value);\n },\n\n /**\n * Sets 'value' as 'hidden' property's value, triggers 'toggle' event,\n * sets instance's hidden identifier in params storage based on\n * 'value'.\n *\n * @returns {Abstract} Chainable.\n */\n setVisible: function (isVisible) {\n this.visible(isVisible);\n\n return this;\n },\n\n /**\n * Show element.\n *\n * @returns {Abstract} Chainable.\n */\n show: function () {\n this.visible(true);\n\n return this;\n },\n\n /**\n * Hide element.\n *\n * @returns {Abstract} Chainable.\n */\n hide: function () {\n this.visible(false);\n\n return this;\n },\n\n /**\n * Disable element.\n *\n * @returns {Abstract} Chainable.\n */\n disable: function () {\n this.disabled(true);\n\n return this;\n },\n\n /**\n * Enable element.\n *\n * @returns {Abstract} Chainable.\n */\n enable: function () {\n this.disabled(false);\n\n return this;\n },\n\n /**\n *\n * @param {(String|Object)} rule\n * @param {(Object|Boolean)} [options]\n * @returns {Abstract} Chainable.\n */\n setValidation: function (rule, options) {\n var rules = utils.copy(this.validation),\n changed;\n\n if (_.isObject(rule)) {\n _.extend(this.validation, rule);\n } else {\n this.validation[rule] = options;\n }\n\n changed = !utils.compare(rules, this.validation).equal;\n\n if (changed) {\n this.required(!!rules['required-entry']);\n this.validate();\n }\n\n return this;\n },\n\n /**\n * Returns unwrapped preview observable.\n *\n * @returns {String} Value of the preview observable.\n */\n getPreview: function () {\n return this.value();\n },\n\n /**\n * Checks if element has addons\n *\n * @returns {Boolean}\n */\n hasAddons: function () {\n return this.addbefore || this.addafter;\n },\n\n /**\n * Checks if element has service setting\n *\n * @returns {Boolean}\n */\n hasService: function () {\n return this.service && this.service.template;\n },\n\n /**\n * Defines if value has changed.\n *\n * @returns {Boolean}\n */\n hasChanged: function () {\n var notEqual = this.value() !== this.initialValue;\n\n return !this.visible() ? false : notEqual;\n },\n\n /**\n * Checks if 'value' is not empty.\n *\n * @returns {Boolean}\n */\n hasData: function () {\n return !utils.isEmpty(this.value());\n },\n\n /**\n * Sets value observable to initialValue property.\n *\n * @returns {Abstract} Chainable.\n */\n reset: function () {\n this.value(this.initialValue);\n this.error(false);\n\n return this;\n },\n\n /**\n * Sets current state as initial.\n */\n overload: function () {\n this.setInitialValue();\n this.bubble('update', this.hasChanged());\n },\n\n /**\n * Clears 'value' property.\n *\n * @returns {Abstract} Chainable.\n */\n clear: function () {\n this.value('');\n\n return this;\n },\n\n /**\n * Converts values like 'null' or 'undefined' to an empty string.\n *\n * @param {*} value - Value to be processed.\n * @returns {*}\n */\n normalizeData: function (value) {\n return utils.isEmpty(value) ? '' : value;\n },\n\n /**\n * Validates itself by it's validation rules using validator object.\n * If validation of a rule did not pass, writes it's message to\n * 'error' observable property.\n *\n * @returns {Object} Validate information.\n */\n validate: function () {\n var value = this.value(),\n result = validator(this.validation, value, this.validationParams),\n message = !this.disabled() && this.visible() ? result.message : '',\n isValid = this.disabled() || !this.visible() || result.passed;\n\n this.error(message);\n this.error.valueHasMutated();\n this.bubble('error', message);\n\n //TODO: Implement proper result propagation for form\n if (this.source && !isValid) {\n this.source.set('params.invalid', true);\n }\n\n return {\n valid: isValid,\n target: this\n };\n },\n\n /**\n * Callback that fires when 'value' property is updated.\n */\n onUpdate: function () {\n this.bubble('update', this.hasChanged());\n\n this.validate();\n },\n\n /**\n * Restore value to default\n */\n restoreToDefault: function () {\n this.value(this.default);\n this.focused(true);\n },\n\n /**\n * Update whether value differs from default value\n */\n setDifferedFromDefault: function () {\n var value = typeof this.value() != 'undefined' && this.value() !== null ? this.value() : '',\n defaultValue = typeof this.default != 'undefined' && this.default !== null ? this.default : '';\n\n this.isDifferedFromDefault(value !== defaultValue);\n },\n\n /**\n * @param {Boolean} state\n */\n toggleUseDefault: function (state) {\n this.disabled(state);\n\n if (this.source && this.hasService()) {\n this.source.set('data.use_default.' + this.index, Number(state));\n }\n },\n\n /**\n * Callback when value is changed by user\n */\n userChanges: function () {\n this.valueChangedByUser = true;\n },\n\n /**\n * Returns correct id for 'aria-describedby' accessibility attribute\n *\n * @returns {Boolean|String}\n */\n getDescriptionId: function () {\n var id = false;\n\n if (this.error()) {\n id = this.errorId;\n } else if (this.notice()) {\n id = this.noticeId;\n }\n\n return id;\n }\n });\n});\n","Magento_Ui/js/form/element/boolean.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n './abstract'\n], function (Abstract) {\n 'use strict';\n\n return Abstract.extend({\n defaults: {\n checked: false,\n links: {\n checked: 'value'\n }\n },\n\n /**\n * @returns {*|void|Element}\n */\n initObservable: function () {\n return this._super()\n .observe('checked');\n },\n\n /**\n * Converts provided value to boolean.\n *\n * @returns {Boolean}\n */\n normalizeData: function () {\n return !!+this._super();\n },\n\n /**\n * Calls 'onUpdate' method of parent, if value is defined and instance's\n * 'unique' property set to true, calls 'setUnique' method\n *\n * @return {Object} - reference to instance\n */\n onUpdate: function () {\n if (this.hasUnique) {\n this.setUnique();\n }\n\n return this._super();\n }\n });\n});\n","Magento_Ui/js/form/element/select.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'mageUtils',\n 'uiRegistry',\n './abstract',\n 'uiLayout'\n], function (_, utils, registry, Abstract, layout) {\n 'use strict';\n\n var inputNode = {\n parent: '${ $.$data.parentName }',\n component: 'Magento_Ui/js/form/element/abstract',\n template: '${ $.$data.template }',\n provider: '${ $.$data.provider }',\n name: '${ $.$data.index }_input',\n dataScope: '${ $.$data.customEntry }',\n customScope: '${ $.$data.customScope }',\n sortOrder: {\n after: '${ $.$data.name }'\n },\n displayArea: 'body',\n label: '${ $.$data.label }'\n };\n\n /**\n * Parses incoming options, considers options with undefined value property\n * as caption\n *\n * @param {Array} nodes\n * @return {Object}\n */\n function parseOptions(nodes, captionValue) {\n var caption,\n value;\n\n nodes = _.map(nodes, function (node) {\n value = node.value;\n\n if (value === null || value === captionValue) {\n if (_.isUndefined(caption)) {\n caption = node.label;\n }\n } else {\n return node;\n }\n });\n\n return {\n options: _.compact(nodes),\n caption: _.isString(caption) ? caption : false\n };\n }\n\n /**\n * Recursively loops over data to find non-undefined, non-array value\n *\n * @param {Array} data\n * @return {*} - first non-undefined value in array\n */\n function findFirst(data) {\n var value;\n\n data.some(function (node) {\n value = node.value;\n\n if (Array.isArray(value)) {\n value = findFirst(value);\n }\n\n return !_.isUndefined(value);\n });\n\n return value;\n }\n\n /**\n * Recursively set to object item like value and item.value like key.\n *\n * @param {Array} data\n * @param {Object} result\n * @returns {Object}\n */\n function indexOptions(data, result) {\n var value;\n\n result = result || {};\n\n data.forEach(function (item) {\n value = item.value;\n\n if (Array.isArray(value)) {\n indexOptions(value, result);\n } else {\n result[value] = item;\n }\n });\n\n return result;\n }\n\n return Abstract.extend({\n defaults: {\n customName: '${ $.parentName }.${ $.index }_input',\n elementTmpl: 'ui/form/element/select',\n caption: '',\n options: []\n },\n\n /**\n * Extends instance with defaults, extends config with formatted values\n * and options, and invokes initialize method of AbstractElement class.\n * If instance's 'customEntry' property is set to true, calls 'initInput'\n */\n initialize: function () {\n this._super();\n\n if (this.customEntry) {\n registry.get(this.name, this.initInput.bind(this));\n }\n\n if (this.filterBy) {\n this.initFilter();\n }\n\n return this;\n },\n\n /**\n * Calls 'initObservable' of parent, initializes 'options' and 'initialOptions'\n * properties, calls 'setOptions' passing options to it\n *\n * @returns {Object} Chainable.\n */\n initObservable: function () {\n this._super();\n\n this.initialOptions = this.options;\n\n this.observe('options caption')\n .setOptions(this.options());\n\n return this;\n },\n\n /**\n * Set link for filter.\n *\n * @returns {Object} Chainable\n */\n initFilter: function () {\n var filter = this.filterBy;\n\n this.filter(this.default, filter.field);\n this.setLinks({\n filter: filter.target\n }, 'imports');\n\n return this;\n },\n\n /**\n * Creates input from template, renders it via renderer.\n *\n * @returns {Object} Chainable.\n */\n initInput: function () {\n layout([utils.template(inputNode, this)]);\n\n return this;\n },\n\n /**\n * Matches specified value with existing options\n * or, if value is not specified, returns value of the first option.\n *\n * @returns {*}\n */\n normalizeData: function () {\n var value = this._super(),\n option;\n\n if (value !== '') {\n option = this.getOption(value);\n\n return option && option.value;\n }\n\n if (!this.caption()) {\n return findFirst(this.options);\n }\n },\n\n /**\n * Filters 'initialOptions' property by 'field' and 'value' passed,\n * calls 'setOptions' passing the result to it\n *\n * @param {*} value\n * @param {String} field\n */\n filter: function (value, field) {\n var source = this.initialOptions,\n result;\n\n field = field || this.filterBy.field;\n\n result = _.filter(source, function (item) {\n return item[field] === value || item.value === '';\n });\n\n this.setOptions(result);\n },\n\n /**\n * Change visibility for input.\n *\n * @param {Boolean} isVisible\n */\n toggleInput: function (isVisible) {\n registry.get(this.customName, function (input) {\n input.setVisible(isVisible);\n });\n },\n\n /**\n * Sets 'data' to 'options' observable array, if instance has\n * 'customEntry' property set to true, calls 'setHidden' method\n * passing !options.length as a parameter\n *\n * @param {Array} data\n * @returns {Object} Chainable\n */\n setOptions: function (data) {\n var captionValue = this.captionValue || '',\n result = parseOptions(data, captionValue),\n isVisible;\n\n this.indexedOptions = indexOptions(result.options);\n\n this.options(result.options);\n\n if (!this.caption()) {\n this.caption(result.caption);\n }\n\n if (this.customEntry) {\n isVisible = !!result.options.length;\n\n this.setVisible(isVisible);\n this.toggleInput(!isVisible);\n }\n\n return this;\n },\n\n /**\n * Processes preview for option by it's value, and sets the result\n * to 'preview' observable\n *\n * @returns {Object} Chainable.\n */\n getPreview: function () {\n var value = this.value(),\n option = this.indexedOptions[value],\n preview = option ? option.label : '';\n\n this.preview(preview);\n\n return preview;\n },\n\n /**\n * Get option from indexedOptions list.\n *\n * @param {Number} value\n * @returns {Object} Chainable\n */\n getOption: function (value) {\n return this.indexedOptions[value];\n },\n\n /**\n * Select first available option\n *\n * @returns {Object} Chainable.\n */\n clear: function () {\n var value = this.caption() ? '' : findFirst(this.options);\n\n this.value(value);\n\n return this;\n },\n\n /**\n * Initializes observable properties of instance\n *\n * @returns {Object} Chainable.\n */\n setInitialValue: function () {\n if (_.isUndefined(this.value()) && !this.default) {\n this.clear();\n }\n\n return this._super();\n }\n });\n});\n","Magento_Ui/js/form/element/single-checkbox.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'Magento_Ui/js/form/element/abstract',\n 'underscore',\n 'mage/translate'\n], function (AbstractField, _, $t) {\n 'use strict';\n\n return AbstractField.extend({\n defaults: {\n template: 'ui/form/components/single/field',\n checked: false,\n initialChecked: false,\n multiple: false,\n prefer: 'checkbox', // 'radio' | 'checkbox' | 'toggle'\n valueMap: {},\n\n templates: {\n radio: 'ui/form/components/single/radio',\n checkbox: 'ui/form/components/single/checkbox',\n toggle: 'ui/form/components/single/switcher'\n },\n\n listens: {\n 'checked': 'onCheckedChanged',\n 'value': 'onExtendedValueChanged'\n }\n },\n\n /**\n * @inheritdoc\n */\n initConfig: function (config) {\n this._super();\n\n if (!config.elementTmpl) {\n if (!this.prefer && !this.multiple) {\n this.elementTmpl = this.templates.radio;\n } else if (this.prefer === 'radio') {\n this.elementTmpl = this.templates.radio;\n } else if (this.prefer === 'checkbox') {\n this.elementTmpl = this.templates.checkbox;\n } else if (this.prefer === 'toggle') {\n this.elementTmpl = this.templates.toggle;\n } else {\n this.elementTmpl = this.templates.checkbox;\n }\n }\n\n if (this.prefer === 'toggle' && _.isEmpty(this.toggleLabels)) {\n this.toggleLabels = {\n 'on': $t('Yes'),\n 'off': $t('No')\n };\n }\n\n if (typeof this.default === 'undefined' || this.default === null) {\n this.default = '';\n }\n\n if (typeof this.value === 'undefined' || this.value === null) {\n this.value = _.isEmpty(this.valueMap) || this.default !== '' ? this.default : this.valueMap.false;\n this.initialValue = this.value;\n } else {\n this.initialValue = this.value;\n }\n\n if (this.multiple && !_.isArray(this.value)) {\n this.value = []; // needed for correct observable assignment\n }\n\n this.initialChecked = this.checked;\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n initObservable: function () {\n return this\n ._super()\n .observe('checked');\n },\n\n /**\n * Get true/false key from valueMap by value.\n *\n * @param {*} value\n * @returns {Boolean|undefined}\n */\n getReverseValueMap: function getReverseValueMap(value) {\n var bool = false;\n\n _.some(this.valueMap, function (iValue, iBool) {\n if (iValue === value) {\n bool = iBool === 'true';\n\n return true;\n }\n });\n\n return bool;\n },\n\n /**\n * @inheritdoc\n */\n setInitialValue: function () {\n if (_.isEmpty(this.valueMap)) {\n this.on('value', this.onUpdate.bind(this));\n } else {\n this._super();\n this.checked(this.getReverseValueMap(this.value()));\n }\n\n return this;\n },\n\n /**\n * Handle dataScope changes for checkbox / radio button.\n *\n * @param {*} newExportedValue\n */\n onExtendedValueChanged: function (newExportedValue) {\n var isMappedUsed = !_.isEmpty(this.valueMap),\n oldChecked = this.checked.peek(),\n oldValue = this.initialValue,\n newChecked;\n\n if (this.multiple) {\n newChecked = newExportedValue.indexOf(oldValue) !== -1;\n } else if (isMappedUsed) {\n newChecked = this.getReverseValueMap(newExportedValue);\n } else if (typeof newExportedValue === 'boolean') {\n newChecked = newExportedValue;\n } else {\n newChecked = newExportedValue === oldValue;\n }\n\n if (newChecked !== oldChecked) {\n this.checked(newChecked);\n }\n },\n\n /**\n * Handle checked state changes for checkbox / radio button.\n *\n * @param {Boolean} newChecked\n */\n onCheckedChanged: function (newChecked) {\n var isMappedUsed = !_.isEmpty(this.valueMap),\n oldValue = this.initialValue,\n newValue;\n\n if (isMappedUsed) {\n newValue = this.valueMap[newChecked];\n } else {\n newValue = oldValue;\n }\n\n if (!this.multiple && newChecked) {\n this.value(newValue);\n } else if (!this.multiple && !newChecked) {\n if (typeof newValue === 'boolean') {\n this.value(newChecked);\n } else if (newValue === this.value.peek()) {\n this.value('');\n }\n\n if (isMappedUsed) {\n this.value(newValue);\n }\n } else if (this.multiple && newChecked && this.value.indexOf(newValue) === -1) {\n this.value.push(newValue);\n } else if (this.multiple && !newChecked && this.value.indexOf(newValue) !== -1) {\n this.value.splice(this.value.indexOf(newValue), 1);\n }\n },\n\n /**\n * @inheritdoc\n */\n onUpdate: function () {\n if (this.hasUnique) {\n this.setUnique();\n }\n\n return this._super();\n },\n\n /**\n * @inheritdoc\n */\n reset: function () {\n if (this.multiple && this.initialChecked) {\n this.value.push(this.initialValue);\n } else if (this.multiple && !this.initialChecked) {\n this.value.splice(this.value.indexOf(this.initialValue), 1);\n } else {\n this.value(this.initialValue);\n }\n\n this.error(false);\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n clear: function () {\n if (this.multiple) {\n this.value([]);\n } else {\n this.value('');\n }\n\n this.error(false);\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/element/website.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'uiRegistry',\n './select'\n], function (_, registry, Select) {\n 'use strict';\n\n return Select.extend({\n defaults: {\n customerId: null,\n isGlobalScope: 0\n },\n\n /**\n * Website component constructor.\n * @returns {exports}\n */\n initialize: function () {\n this._super();\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/element/wysiwyg.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'wysiwygAdapter',\n 'Magento_Ui/js/lib/view/utils/async',\n 'underscore',\n 'ko',\n './abstract',\n 'mage/adminhtml/events',\n 'Magento_Variable/variables'\n], function (wysiwyg, $, _, ko, Abstract, varienGlobalEvents) {\n 'use strict';\n\n return Abstract.extend({\n currentWysiwyg: undefined,\n defaults: {\n elementSelector: 'textarea',\n suffixRegExpPattern: '${ $.wysiwygUniqueSuffix }',\n $wysiwygEditorButton: '',\n links: {\n value: '${ $.provider }:${ $.dataScope }'\n },\n template: 'ui/form/field',\n elementTmpl: 'ui/form/element/wysiwyg',\n content: '',\n showSpinner: false,\n loading: false,\n listens: {\n disabled: 'setDisabled'\n }\n },\n\n /**\n *\n * @returns {} Chainable.\n */\n initialize: function () {\n this._super()\n .initNodeListener();\n\n $.async({\n component: this,\n selector: 'button'\n }, function (element) {\n this.$wysiwygEditorButton = this.$wysiwygEditorButton ?\n this.$wysiwygEditorButton.add($(element)) : $(element);\n }.bind(this));\n\n // disable editor completely after initialization is field is disabled\n varienGlobalEvents.attachEventHandler('wysiwygEditorInitialized', function () {\n if (!_.isUndefined(window.tinyMceEditors)) {\n this.currentWysiwyg = window.tinyMceEditors[this.wysiwygId];\n }\n\n if (this.disabled()) {\n this.setDisabled(true);\n }\n }.bind(this));\n\n return this;\n },\n\n /** @inheritdoc */\n initConfig: function (config) {\n var pattern = config.suffixRegExpPattern || this.constructor.defaults.suffixRegExpPattern;\n\n pattern = pattern.replace(/\\$/g, '\\\\$&');\n config.content = config.content.replace(new RegExp(pattern, 'g'), this.getUniqueSuffix(config));\n this._super();\n\n return this;\n },\n\n /**\n * Build unique id based on name, underscore separated.\n *\n * @param {Object} config\n */\n getUniqueSuffix: function (config) {\n return config.name.replace(/(\\.|-)/g, '_');\n },\n\n /**\n * @inheritdoc\n */\n destroy: function () {\n this._super();\n wysiwyg.removeEvents(this.wysiwygId);\n },\n\n /**\n *\n * @returns {exports}\n */\n initObservable: function () {\n this._super()\n .observe(['value', 'content']);\n\n return this;\n },\n\n /**\n *\n * @returns {} Chainable.\n */\n initNodeListener: function () {\n $.async({\n component: this,\n selector: this.elementSelector\n }, this.setElementNode.bind(this));\n\n return this;\n },\n\n /**\n *\n * @param {HTMLElement} node\n */\n setElementNode: function (node) {\n $(node).bindings({\n value: this.value\n });\n },\n\n /**\n * Set disabled property to wysiwyg component\n *\n * @param {Boolean} disabled\n */\n setDisabled: function (disabled) {\n if (this.$wysiwygEditorButton && disabled) {\n this.$wysiwygEditorButton.prop('disabled', 'disabled');\n } else if (this.$wysiwygEditorButton) {\n this.$wysiwygEditorButton.prop('disabled', false);\n }\n\n /* eslint-disable no-undef */\n if (!_.isUndefined(this.currentWysiwyg) && this.currentWysiwyg.activeEditor()) {\n this.currentWysiwyg.setEnabledStatus(!disabled);\n this.currentWysiwyg.getPluginButtons().prop('disabled', disabled);\n }\n },\n\n /**\n * Content getter\n *\n * @returns {String}\n */\n getContentUnsanitizedHtml: function () {\n return this.content();\n }\n });\n});\n","Magento_Ui/js/form/element/single-checkbox-use-config.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'Magento_Ui/js/form/element/single-checkbox'\n], function (Component) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n isUseDefault: false,\n isUseConfig: false,\n listens: {\n 'isUseConfig': 'toggleElement',\n 'isUseDefault': 'toggleElement'\n }\n },\n\n /**\n * @inheritdoc\n */\n initObservable: function () {\n\n return this\n ._super()\n .observe('isUseConfig');\n },\n\n /**\n * Toggle element\n */\n toggleElement: function () {\n this.disabled(this.isUseDefault() || this.isUseConfig());\n\n if (this.source) {\n this.source.set('data.use_default.' + this.index, Number(this.isUseDefault()));\n }\n }\n });\n});\n","Magento_Ui/js/form/element/region.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'uiRegistry',\n './select',\n 'Magento_Checkout/js/model/default-post-code-resolver'\n], function (_, registry, Select, defaultPostCodeResolver) {\n 'use strict';\n\n return Select.extend({\n defaults: {\n skipValidation: false,\n imports: {\n countryOptions: '${ $.parentName }.country_id:indexedOptions',\n update: '${ $.parentName }.country_id:value'\n }\n },\n\n /**\n * {@inheritdoc}\n */\n initialize: function () {\n var option;\n\n this._super();\n\n option = _.find(this.countryOptions, function (row) {\n return row['is_default'] === true;\n });\n this.hideRegion(option);\n\n return this;\n },\n\n /**\n * Method called every time country selector's value gets changed.\n * Updates all validations and requirements for certain country.\n * @param {String} value - Selected country ID.\n */\n update: function (value) {\n var isRegionRequired,\n option;\n\n if (!value) {\n return;\n }\n\n option = _.isObject(this.countryOptions) && this.countryOptions[value];\n\n if (!option) {\n return;\n }\n\n this.hideRegion(option);\n\n defaultPostCodeResolver.setUseDefaultPostCode(!option['is_zipcode_optional']);\n\n isRegionRequired = !this.skipValidation && !!option['is_region_required'];\n\n if (!isRegionRequired) {\n this.error(false);\n }\n\n this.required(isRegionRequired);\n this.validation['required-entry'] = isRegionRequired;\n\n registry.get(this.customName, function (input) {\n input.required(isRegionRequired);\n input.validation['required-entry'] = isRegionRequired;\n input.validation['validate-not-number-first'] = !this.options().length;\n }.bind(this));\n },\n\n /**\n * Hide select and corresponding text input field if region must not be shown for selected country.\n *\n * @private\n * @param {Object}option\n */\n hideRegion: function (option) {\n if (!option || option['is_region_visible'] !== false) {\n return;\n }\n\n this.setVisible(false);\n\n if (this.customEntry) {\n this.toggleInput(false);\n }\n }\n });\n});\n","Magento_Ui/js/form/element/single-checkbox-toggle-notice.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'Magento_Ui/js/form/element/single-checkbox'\n], function (SingleCheckbox) {\n 'use strict';\n\n return SingleCheckbox.extend({\n defaults: {\n notices: [],\n tracks: {\n notice: true\n }\n },\n\n /**\n * Choose notice on initialization\n *\n * @returns {*|void|Element}\n */\n initialize: function () {\n this._super()\n .chooseNotice();\n\n return this;\n },\n\n /**\n * Choose notice function\n *\n * @returns void\n */\n chooseNotice: function () {\n var checkedNoticeNumber = Number(this.checked());\n\n this.notice = this.notices[checkedNoticeNumber];\n },\n\n /**\n * Choose notice on update\n *\n * @returns void\n */\n onUpdate: function () {\n this._super();\n this.chooseNotice();\n }\n });\n});\n","Magento_Ui/js/form/element/text.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'uiElement',\n 'mageUtils'\n], function (Element, utils) {\n 'use strict';\n\n return Element.extend({\n defaults: {\n visible: true,\n label: '',\n error: '',\n uid: utils.uniqueid(),\n disabled: false,\n links: {\n value: '${ $.provider }:${ $.dataScope }'\n }\n },\n\n /**\n * Has service\n *\n * @returns {Boolean} false.\n */\n hasService: function () {\n return false;\n },\n\n /**\n * Has addons\n *\n * @returns {Boolean} false.\n */\n hasAddons: function () {\n return false;\n },\n\n /**\n * Calls 'initObservable' of parent\n *\n * @returns {Object} Chainable.\n */\n initObservable: function () {\n this._super()\n .observe('disabled visible value');\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/element/date.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'moment',\n 'mageUtils',\n './abstract',\n 'moment-timezone-with-data'\n], function (moment, utils, Abstract) {\n 'use strict';\n\n return Abstract.extend({\n defaults: {\n options: {},\n\n storeTimeZone: 'UTC',\n\n validationParams: {\n dateFormat: '${ $.outputDateFormat }'\n },\n\n /**\n * Format of date that comes from the\n * server (ICU Date Format).\n *\n * Used only in date picker mode\n * (this.options.showsTime == false).\n *\n * @type {String}\n */\n inputDateFormat: 'y-MM-dd',\n\n /**\n * Format of date that should be sent to the\n * server (ICU Date Format).\n *\n * Used only in date picker mode\n * (this.options.showsTime == false).\n *\n * @type {String}\n */\n outputDateFormat: 'MM/dd/y',\n\n /**\n * Date/time format that is used to display date in\n * the input field.\n *\n * @type {String}\n */\n pickerDateTimeFormat: '',\n\n pickerDefaultDateFormat: 'MM/dd/y', // ICU Date Format\n pickerDefaultTimeFormat: 'h:mm a', // ICU Time Format\n\n elementTmpl: 'ui/form/element/date',\n\n /**\n * Format needed by moment timezone for conversion\n */\n timezoneFormat: 'YYYY-MM-DD HH:mm',\n\n listens: {\n 'value': 'onValueChange',\n 'shiftedValue': 'onShiftedValueChange'\n },\n\n /**\n * Date/time value shifted to corresponding timezone\n * according to this.storeTimeZone property. This value\n * will be sent to the server.\n *\n * @type {String}\n */\n shiftedValue: ''\n },\n\n /**\n * Initializes regular properties of instance.\n *\n * @returns {Object} Chainable.\n */\n initConfig: function () {\n this._super();\n\n if (!this.options.dateFormat) {\n this.options.dateFormat = this.pickerDefaultDateFormat;\n }\n\n if (!this.options.timeFormat) {\n this.options.timeFormat = this.pickerDefaultTimeFormat;\n }\n\n this.prepareDateTimeFormats();\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n initObservable: function () {\n return this._super().observe(['shiftedValue']);\n },\n\n /**\n * @inheritdoc\n */\n getPreview: function () {\n return this.shiftedValue();\n },\n\n /**\n * Prepares and sets date/time value that will be displayed\n * in the input field.\n *\n * @param {String} value\n */\n onValueChange: function (value) {\n var shiftedValue;\n\n if (value) {\n if (this.options.showsTime && !this.options.timeOnly) {\n shiftedValue = moment.tz(value, 'UTC').tz(this.storeTimeZone);\n } else {\n shiftedValue = moment(value, this.outputDateFormat, true);\n }\n\n if (!shiftedValue.isValid()) {\n shiftedValue = moment(value, this.inputDateFormat);\n }\n shiftedValue = shiftedValue.format(this.pickerDateTimeFormat);\n } else {\n shiftedValue = '';\n }\n\n if (shiftedValue !== this.shiftedValue()) {\n this.shiftedValue(shiftedValue);\n }\n },\n\n /**\n * Prepares and sets date/time value that will be sent\n * to the server.\n *\n * @param {String} shiftedValue\n */\n onShiftedValueChange: function (shiftedValue) {\n var value,\n formattedValue,\n momentValue;\n\n if (shiftedValue) {\n momentValue = moment(shiftedValue, this.pickerDateTimeFormat);\n\n if (this.options.showsTime && !this.options.timeOnly) {\n formattedValue = moment(momentValue).format(this.timezoneFormat);\n value = moment.tz(formattedValue, this.storeTimeZone).tz('UTC').toISOString();\n } else {\n value = momentValue.format(this.outputDateFormat);\n }\n } else {\n value = '';\n }\n\n if (value !== this.value()) {\n this.value(value);\n }\n },\n\n /**\n * Prepares and converts all date/time formats to be compatible\n * with moment.js library.\n */\n prepareDateTimeFormats: function () {\n if (this.options.timeOnly) {\n this.pickerDateTimeFormat = this.options.timeFormat;\n } else {\n this.pickerDateTimeFormat = this.options.dateFormat;\n\n if (this.options.showsTime) {\n this.pickerDateTimeFormat += ' ' + this.options.timeFormat;\n }\n }\n\n this.pickerDateTimeFormat = utils.convertToMomentFormat(this.pickerDateTimeFormat);\n\n if (this.options.dateFormat) {\n this.outputDateFormat = this.options.dateFormat;\n }\n\n this.inputDateFormat = this.options.timeOnly ?\n utils.convertToMomentFormat(this.pickerDefaultTimeFormat) :\n utils.convertToMomentFormat(this.inputDateFormat);\n this.outputDateFormat = this.options.timeOnly ?\n utils.convertToMomentFormat(this.options.timeFormat) :\n utils.convertToMomentFormat(this.outputDateFormat);\n\n this.validationParams.dateFormat = this.outputDateFormat;\n }\n });\n});\n","Magento_Ui/js/form/element/color-picker.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'mage/translate',\n 'Magento_Ui/js/form/element/abstract',\n 'Magento_Ui/js/form/element/color-picker-palette'\n], function ($t, Abstract, palette) {\n 'use strict';\n\n return Abstract.extend({\n\n defaults: {\n colorPickerConfig: {\n chooseText: $t('Apply'),\n cancelText: $t('Cancel'),\n maxSelectionSize: 8,\n clickoutFiresChange: true,\n allowEmpty: true,\n localStorageKey: 'magento.spectrum',\n palette: palette\n }\n },\n\n /**\n * Invokes initialize method of parent class,\n * contains initialization logic\n */\n initialize: function () {\n this._super();\n\n this.colorPickerConfig.value = this.value;\n\n return this;\n }\n });\n});\n","Magento_Ui/js/form/element/image-uploader.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/* global Base64 */\ndefine([\n 'jquery',\n 'underscore',\n 'mageUtils',\n 'Magento_Ui/js/modal/alert',\n 'Magento_Ui/js/lib/validation/validator',\n 'Magento_Ui/js/form/element/file-uploader',\n 'mage/adminhtml/browser'\n], function ($, _, utils, uiAlert, validator, Element, browser) {\n 'use strict';\n\n return Element.extend({\n /**\n * {@inheritDoc}\n */\n initialize: function () {\n this._super();\n\n // Listen for file deletions from the media browser\n $(window).on('fileDeleted.mediabrowser', this.onDeleteFile.bind(this));\n },\n\n /**\n * Assign uid for media gallery\n *\n * @return {ImageUploader} Chainable.\n */\n initConfig: function () {\n var mediaGalleryUid = utils.uniqueid();\n\n this._super();\n\n _.extend(this, {\n mediaGalleryUid: mediaGalleryUid\n });\n\n return this;\n },\n\n /**\n * Add file event callback triggered from media gallery\n *\n * @param {ImageUploader} imageUploader - UI Class\n * @param {Event} e\n */\n addFileFromMediaGallery: function (imageUploader, e) {\n var $buttonEl = $(e.target),\n fileSize = $buttonEl.data('size'),\n fileMimeType = $buttonEl.data('mime-type'),\n filePathname = $buttonEl.val(),\n fileBasename = filePathname.split('/').pop();\n\n this.addFile({\n type: fileMimeType,\n name: fileBasename,\n size: fileSize,\n url: filePathname\n });\n },\n\n /**\n * Open the media browser dialog\n *\n * @param {ImageUploader} imageUploader - UI Class\n * @param {Event} e\n */\n openMediaBrowserDialog: function (imageUploader, e) {\n var $buttonEl = $(e.target),\n openDialogUrl = this.mediaGallery.openDialogUrl +\n 'target_element_id/' + $buttonEl.attr('id') +\n '/store/' + this.mediaGallery.storeId +\n '/type/image/?isAjax=true';\n\n if (this.mediaGallery.initialOpenSubpath) {\n openDialogUrl += '¤t_tree_path=' + Base64.idEncode(this.mediaGallery.initialOpenSubpath);\n }\n\n browser.openDialog(\n openDialogUrl,\n null,\n null,\n this.mediaGallery.openDialogTitle,\n {\n targetElementId: $buttonEl.attr('id')\n }\n );\n },\n\n /**\n * @param {jQuery.event} e\n * @param {Object} data\n * @returns {Object} Chainables\n */\n onDeleteFile: function (e, data) {\n var fileId = this.getFileId(),\n deletedFileIds = data.ids;\n\n if (fileId && $.inArray(fileId, deletedFileIds) > -1) {\n this.clear();\n }\n\n return this;\n },\n\n /**\n * {@inheritDoc}\n */\n clear: function () {\n this.value([]);\n\n return this;\n },\n\n /**\n * Gets the ID of the file used if set\n *\n * @return {String|Null} ID\n */\n getFileId: function () {\n return this.hasData() ? this.value()[0].id : null;\n },\n\n /**\n * Trigger native browser file upload UI via clicking on 'Upload' button\n *\n * @param {ImageUploader} imageUploader - UI Class\n * @param {Event} e\n */\n triggerImageUpload: function (imageUploader, e) {\n $(e.target).closest('.file-uploader').find('input[type=\"file\"]').trigger('click');\n },\n\n /**\n * Get list of file extensions allowed in comma delimited format\n *\n * @return {String}\n */\n getAllowedFileExtensionsInCommaDelimitedFormat: function () {\n var allowedExtensions = this.allowedExtensions.toUpperCase().split(' ');\n\n // if jpg and jpeg in allowed extensions, remove jpeg from list\n if (allowedExtensions.indexOf('JPG') !== -1 && allowedExtensions.indexOf('JPEG') !== -1) {\n allowedExtensions.splice(allowedExtensions.indexOf('JPEG'), 1);\n }\n\n return allowedExtensions.join(', ');\n }\n });\n});\n","Magento_Ui/js/form/element/textarea.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n './abstract'\n], function (Abstract) {\n 'use strict';\n\n return Abstract.extend({\n defaults: {\n cols: 15,\n rows: 2,\n elementTmpl: 'ui/form/element/textarea'\n }\n });\n});\n","Magento_Ui/js/form/element/post-code.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n './abstract'\n], function (_, Abstract) {\n 'use strict';\n\n return Abstract.extend({\n defaults: {\n imports: {\n countryOptions: '${ $.parentName }.country_id:indexedOptions',\n update: '${ $.parentName }.country_id:value'\n }\n },\n\n /**\n * Initializes observable properties of instance\n *\n * @returns {Abstract} Chainable.\n */\n initObservable: function () {\n this._super();\n\n /**\n * equalityComparer function\n *\n * @returns boolean.\n */\n this.value.equalityComparer = function (oldValue, newValue) {\n return !oldValue && !newValue || oldValue === newValue;\n };\n\n return this;\n },\n\n /**\n * Method called every time country selector's value gets changed.\n * Updates all validations and requirements for certain country.\n * @param {String} value - Selected country ID.\n */\n update: function (value) {\n var isZipCodeOptional,\n option;\n\n if (!value) {\n return;\n }\n\n option = _.isObject(this.countryOptions) && this.countryOptions[value];\n\n if (!option) {\n return;\n }\n\n isZipCodeOptional = !!option['is_zipcode_optional'];\n\n if (isZipCodeOptional) {\n this.error(false);\n }\n\n this.validation['required-entry'] = !isZipCodeOptional;\n this.required(!isZipCodeOptional);\n }\n });\n});\n","Magento_Ui/js/form/element/checkbox-set.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'mageUtils',\n './abstract'\n], function (_, utils, Abstract) {\n 'use strict';\n\n return Abstract.extend({\n defaults: {\n template: 'ui/form/element/checkbox-set',\n multiple: false,\n multipleScopeValue: null\n },\n\n /**\n * @inheritdoc\n */\n initConfig: function () {\n this._super();\n\n this.value = this.normalizeData(this.value);\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n initLinks: function () {\n var scope = this.source.get(this.dataScope);\n\n this.multipleScopeValue = this.multiple && _.isArray(scope) ? utils.copy(scope) : undefined;\n\n return this._super();\n },\n\n /**\n * @inheritdoc\n */\n reset: function () {\n this.value(utils.copy(this.initialValue));\n this.error(false);\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n clear: function () {\n var value = this.multiple ? [] : '';\n\n this.value(value);\n this.error(false);\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n normalizeData: function (value) {\n if (!this.multiple) {\n return this._super();\n }\n\n return _.isArray(value) ? utils.copy(value) : [];\n },\n\n /**\n * @inheritdoc\n */\n setInitialValue: function () {\n this._super();\n\n this.initialValue = utils.copy(this.initialValue);\n\n return this;\n },\n\n /**\n * @inheritdoc\n */\n getInitialValue: function () {\n var values = [this.multipleScopeValue, this.default, this.value.peek(), []],\n value;\n\n if (!this.multiple) {\n return this._super();\n }\n\n values.some(function (v) {\n return _.isArray(v) && (value = utils.copy(v));\n });\n\n return value;\n },\n\n /**\n * Returns labels which matches current value.\n *\n * @returns {String|Array}\n */\n getPreview: function () {\n var option;\n\n if (!this.multiple) {\n option = this.getOption(this.value());\n\n return option ? option.label : '';\n }\n\n return this.value.map(function (value) {\n return this.getOption(value).label;\n }, this);\n },\n\n /**\n * Returns option object associated with provided value.\n *\n * @param {String} value\n * @returns {Object}\n */\n getOption: function (value) {\n return _.findWhere(this.options, {\n value: value\n });\n },\n\n /**\n * @inheritdoc\n */\n hasChanged: function () {\n var value = this.value(),\n initial = this.initialValue;\n\n return this.multiple ?\n !utils.equalArrays(value, initial) :\n this._super();\n }\n });\n});\n","Magento_Ui/js/form/element/country.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'uiRegistry',\n './select'\n], function (_, registry, Select) {\n 'use strict';\n\n return Select.extend({\n defaults: {\n imports: {\n update: '${ $.parentName }.website_id:value'\n }\n },\n\n /**\n * Filters 'initialOptions' property by 'field' and 'value' passed,\n * calls 'setOptions' passing the result to it\n *\n * @param {*} value\n * @param {String} field\n */\n filter: function (value, field) {\n var result, defaultCountry, defaultValue;\n\n if (!field) { //validate field, if we are on update\n field = this.filterBy.field;\n }\n\n this._super(value, field);\n result = _.filter(this.initialOptions, function (item) {\n\n if (item[field]) {\n return ~item[field].indexOf(value);\n }\n\n return false;\n });\n\n this.setOptions(result);\n this.reset();\n\n if (!this.value()) {\n defaultCountry = _.filter(result, function (item) {\n return item['is_default'] && _.contains(item['is_default'], value);\n });\n\n if (defaultCountry.length) {\n defaultValue = defaultCountry.shift();\n this.value(defaultValue.value);\n }\n }\n }\n });\n});\n\n","Magento_Ui/js/form/element/color-picker-palette.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/**\n * @api\n */\ndefine([], function () {\n 'use strict';\n\n return [\n [\n 'rgb(0,0,0)', 'rgb(52,52,52)', 'rgb(83,83,83)', 'rgb(135,135,135)', 'rgb(193,193,193)',\n 'rgb(234,234,234)', 'rgb(240,240,240)', 'rgb(255,255,255)'\n ],\n [\n 'rgb(252,0,9)', 'rgb(253,135,10)', 'rgb(255,255,13)', 'rgb(35,255,9)', 'rgb(33,255,255)',\n 'rgb(0,0,254)', 'rgb(132,0,254)', 'rgb(251,0,255)'\n ],\n [\n 'rgb(240,192,194)', 'rgb(251,223,194)', 'rgb(255,241,193)', 'rgb(210,230,201)',\n 'rgb(199,217,220)', 'rgb(197,219,240)', 'rgb(208,200,227)', 'rgb(229,199,212)'\n ],\n [\n 'rgb(228,133,135)', 'rgb(246,193,139)', 'rgb(254,225,136)', 'rgb(168,208,152)',\n 'rgb(146,184,190)', 'rgb(143,184,227)', 'rgb(165,148,204)', 'rgb(202,147,175)'\n ],\n [\n 'rgb(214,78,83)', 'rgb(243,163,88)', 'rgb(254,211,83)', 'rgb(130,187,106)',\n 'rgb(99,149,159)', 'rgb(93,150,211)', 'rgb(123,100,182)', 'rgb(180,100,142)'\n ],\n [\n 'rgb(190,0,5)', 'rgb(222,126,44)', 'rgb(236,183,39)', 'rgb(89,155,61)', 'rgb(55,110,123)',\n 'rgb(49,112,185)', 'rgb(83,55,150)', 'rgb(147,55,101)'\n ],\n [\n 'rgb(133,0,3)', 'rgb(163,74,10)', 'rgb(177,127,7)', 'rgb(45,101,23)', 'rgb(18,62,74)',\n 'rgb(14,62,129)', 'rgb(40,15,97)', 'rgb(95,16,55)'\n ],\n [\n 'rgb(81,0,1)', 'rgb(100,48,7)', 'rgb(107,78,3)', 'rgb(31,63,16)',\n 'rgb(13,39,46)', 'rgb(10,40,79)', 'rgb(24,12,59)', 'rgb(59,10,36)'\n ]\n ];\n});\n","Magento_Ui/js/view/messages.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'ko',\n 'jquery',\n 'uiComponent',\n '../model/messageList',\n 'jquery-ui-modules/effect-blind'\n], function (ko, $, Component, globalMessages) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n template: 'Magento_Ui/messages',\n selector: '[data-role=checkout-messages]',\n isHidden: false,\n hideTimeout: 5000,\n hideSpeed: 500,\n listens: {\n isHidden: 'onHiddenChange'\n }\n },\n\n /** @inheritdoc */\n initialize: function (config, messageContainer) {\n this._super()\n .initObservable();\n\n this.messageContainer = messageContainer || config.messageContainer || globalMessages;\n\n return this;\n },\n\n /** @inheritdoc */\n initObservable: function () {\n this._super()\n .observe('isHidden');\n\n return this;\n },\n\n /**\n * Checks visibility.\n *\n * @return {Boolean}\n */\n isVisible: function () {\n return this.isHidden(this.messageContainer.hasMessages());\n },\n\n /**\n * Remove all messages.\n */\n removeAll: function () {\n this.messageContainer.clear();\n },\n\n /**\n * @param {Boolean} isHidden\n */\n onHiddenChange: function (isHidden) {\n // Hide message block if needed\n if (isHidden) {\n setTimeout(function () {\n $(this.selector).hide('slow');\n\n //commented because effect-blind.js(1.13.1) is having show & hide issue\n // $(this.selector).hide('blind', {}, this.hideSpeed);\n }.bind(this), this.hideTimeout);\n }\n }\n });\n});\n","Magento_Ui/js/core/app.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n './renderer/types',\n './renderer/layout',\n '../lib/knockout/bootstrap'\n], function (types, layout) {\n 'use strict';\n\n return function (data, merge) {\n types.set(data.types);\n layout(data.components, undefined, true, merge);\n };\n});\n","Magento_Ui/js/core/renderer/types.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'underscore',\n 'mageUtils'\n], function (_, utils) {\n 'use strict';\n\n var store = {};\n\n /**\n * Flatten a nested data.\n *\n * @param {Object} data\n * @returns {Object}\n */\n function flatten(data) {\n var extender = data.extends || [],\n result = {};\n\n extender = utils.stringToArray(extender);\n\n extender.push(data);\n\n extender.forEach(function (item) {\n if (_.isString(item)) {\n item = store[item] || {};\n }\n\n utils.extend(result, item);\n });\n\n delete result.extends;\n\n return result;\n }\n\n return {\n /**\n * Set types to store object.\n *\n * @param {Object} types\n */\n set: function (types) {\n types = types || {};\n\n utils.extend(store, types);\n\n _.each(types, function (data, type) {\n store[type] = flatten(data);\n });\n },\n\n /**\n * Get type from store object.\n *\n * @param {String} type\n * @returns {*|{}}\n */\n get: function (type) {\n return store[type] || {};\n }\n };\n});\n","Magento_Ui/js/core/renderer/layout.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'underscore',\n 'jquery',\n 'mageUtils',\n 'uiRegistry',\n './types',\n '../../lib/logger/console-logger'\n], function (_, $, utils, registry, types, consoleLogger) {\n 'use strict';\n\n var templates = registry.create(),\n layout = {},\n cachedConfig = {};\n\n /**\n * Build name from parent name and node name\n *\n * @param {Object} parent\n * @param {Object} node\n * @param {String} [name]\n * @returns {String}\n */\n function getNodeName(parent, node, name) {\n var parentName = parent && parent.name;\n\n if (typeof name !== 'string') {\n name = node.name || name;\n }\n\n return utils.fullPath(parentName, name);\n }\n\n /**\n * Get node type from node or parent.\n *\n * @param {Object} parent\n * @param {Object} node\n * @returns {String}\n */\n function getNodeType(parent, node) {\n return node.type || parent && parent.childType;\n }\n\n /**\n * Get data scope based on parent data scope and node data scope.\n *\n * @param {Object} parent\n * @param {Object} node\n * @returns {String}\n */\n function getDataScope(parent, node) {\n var dataScope = node.dataScope,\n parentScope = parent && parent.dataScope;\n\n return !utils.isEmpty(parentScope) ?\n !utils.isEmpty(dataScope) ?\n parentScope + '.' + dataScope :\n parentScope :\n dataScope || '';\n }\n\n /**\n * Load node dependencies on other instances.\n *\n * @param {Object} node\n * @returns {jQueryPromise}\n */\n function loadDeps(node) {\n var loaded = $.Deferred(),\n loggerUtils = consoleLogger.utils;\n\n if (node.deps) {\n consoleLogger.utils.asyncLog(\n loaded,\n {\n data: {\n component: node.name,\n deps: node.deps\n },\n messages: loggerUtils.createMessages(\n 'depsStartRequesting',\n 'depsFinishRequesting',\n 'depsLoadingFail'\n )\n }\n );\n }\n\n registry.get(node.deps, function (deps) {\n node.provider = node.extendProvider ? deps && deps.name : node.provider;\n loaded.resolve(node);\n });\n\n return loaded.promise();\n }\n\n /**\n * Load node component file via requirejs.\n *\n * @param {Object} node\n * @returns {jQueryPromise}\n */\n function loadSource(node) {\n var loaded = $.Deferred(),\n source = node.component;\n\n consoleLogger.info('componentStartLoading', {\n component: node.component\n });\n\n require([source], function (constr) {\n consoleLogger.info('componentFinishLoading', {\n component: node.component\n });\n loaded.resolve(node, constr);\n }, function () {\n consoleLogger.error('componentLoadingFail', {\n component: node.component\n });\n });\n\n return loaded.promise();\n }\n\n /**\n * Create a new component instance and set it to the registry.\n *\n * @param {Object} node\n * @param {Function} Constr\n */\n function initComponent(node, Constr) {\n var component = new Constr(_.omit(node, 'children'));\n\n consoleLogger.info('componentStartInitialization', {\n component: node.component,\n componentName: node.name\n });\n\n registry.set(node.name, component);\n }\n\n /**\n * Application entry point.\n *\n * @param {Object} nodes\n * @param {Object} parent\n * @param {Boolean} cached\n * @param {Boolean} merge\n * @returns {Boolean|undefined}\n */\n function run(nodes, parent, cached, merge) {\n if (_.isBoolean(merge) && merge) {\n layout.merge(nodes);\n\n return false;\n }\n\n if (cached) {\n cachedConfig[_.keys(nodes)[0]] = JSON.parse(JSON.stringify(nodes));\n }\n\n _.each(nodes || [], layout.iterator.bind(layout, parent));\n }\n\n _.extend(layout, {\n /**\n * Determines if node ready to be added or process it.\n *\n * @param {Object} parent\n * @param {Object|String} node\n */\n iterator: function (parent, node) {\n var action = _.isString(node) ?\n this.addChild :\n this.process;\n\n action.apply(this, arguments);\n },\n\n /**\n * Prepare component.\n *\n * @param {Object} parent\n * @param {Object} node\n * @param {String} name\n * @returns {Object}\n */\n process: function (parent, node, name) {\n if (!parent && node.parent) {\n return this.waitParent(node, name);\n }\n\n if (node.nodeTemplate) {\n return this.waitTemplate.apply(this, arguments);\n }\n\n node = this.build.apply(this, arguments);\n\n if (!registry.has(node.name)) {\n this.addChild(parent, node)\n .manipulate(node)\n .initComponent(node);\n }\n\n if (node) {\n run(node.children, node);\n }\n\n return this;\n },\n\n /**\n * Detailed processing of component config.\n *\n * @param {Object} parent\n * @param {Object} node\n * @param {String} name\n * @returns {Boolean|Object}\n */\n build: function (parent, node, name) {\n var defaults = parent && parent.childDefaults || {},\n children = this.filterDisabledChildren(node.children),\n type = getNodeType(parent, node),\n dataScope = getDataScope(parent, node),\n component,\n extendDeps = true,\n nodeName;\n\n node.children = false;\n node.extendProvider = true;\n\n if (node.config && node.config.provider || node.provider) {\n node.extendProvider = false;\n }\n\n if (node.config && node.config.deps || node.deps) {\n extendDeps = false;\n }\n\n node = utils.extend({\n }, types.get(type), defaults, node);\n\n nodeName = getNodeName(parent, node, name);\n\n if (registry.has(nodeName)) {\n component = registry.get(nodeName);\n component.children = children;\n\n return component;\n }\n\n if (extendDeps && parent && parent.deps && type) {\n node.deps = parent.deps;\n }\n\n _.extend(node, node.config || {}, {\n index: node.name || name,\n name: nodeName,\n dataScope: dataScope,\n parentName: utils.getPart(nodeName, -2),\n parentScope: utils.getPart(dataScope, -2)\n });\n\n node.children = children;\n node.componentType = node.type;\n\n delete node.type;\n delete node.config;\n\n if (children) {\n node.initChildCount = _.size(children);\n }\n\n if (node.isTemplate) {\n node.isTemplate = false;\n\n templates.set(node.name, node);\n registry.get(node.parentName, function (parentComp) {\n parentComp.childTemplate = node;\n });\n\n return false;\n }\n\n if (node.componentDisabled === true) {\n return false;\n }\n\n return node;\n },\n\n /**\n * Filter out all disabled components.\n *\n * @param {Object} children\n * @returns {*}\n */\n filterDisabledChildren: function (children) {\n var cIds;\n\n //cleanup children config.componentDisabled = true\n if (children && typeof children === 'object') {\n cIds = Object.keys(children);\n\n if (cIds) {\n _.each(cIds, function (cId) {\n if (typeof children[cId] === 'object' &&\n children[cId].hasOwnProperty('config') &&\n typeof children[cId].config === 'object' &&\n children[cId].config.hasOwnProperty('componentDisabled') &&\n children[cId].config.componentDisabled === true) {\n delete children[cId];\n }\n });\n }\n }\n\n return children;\n },\n\n /**\n * Init component.\n *\n * @param {Object} node\n * @returns {Object}\n */\n initComponent: function (node) {\n if (!node.component) {\n return this;\n }\n\n loadDeps(node)\n .then(loadSource)\n .done(initComponent);\n\n return this;\n }\n });\n\n _.extend(layout, {\n /**\n * Loading component marked as isTemplate.\n *\n * @param {Object} parent\n * @param {Object} node\n * @returns {Object}\n */\n waitTemplate: function (parent, node) {\n var args = _.toArray(arguments);\n\n templates.get(node.nodeTemplate, function () {\n this.applyTemplate.apply(this, args);\n }.bind(this));\n\n return this;\n },\n\n /**\n * Waiting for parent component and process provided component.\n *\n * @param {Object} node\n * @param {String} name\n * @returns {Object}\n */\n waitParent: function (node, name) {\n var process = this.process.bind(this);\n\n registry.get(node.parent, function (parent) {\n process(parent, node, name);\n });\n\n return this;\n },\n\n /**\n * Processing component marked as isTemplate.\n *\n * @param {Object} parent\n * @param {Object} node\n * @param {String} name\n */\n applyTemplate: function (parent, node, name) {\n var template = templates.get(node.nodeTemplate);\n\n node = utils.extend({}, template, node);\n\n delete node.nodeTemplate;\n\n this.process(parent, node, name);\n }\n });\n\n _.extend(layout, {\n /**\n * Determines inserting strategy.\n *\n * @param {Object} node\n * @returns {Object}\n */\n manipulate: function (node) {\n var name = node.name;\n\n if (node.appendTo) {\n this.insert(name, node.appendTo, -1);\n }\n\n if (node.prependTo) {\n this.insert(name, node.prependTo, 0);\n }\n\n if (node.insertTo) {\n this.insertTo(name, node.insertTo);\n }\n\n return this;\n },\n\n /**\n * Insert component to provide target and position.\n *\n * @param {Object|String} item\n * @param {Object} target\n * @param {Number} position\n * @returns {Object}\n */\n insert: function (item, target, position) {\n registry.get(target, function (container) {\n container.insertChild(item, position);\n });\n\n return this;\n },\n\n /**\n * Insert component into multiple targets.\n *\n * @param {Object} item\n * @param {Array} targets\n * @returns {Object}\n */\n insertTo: function (item, targets) {\n _.each(targets, function (info, target) {\n this.insert(item, target, info.position);\n }, this);\n\n return this;\n },\n\n /**\n * Add provided child to parent.\n *\n * @param {Object} parent\n * @param {Object|String} child\n * @returns {Object}\n */\n addChild: function (parent, child) {\n var name;\n\n if (parent && parent.component) {\n name = child.name || child;\n\n this.insert(name, parent.name, child.sortOrder);\n }\n\n return this;\n },\n\n /**\n * Merge components configuration with cached configuration.\n *\n * @param {Array} components\n */\n merge: function (components) {\n var cachedKey = _.keys(components)[0],\n compared = utils.compare(cachedConfig[cachedKey], components),\n remove = this.filterComponents(this.getByProperty(compared.changes, 'type', 'remove'), true),\n update = this.getByProperty(compared.changes, 'type', 'update'),\n dataSources = this.getDataSources(components),\n names, index, name, component;\n\n _.each(dataSources, function (val, key) {\n name = key.replace(/\\.children|\\.config/g, '');\n component = registry.get(name);\n\n component.cacheData();\n component.updateConfig(\n true,\n this.getFullConfig(key, components),\n this.getFullConfig(key, cachedConfig[cachedKey])\n );\n }, this);\n\n _.each(remove, function (val) {\n component = registry.get(val.path);\n\n if (component) {\n component.destroy();\n }\n });\n\n update = _.compact(_.filter(update, function (val) {\n return !_.isEqual(val.oldValue, val.value);\n }));\n\n _.each(update, function (val) {\n names = val.path.split('.');\n index = Math.max(_.lastIndexOf(names, 'config'), _.lastIndexOf(names, 'children') + 2);\n name = _.without(names.splice(0, index), 'children', 'config').join('.');\n component = registry.get(name);\n\n if (val.name === 'sortOrder' && component) {\n registry.get(component.parentName).insertChild(component, val.value);\n } else if (component) {\n component.updateConfig(\n val.oldValue,\n val.value,\n val.path\n );\n }\n }, this);\n\n run(components, undefined, true);\n },\n\n /**\n * Recursive dataSource assignment.\n *\n * @param {Object} config\n * @param {String} parentPath\n * @returns {Object}\n */\n getDataSources: function (config, parentPath) {\n var dataSources = {},\n key, obj;\n\n /* eslint-disable no-loop-func, max-depth */\n for (key in config) {\n if (config.hasOwnProperty(key)) {\n if (\n key === 'type' &&\n config[key] === 'dataSource' &&\n config.hasOwnProperty('config')\n ) {\n dataSources[parentPath + '.config'] = config.config;\n } else if (_.isObject(config[key])) {\n obj = this.getDataSources(config[key], utils.fullPath(parentPath, key));\n\n _.each(obj, function (value, path) {\n dataSources[path] = value;\n });\n }\n }\n }\n\n /* eslint-enable no-loop-func, max-depth */\n\n return dataSources;\n },\n\n /**\n * Configuration getter.\n *\n * @param {String} path\n * @param {Object} config\n * @returns {Boolean|Object}\n */\n getFullConfig: function (path, config) {\n var index;\n\n path = path.split('.');\n index = _.lastIndexOf(path, 'config');\n\n if (!~index) {\n return false;\n }\n path = path.splice(0, index);\n\n _.each(path, function (val) {\n config = config[val];\n });\n\n return config.config;\n },\n\n /**\n * Filter data by property and value.\n *\n * @param {Object} data\n * @param {String} prop\n * @param {*} propValue\n */\n getByProperty: function (data, prop, propValue) {\n return _.filter(data, function (value) {\n return value[prop] === propValue;\n });\n },\n\n /**\n * Filter components.\n *\n * @param {Array} data\n * @param {Boolean} splitPath\n * @param {Number} index\n * @param {String} separator\n * @param {String} keyName\n * @returns {Array}\n */\n filterComponents: function (data, splitPath, index, separator, keyName) {\n var result = [],\n names, length;\n\n index = -2;\n separator = '.' || separator;\n keyName = 'children' || keyName;\n\n _.each(data, function (val) {\n names = val.path.split(separator);\n length = names.length;\n\n if (names[length + index] === keyName) {\n val.path = splitPath ? _.without(names, keyName).join(separator) : val.path;\n result.push(val);\n }\n });\n\n return result;\n }\n });\n\n return run;\n});\n","Magento_Ui/js/model/messageList.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n './messages'\n], function (Messages) {\n 'use strict';\n\n return new Messages();\n});\n","Magento_Ui/js/model/messages.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'ko',\n 'uiClass'\n], function (ko, Class) {\n 'use strict';\n\n return Class.extend({\n /** @inheritdoc */\n initialize: function () {\n this._super()\n .initObservable();\n\n return this;\n },\n\n /** @inheritdoc */\n initObservable: function () {\n this.errorMessages = ko.observableArray([]);\n this.successMessages = ko.observableArray([]);\n\n return this;\n },\n\n /**\n * Add message to list.\n * @param {Object} messageObj\n * @param {Object} type\n * @returns {Boolean}\n */\n add: function (messageObj, type) {\n var expr = /([%])\\w+/g,\n message;\n\n if (!messageObj.hasOwnProperty('parameters')) {\n this.clear();\n type.push(messageObj.message);\n\n return true;\n }\n message = messageObj.message.replace(expr, function (varName) {\n varName = varName.substr(1);\n\n if (!isNaN(varName)) {\n varName--;\n }\n\n if (messageObj.parameters.hasOwnProperty(varName)) {\n return messageObj.parameters[varName];\n }\n\n return messageObj.parameters.shift();\n });\n this.clear();\n type.push(message);\n\n return true;\n },\n\n /**\n * Add success message.\n *\n * @param {Object} message\n * @return {*|Boolean}\n */\n addSuccessMessage: function (message) {\n return this.add(message, this.successMessages);\n },\n\n /**\n * Add error message.\n *\n * @param {Object} message\n * @return {*|Boolean}\n */\n addErrorMessage: function (message) {\n return this.add(message, this.errorMessages);\n },\n\n /**\n * Get error messages.\n *\n * @return {Array}\n */\n getErrorMessages: function () {\n return this.errorMessages;\n },\n\n /**\n * Get success messages.\n *\n * @return {Array}\n */\n getSuccessMessages: function () {\n return this.successMessages;\n },\n\n /**\n * Checks if an instance has stored messages.\n *\n * @return {Boolean}\n */\n hasMessages: function () {\n return this.errorMessages().length > 0 || this.successMessages().length > 0;\n },\n\n /**\n * Removes stored messages.\n */\n clear: function () {\n this.errorMessages.removeAll();\n this.successMessages.removeAll();\n }\n });\n});\n","Magento_Ui/js/lib/key-codes.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([], function () {\n 'use strict';\n\n return {\n 13: 'enterKey',\n 27: 'escapeKey',\n 40: 'pageDownKey',\n 38: 'pageUpKey',\n 32: 'spaceKey',\n 9: 'tabKey',\n 37: 'pageLeftKey',\n 39: 'pageRightKey',\n 17: 'ctrlKey',\n 18: 'altKey',\n 16: 'shiftKey',\n 191: 'forwardSlashKey',\n 66: 'bKey',\n 73: 'iKey',\n 85: 'uKey'\n };\n});\n","Magento_Ui/js/lib/spinner.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery'\n], function ($) {\n 'use strict';\n\n var selector = '[data-role=\"spinner\"]',\n spinner = $(selector);\n\n return {\n /**\n * Show spinner.\n */\n show: function () {\n spinner.show();\n },\n\n /**\n * Hide spinner.\n */\n hide: function () {\n spinner.hide();\n },\n\n /**\n * Get spinner by selector.\n *\n * @param {String} id\n * @return {jQuery}\n */\n get: function (id) {\n return $(selector + '[data-component=\"' + id + '\"]');\n }\n };\n});\n","Magento_Ui/js/lib/collapsible.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'uiComponent'\n], function (Component) {\n 'use strict';\n\n return Component.extend({\n defaults: {\n opened: false,\n collapsible: true\n },\n\n /**\n * Initializes observable properties.\n *\n * @returns {Collapsible} Chainable.\n */\n initObservable: function () {\n this._super()\n .observe('opened');\n\n return this;\n },\n\n /**\n * Toggles value of the 'opened' property.\n *\n * @returns {Collapsible} Chainable.\n */\n toggleOpened: function () {\n this.opened() ?\n this.close() :\n this.open();\n\n return this;\n },\n\n /**\n * Sets 'opened' flag to false.\n *\n * @returns {Collapsible} Chainable.\n */\n close: function () {\n if (this.collapsible) {\n this.opened(false);\n }\n\n return this;\n },\n\n /**\n * Sets 'opened' flag to true.\n *\n * @returns {Collapsible} Chainable.\n */\n open: function () {\n if (this.collapsible) {\n this.opened(true);\n }\n\n return this;\n }\n });\n});\n","Magento_Ui/js/lib/knockout/bootstrap.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/** Loads all available knockout bindings, sets custom template engine, initializes knockout on page */\n\ndefine([\n 'ko',\n './template/engine',\n 'knockoutjs/knockout-es5',\n './bindings/bootstrap',\n './extender/observable_array',\n './extender/bound-nodes',\n 'domReady!'\n], function (ko, templateEngine) {\n 'use strict';\n\n ko.uid = 0;\n\n ko.setTemplateEngine(templateEngine);\n ko.applyBindings();\n});\n","Magento_Ui/js/lib/knockout/extender/observable_array.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'ko',\n 'underscore'\n], function (ko, _) {\n 'use strict';\n\n /**\n * Iterator function.\n *\n * @param {String} callback\n * @param {Array} args\n * @param {Object} elem\n * @returns {*}\n */\n function iterator(callback, args, elem) {\n callback = elem[callback];\n\n if (_.isFunction(callback)) {\n return callback.apply(elem, args);\n }\n\n return callback;\n }\n\n /**\n * Wrapper function.\n *\n * @param {String} method\n * @returns {Function}\n */\n function wrapper(method) {\n return function (iteratee) {\n var callback = iteratee,\n elems = this(),\n args = _.toArray(arguments);\n\n if (_.isString(iteratee)) {\n callback = iterator.bind(null, iteratee, args.slice(1));\n\n args.unshift(callback);\n }\n\n args.unshift(elems);\n\n return _[method].apply(_, args);\n };\n }\n\n _.extend(ko.observableArray.fn, {\n each: wrapper('each'),\n\n map: wrapper('map'),\n\n filter: wrapper('filter'),\n\n some: wrapper('some'),\n\n every: wrapper('every'),\n\n groupBy: wrapper('groupBy'),\n\n sortBy: wrapper('sortBy'),\n\n /**\n * Wrapper for underscore findWhere function.\n *\n * @param {Object} properties\n * @return {Object}\n */\n findWhere: function (properties) {\n return _.findWhere(this(), properties);\n },\n\n /**\n * Wrapper for underscore contains function.\n *\n * @param {*} value\n * @return {Boolean}\n */\n contains: function (value) {\n return _.contains(this(), value);\n },\n\n /**\n * Inverse contains call.\n *\n * @return {Boolean}\n */\n hasNo: function () {\n return !this.contains.apply(this, arguments);\n },\n\n /**\n * Getter for length property.\n *\n * @return {Number}\n */\n getLength: function () {\n return this().length;\n },\n\n /**\n * Create object with keys that gets from each object property.\n *\n * @return {Object}\n */\n indexBy: function (key) {\n return _.indexBy(this(), key);\n },\n\n /**\n * Returns a copy of the array with all instances of the values removed.\n *\n * @return {Array}\n */\n without: function () {\n var args = Array.prototype.slice.call(arguments);\n\n args.unshift(this());\n\n return _.without.apply(_, args);\n },\n\n /**\n * Returns the first element of an array.\n *\n * @return {*}\n */\n first: function () {\n return _.first(this());\n },\n\n /**\n * Returns the last element of an array\n *\n * @return {*}\n */\n last: function () {\n return _.last(this());\n },\n\n /**\n * Iterate and pick provided properties.\n *\n * @return {Array}\n */\n pluck: function () {\n var args = Array.prototype.slice.call(arguments);\n\n args.unshift(this());\n\n return _.pluck.apply(_, args);\n }\n });\n});\n","Magento_Ui/js/lib/knockout/extender/bound-nodes.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'ko',\n 'underscore',\n 'mage/utils/wrapper',\n 'uiEvents'\n], function (ko, _, wrapper, Events) {\n 'use strict';\n\n var nodesMap = new WeakMap();\n\n /**\n * Returns a array of nodes associated with a specified model.\n *\n * @param {Object} model\n * @returns {Undefined|Array}\n */\n function getBounded(model) {\n return nodesMap.get(model);\n }\n\n /**\n * Removes specified node to models' associations list, if it's\n * a root node (node is not a descendant of any previously added nodes).\n * Triggers 'addNode' event.\n *\n * @param {Object} model\n * @param {HTMLElement} node\n */\n function addBounded(model, node) {\n var nodes = getBounded(model),\n isRoot;\n\n if (!nodes) {\n nodesMap.set(model, [node]);\n\n Events.trigger.call(model, 'addNode', node);\n\n return;\n }\n\n isRoot = nodes.every(function (bounded) {\n return !bounded.contains(node);\n });\n\n if (isRoot) {\n nodes.push(node);\n\n Events.trigger.call(model, 'addNode', node);\n }\n }\n\n /**\n * Removes specified node from models' associations list.\n * Triggers 'removeNode' event.\n *\n * @param {Object} model\n * @param {HTMLElement} node\n */\n function removeBounded(model, node) {\n var nodes = getBounded(model),\n index;\n\n if (!nodes) {\n return;\n }\n\n index = nodes.indexOf(node);\n\n if (~index) {\n nodes.splice(index, 0);\n\n Events.trigger.call(model, 'removeNode', node);\n }\n\n if (!nodes.length) {\n nodesMap.delete(model);\n }\n }\n\n /**\n * Returns node's first sibling of 'element' type within the common component scope\n *\n * @param {HTMLElement} node\n * @param {*} data\n * @returns {HTMLElement}\n */\n function getElement(node, data) {\n var elem;\n\n while (node.nextElementSibling) {\n node = node.nextElementSibling;\n\n if (node.nodeType === 1 && ko.dataFor(node) === data) {\n elem = node;\n break;\n }\n }\n\n return elem;\n }\n\n wrapper.extend(ko, {\n\n /**\n * Extends knockouts' 'applyBindings'\n * to track nodes associated with model.\n *\n * @param {Function} orig - Original 'applyBindings' method.\n * @param {Object} ctx\n * @param {HTMLElement} node - Original 'applyBindings' method.\n */\n applyBindings: function (orig, ctx, node) {\n var result = orig(),\n data = ctx && (ctx.$data || ctx);\n\n if (node && node.nodeType === 8) {\n node = getElement(node, data);\n }\n\n if (!node || node.nodeType !== 1) {\n return result;\n }\n\n if (data && data.registerNodes) {\n addBounded(data, node);\n }\n\n return result;\n },\n\n /**\n * Extends knockouts' cleanNode\n * to track nodes associated with model.\n *\n * @param {Function} orig - Original 'cleanNode' method.\n * @param {HTMLElement} node - Original 'cleanNode' method.\n */\n cleanNode: function (orig, node) {\n var result = orig(),\n data;\n\n if (node.nodeType !== 1) {\n return result;\n }\n\n data = ko.dataFor(node);\n\n if (data && data.registerNodes) {\n removeBounded(data, node);\n }\n\n return result;\n }\n });\n\n return {\n\n /**\n * Returns root nodes associated with a model. If callback is provided,\n * will iterate through all of the present nodes triggering callback\n * for each of it. Also it will subscribe to the 'addNode' event.\n *\n * @param {Object} model\n * @param {Function} [callback]\n * @returns {Array|Undefined}\n */\n get: function (model, callback) {\n var nodes = getBounded(model) || [];\n\n if (!_.isFunction(callback)) {\n return nodes;\n }\n\n nodes.forEach(function (node) {\n callback(node);\n });\n\n this.add.apply(this, arguments);\n },\n\n /**\n * Subscribes to adding of nodes associated with a model.\n *\n * @param {Object} model\n */\n add: function (model) {\n var args = _.toArray(arguments).slice(1);\n\n args.unshift('addNode');\n\n Events.on.apply(model, args);\n },\n\n /**\n * Subscribes to removal of nodes associated with a model.\n *\n * @param {Object} model\n */\n remove: function (model) {\n var args = _.toArray(arguments).slice(1);\n\n args.unshift('removeNode');\n\n Events.on.apply(model, args);\n },\n\n /**\n * Removes subscriptions from the model.\n *\n * @param {Object} model\n */\n off: function (model) {\n var args = _.toArray(arguments).slice(1);\n\n Events.off.apply(model, args);\n }\n };\n});\n","Magento_Ui/js/lib/knockout/template/observable_source.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/**\n * Is being used by knockout template engine to store template to.\n */\ndefine([\n 'ko',\n 'uiClass'\n], function (ko, Class) {\n 'use strict';\n\n return Class.extend({\n\n /**\n * Initializes templateName, _data, nodes properties.\n *\n * @param {template} template - identifier of template\n */\n initialize: function (template) {\n this.templateName = template;\n this._data = {};\n this.nodes = ko.observable([]);\n },\n\n /**\n * Data setter. If only one arguments passed, returns corresponding value.\n * Else, writes into it.\n * @param {String} key - key to write to or to read from\n * @param {*} value\n * @return {*} - if 1 arg provided, Returns _data[key] property\n */\n data: function (key, value) {\n if (arguments.length === 1) {\n return this._data[key];\n }\n\n this._data[key] = value;\n }\n });\n});\n","Magento_Ui/js/lib/knockout/template/renderer.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'underscore',\n './loader'\n], function ($, _, loader) {\n 'use strict';\n\n var colonReg = /\\\\:/g,\n renderedTemplatePromises = {},\n attributes = {},\n elements = {},\n globals = [],\n renderer,\n preset;\n\n renderer = {\n\n /**\n * Loads template by provided path and\n * than converts it's content to html.\n *\n * @param {String} tmplPath - Path to the template.\n * @returns {jQueryPromise}\n * @alias getRendered\n */\n render: function (tmplPath) {\n var cachedPromise = renderedTemplatePromises[tmplPath];\n\n if (!cachedPromise) {\n cachedPromise = renderedTemplatePromises[tmplPath] = loader\n .loadTemplate(tmplPath)\n .then(renderer.parseTemplate);\n }\n\n return cachedPromise;\n },\n\n /**\n * @ignore\n */\n getRendered: function (tmplPath) {\n return renderer.render(tmplPath);\n },\n\n /**\n * Parses provided string as html content\n * and returns an array of DOM elements.\n *\n * @param {String} html - String to be processed.\n * @returns {Array}\n */\n parseTemplate: function (html) {\n var fragment = document.createDocumentFragment();\n\n $(fragment).append(html);\n\n return renderer.normalize(fragment);\n },\n\n /**\n * Processes custom attributes and nodes of provided DOM element.\n *\n * @param {HTMLElement} content - Element to be processed.\n * @returns {Array} An array of content's child nodes.\n */\n normalize: function (content) {\n globals.forEach(function (handler) {\n handler(content);\n });\n\n return _.toArray(content.childNodes);\n },\n\n /**\n * Adds new global content handler.\n *\n * @param {Function} handler - Function which will be invoked for\n * an every content passed to 'normalize' method.\n * @returns {Renderer} Chainable.\n */\n addGlobal: function (handler) {\n if (!_.contains(globals, handler)) {\n globals.push(handler);\n }\n\n return this;\n },\n\n /**\n * Removes specified global content handler.\n *\n * @param {Function} handler - Handler to be removed.\n * @returns {Renderer} Chainable.\n */\n removeGlobal: function (handler) {\n var index = globals.indexOf(handler);\n\n if (~index) {\n globals.splice(index, 1);\n }\n\n return this;\n },\n\n /**\n * Adds new custom attribute handler.\n *\n * @param {String} id - Attribute identifier.\n * @param {(Object|Function)} [config={}]\n * @returns {Renderer} Chainable.\n */\n addAttribute: function (id, config) {\n var data = {\n name: id,\n binding: id,\n handler: renderer.handlers.attribute\n };\n\n if (_.isFunction(config)) {\n data.handler = config;\n } else if (_.isObject(config)) {\n _.extend(data, config);\n }\n\n data.id = id;\n attributes[id] = data;\n\n return this;\n },\n\n /**\n * Removes specified attribute handler.\n *\n * @param {String} id - Attribute identifier.\n * @returns {Renderer} Chainable.\n */\n removeAttribute: function (id) {\n delete attributes[id];\n\n return this;\n },\n\n /**\n * Adds new custom node handler.\n *\n * @param {String} id - Node identifier.\n * @param {(Object|Function)} [config={}]\n * @returns {Renderer} Chainable.\n */\n addNode: function (id, config) {\n var data = {\n name: id,\n binding: id,\n handler: renderer.handlers.node\n };\n\n if (_.isFunction(config)) {\n data.handler = config;\n } else if (_.isObject(config)) {\n _.extend(data, config);\n }\n\n data.id = id;\n elements[id] = data;\n\n return this;\n },\n\n /**\n * Removes specified custom node handler.\n *\n * @param {String} id - Node identifier.\n * @returns {Renderer} Chainable.\n */\n removeNode: function (id) {\n delete elements[id];\n\n return this;\n },\n\n /**\n * Checks if provided DOM element is a custom node.\n *\n * @param {HTMLElement} node - Node to be checked.\n * @returns {Boolean}\n */\n isCustomNode: function (node) {\n return _.some(elements, function (elem) {\n return elem.name.toUpperCase() === node.tagName;\n });\n },\n\n /**\n * Processes custom attributes of a content's child nodes.\n *\n * @param {HTMLElement} content - DOM element to be processed.\n */\n processAttributes: function (content) {\n var repeat;\n\n repeat = _.some(attributes, function (attr) {\n var attrName = attr.name,\n nodes = content.querySelectorAll('[' + attrName + ']'),\n handler = attr.handler;\n\n return _.toArray(nodes).some(function (node) {\n var data = node.getAttribute(attrName);\n\n return handler(node, data, attr) === true;\n });\n });\n\n if (repeat) {\n renderer.processAttributes(content);\n }\n },\n\n /**\n * Processes custom nodes of a provided content.\n *\n * @param {HTMLElement} content - DOM element to be processed.\n */\n processNodes: function (content) {\n var repeat;\n\n repeat = _.some(elements, function (element) {\n var nodes = content.querySelectorAll(element.name),\n handler = element.handler;\n\n return _.toArray(nodes).some(function (node) {\n var data = node.getAttribute('args');\n\n return handler(node, data, element) === true;\n });\n });\n\n if (repeat) {\n renderer.processNodes(content);\n }\n },\n\n /**\n * Wraps provided string in curly braces if it's necessary.\n *\n * @param {String} args - String to be wrapped.\n * @returns {String} Wrapped string.\n */\n wrapArgs: function (args) {\n if (~args.indexOf('\\\\:')) {\n args = args.replace(colonReg, ':');\n } else if (~args.indexOf(':') && !~args.indexOf('}')) {\n args = '{' + args + '}';\n }\n\n return args;\n },\n\n /**\n * Wraps child nodes of provided DOM element\n * with knockout's comment tag.\n *\n * @param {HTMLElement} node - Node whose children should be wrapped.\n * @param {String} binding - Name of the binding for the opener comment tag.\n * @param {String} data - Data associated with a binding.\n *\n * @example\n * <div id=\"example\"><span/></div>\n * wrapChildren(document.getElementById('example'), 'foreach', 'data');\n * =>\n * <div id=\"example\">\n * <!-- ko foreach: data -->\n * <span></span>\n * <!-- /ko -->\n * </div>\n */\n wrapChildren: function (node, binding, data) {\n var tag = this.createComment(binding, data),\n $node = $(node);\n\n $node.prepend(tag.open);\n $node.append(tag.close);\n },\n\n /**\n * Wraps specified node with knockout's comment tag.\n *\n * @param {HTMLElement} node - Node to be wrapped.\n * @param {String} binding - Name of the binding for the opener comment tag.\n * @param {String} data - Data associated with a binding.\n *\n * @example\n * <div id=\"example\"></div>\n * wrapNode(document.getElementById('example'), 'foreach', 'data');\n * =>\n * <!-- ko foreach: data -->\n * <div id=\"example\"></div>\n * <!-- /ko -->\n */\n wrapNode: function (node, binding, data) {\n var tag = this.createComment(binding, data),\n $node = $(node);\n\n $node.before(tag.open);\n $node.after(tag.close);\n },\n\n /**\n * Creates knockouts' comment tag for the provided binding.\n *\n * @param {String} binding - Name of the binding.\n * @param {String} data - Data associated with a binding.\n * @returns {Object} Object with an open and close comment elements.\n */\n createComment: function (binding, data) {\n return {\n open: document.createComment(' ko ' + binding + ': ' + data + ' '),\n close: document.createComment(' /ko ')\n };\n }\n };\n\n renderer.handlers = {\n\n /**\n * Basic node handler. Replaces custom nodes\n * with a corresponding knockout's comment tag.\n *\n * @param {HTMLElement} node - Node to be processed.\n * @param {String} data\n * @param {Object} element\n * @returns {Boolean} True\n *\n * @example Sample syntaxes conversions.\n * <with args=\"model\">\n * <span/>\n * </with>\n * =>\n * <!-- ko with: model-->\n * <span/>\n * <!-- /ko -->\n */\n node: function (node, data, element) {\n data = renderer.wrapArgs(data);\n\n renderer.wrapNode(node, element.binding, data);\n $(node).replaceWith(node.childNodes);\n\n return true;\n },\n\n /**\n * Base attribute handler. Replaces custom attributes with\n * a corresponding knockouts' data binding.\n *\n * @param {HTMLElement} node - Node to be processed.\n * @param {String} data - Data associated with a binding.\n * @param {Object} attr - Attribute definition.\n *\n * @example Sample syntaxes conversions.\n * <div text=\"label\"></div>\n * =>\n * <div data-bind=\"text: label\"></div>\n */\n attribute: function (node, data, attr) {\n data = renderer.wrapArgs(data);\n\n renderer.bindings.add(node, attr.binding, data);\n node.removeAttribute(attr.name);\n },\n\n /**\n * Wraps provided node with a knockouts' comment tag.\n *\n * @param {HTMLElement} node - Node that will be wrapped.\n * @param {String} data - Data associated with a binding.\n * @param {Object} attr - Attribute definition.\n *\n * @example\n * <div outereach=\"data\" class=\"test\"></div>\n * =>\n * <!-- ko foreach: data -->\n * <div class=\"test\"></div>\n * <!-- /ko -->\n */\n wrapAttribute: function (node, data, attr) {\n data = renderer.wrapArgs(data);\n\n renderer.wrapNode(node, attr.binding, data);\n node.removeAttribute(attr.name);\n }\n };\n\n renderer.bindings = {\n\n /**\n * Appends binding string to the current\n * 'data-bind' attribute of provided node.\n *\n * @param {HTMLElement} node - DOM element whose 'data-bind' attribute will be extended.\n * @param {String} name - Name of a binding.\n * @param {String} data - Data associated with the binding.\n */\n add: function (node, name, data) {\n var bindings = this.get(node);\n\n if (bindings) {\n bindings += ', ';\n }\n\n bindings += name;\n\n if (data) {\n bindings += ': ' + data;\n }\n\n this.set(node, bindings);\n },\n\n /**\n * Extracts value of a 'data-bind' attribute from provided node.\n *\n * @param {HTMLElement} node - Node whose attribute to be extracted.\n * @returns {String}\n */\n get: function (node) {\n return node.getAttribute('data-bind') || '';\n },\n\n /**\n * Sets 'data-bind' attribute of the specified node\n * to the provided value.\n *\n * @param {HTMLElement} node - Node whose attribute will be altered.\n * @param {String} bindings - New value of 'data-bind' attribute.\n */\n set: function (node, bindings) {\n node.setAttribute('data-bind', bindings);\n }\n };\n\n renderer\n .addGlobal(renderer.processAttributes)\n .addGlobal(renderer.processNodes);\n\n /**\n * Collection of default binding conversions.\n */\n preset = {\n nodes: _.object([\n 'if',\n 'text',\n 'with',\n 'scope',\n 'ifnot',\n 'foreach',\n 'component'\n ], Array.prototype),\n attributes: _.object([\n 'css',\n 'attr',\n 'html',\n 'with',\n 'text',\n 'click',\n 'event',\n 'submit',\n 'enable',\n 'disable',\n 'options',\n 'visible',\n 'template',\n 'hasFocus',\n 'textInput',\n 'component',\n 'uniqueName',\n 'optionsText',\n 'optionsValue',\n 'checkedValue',\n 'selectedOptions'\n ], Array.prototype)\n };\n\n _.extend(preset.attributes, {\n if: renderer.handlers.wrapAttribute,\n ifnot: renderer.handlers.wrapAttribute,\n innerif: {\n binding: 'if'\n },\n innerifnot: {\n binding: 'ifnot'\n },\n outereach: {\n binding: 'foreach',\n handler: renderer.handlers.wrapAttribute\n },\n foreach: {\n name: 'each'\n },\n value: {\n name: 'ko-value'\n },\n style: {\n name: 'ko-style'\n },\n checked: {\n name: 'ko-checked'\n },\n disabled: {\n name: 'ko-disabled',\n binding: 'disable'\n },\n focused: {\n name: 'ko-focused',\n binding: 'hasFocus'\n },\n\n /**\n * Custom 'render' attribute handler function. Wraps child elements\n * of a node with knockout's 'ko template:' comment tag.\n *\n * @param {HTMLElement} node - Element to be processed.\n * @param {String} data - Data specified in 'render' attribute of a node.\n */\n render: function (node, data) {\n data = data || 'getTemplate()';\n data = renderer.wrapArgs(data);\n\n renderer.wrapChildren(node, 'template', data);\n node.removeAttribute('render');\n }\n });\n\n _.extend(preset.nodes, {\n foreach: {\n name: 'each'\n },\n\n /**\n * Custom 'render' node handler function.\n * Replaces node with knockout's 'ko template:' comment tag.\n *\n * @param {HTMLElement} node - Element to be processed.\n * @param {String} data - Data specified in 'args' attribute of a node.\n */\n render: function (node, data) {\n data = data || 'getTemplate()';\n data = renderer.wrapArgs(data);\n\n renderer.wrapNode(node, 'template', data);\n $(node).replaceWith(node.childNodes);\n }\n });\n\n _.each(preset.attributes, function (data, id) {\n renderer.addAttribute(id, data);\n });\n\n _.each(preset.nodes, function (data, id) {\n renderer.addNode(id, data);\n });\n\n return renderer;\n});\n","Magento_Ui/js/lib/knockout/template/engine.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'ko',\n 'underscore',\n './observable_source',\n './renderer',\n '../../logger/console-logger'\n], function ($, ko, _, Source, renderer, consoleLogger) {\n 'use strict';\n\n var RemoteTemplateEngine,\n NativeTemplateEngine = ko.nativeTemplateEngine,\n sources = {};\n\n /**\n * Remote template engine class. Is used to be able to load remote templates via knockout template binding.\n */\n RemoteTemplateEngine = function () {\n // Instance reference for closure.\n var engine = this,\n // Decorate the builtin Knockout \"template\" binding to track synchronous template renders.\n origUpdate = ko.bindingHandlers.template.update;\n\n /**\n * Counter to track the number of currently running render tasks (both synchronous and asynchronous).\n * @type {Number}\n * @private\n */\n this._rendersOutstanding = 0;\n\n /**\n * Use a jQuery object as an event bus (but any event emitter with on/off/emit methods could work)\n * @type {jQuery}\n * @private\n */\n this._events = $(this);\n\n /**\n * Rendered templates\n * @type {Object}\n * @private\n */\n this._templatesRendered = {};\n\n /*eslint-disable no-unused-vars*/\n /**\n * Decorate update method\n *\n * @param {HTMLElement} element\n * @param {Function} valueAccessor\n * @param {Object} allBindings\n * @param {Object} viewModel\n * @param {ko.bindingContext} bindingContext\n * @returns {*}\n */\n ko.bindingHandlers.template.update = function (element, valueAccessor, allBindings, viewModel, bindingContext) {\n /*eslint-enable no-unused-vars*/\n var options = ko.utils.peekObservable(valueAccessor()),\n templateName,\n isSync,\n updated;\n\n if (typeof options === 'object') {\n if (options.templateEngine && options.templateEngine !== engine) {\n return origUpdate.apply(this, arguments);\n }\n\n if (!options.name) {\n consoleLogger.error('Could not find template name', options);\n }\n templateName = options.name;\n } else if (typeof options === 'string') {\n templateName = options;\n } else {\n consoleLogger.error('Could not build a template binding', options);\n }\n engine._trackRender(templateName);\n isSync = engine._hasTemplateLoaded(templateName);\n updated = origUpdate.apply(this, arguments);\n\n if (isSync) {\n engine._releaseRender(templateName, 'sync');\n }\n\n return updated;\n };\n };\n\n /**\n * Creates unique template identifier based on template name and it's extenders (optional)\n * @param {String} templateName\n * @return {String} - unique template identifier\n */\n function createTemplateIdentifier(templateName) {\n return templateName;\n }\n\n RemoteTemplateEngine.prototype = new NativeTemplateEngine;\n RemoteTemplateEngine.prototype.constructor = RemoteTemplateEngine;\n\n /**\n * When an asynchronous render task begins, increment the internal counter for tracking when renders are complete.\n * @private\n */\n RemoteTemplateEngine.prototype._trackRender = function (templateName) {\n var rendersForTemplate = this._templatesRendered[templateName] !== undefined ?\n this._templatesRendered[templateName] : 0;\n\n this._rendersOutstanding++;\n this._templatesRendered[templateName] = rendersForTemplate + 1;\n this._resolveRenderWaits();\n };\n\n /**\n * When an asynchronous render task ends, decrement the internal counter for tracking when renders are complete.\n * @private\n */\n RemoteTemplateEngine.prototype._releaseRender = function (templateName) {\n var rendersForTemplate = this._templatesRendered[templateName];\n\n this._rendersOutstanding--;\n this._templatesRendered[templateName] = rendersForTemplate - 1;\n this._resolveRenderWaits();\n };\n\n /**\n * Check to see if renders are complete and trigger events for listeners.\n * @private\n */\n RemoteTemplateEngine.prototype._resolveRenderWaits = function () {\n if (this._rendersOutstanding === 0) {\n this._events.triggerHandler('finishrender');\n }\n };\n\n /**\n * Get a promise for the end of the current run of renders, both sync and async.\n * @return {jQueryPromise} - promise that resolves when render completes\n */\n RemoteTemplateEngine.prototype.waitForFinishRender = function () {\n var defer = $.Deferred();\n\n this._events.one('finishrender', defer.resolve);\n\n return defer.promise();\n };\n\n /**\n * Returns true if this template has already been asynchronously loaded and will be synchronously rendered.\n * @param {String} templateName\n * @returns {Boolean}\n * @private\n */\n RemoteTemplateEngine.prototype._hasTemplateLoaded = function (templateName) {\n // Sources object will have cached template once makeTemplateSource has run\n return sources.hasOwnProperty(templateName);\n };\n\n /**\n * Overrided method of native knockout template engine.\n * Caches template after it's unique name and renders in once.\n * If template name is not typeof string, delegates work to knockout.templateSources.anonymousTemplate.\n * @param {*} template\n * @param {HTMLElement} templateDocument - document\n * @param {Object} options - options, passed to template binding\n * @param {ko.bindingContext} bindingContext\n * @returns {TemplateSource} Object with methods 'nodes' and 'data'.\n */\n RemoteTemplateEngine.prototype.makeTemplateSource = function (template, templateDocument, options, bindingContext) {\n var engine = this,\n source,\n templateId;\n\n if (typeof template === 'string') {\n templateId = createTemplateIdentifier(template);\n source = sources[templateId];\n\n if (!source) {\n source = new Source(template);\n source.requestedBy = bindingContext.$data.name;\n sources[templateId] = source;\n\n consoleLogger.info('templateStartLoading', {\n template: templateId,\n component: bindingContext.$data.name\n });\n\n renderer.render(template).then(function (rendered) {\n consoleLogger.info('templateLoadedFromServer', {\n template: templateId,\n component: bindingContext.$data.name\n });\n source.nodes(rendered);\n engine._releaseRender(templateId, 'async');\n }).fail(function () {\n consoleLogger.error('templateLoadingFail', {\n template: templateId,\n component: bindingContext.$data.name\n });\n });\n }\n\n if (source.requestedBy !== bindingContext.$data.name) {\n consoleLogger.info('templateLoadedFromCache', {\n template: templateId,\n component: bindingContext.$data.name\n });\n }\n\n return source;\n } else if (template.nodeType === 1 || template.nodeType === 8) {\n source = new ko.templateSources.anonymousTemplate(template);\n\n return source;\n }\n\n throw new Error('Unknown template type: ' + template);\n };\n\n /**\n * Overrided method of native knockout template engine.\n * Should return array of html elements.\n * @param {TemplateSource} templateSource - object with methods 'nodes' and 'data'.\n * @return {Array} - array of html elements\n */\n RemoteTemplateEngine.prototype.renderTemplateSource = function (templateSource) {\n var nodes = templateSource.nodes();\n\n return ko.utils.cloneNodes(nodes);\n };\n\n /**\n * Overrided method of native knockout template engine.\n * Created in order to invoke makeTemplateSource method with custom set of params.\n * @param {*} template - template identifier\n * @param {ko.bindingContext} bindingContext\n * @param {Object} options - options, passed to template binding\n * @param {HTMLElement} templateDocument - document\n * @return {Array} - array of html elements\n */\n RemoteTemplateEngine.prototype.renderTemplate = function (template, bindingContext, options, templateDocument) {\n var templateSource = this.makeTemplateSource(template, templateDocument, options, bindingContext);\n\n return this.renderTemplateSource(templateSource);\n };\n\n return new RemoteTemplateEngine;\n});\n","Magento_Ui/js/lib/knockout/template/loader.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery'\n], function ($) {\n 'use strict';\n\n var licenseRegExp = /<!--[\\s\\S]*?-->/,\n defaultPlugin = 'text',\n defaultExt = 'html';\n\n /**\n * Checks of provided string contains a file extension.\n *\n * @param {String} str - String to be checked.\n * @returns {Boolean}\n */\n function hasFileExtension(str) {\n return !!~str.indexOf('.') && !!str.split('.').pop();\n }\n\n /**\n * Checks if provided string contains a requirejs's plugin reference.\n *\n * @param {String} str - String to be checked.\n * @returns {Boolean}\n */\n function hasPlugin(str) {\n return !!~str.indexOf('!');\n }\n\n /**\n * Checks if provided string is a full path to the file.\n *\n * @param {String} str - String to be checked.\n * @returns {Boolean}\n */\n function isFullPath(str) {\n return !!~str.indexOf('://');\n }\n\n /**\n * Removes license comment from the provided string.\n *\n * @param {String} content - String to be processed.\n * @returns {String}\n */\n function removeLicense(content) {\n return content.replace(licenseRegExp, function (match) {\n return ~match.indexOf('/**') ? '' : match;\n });\n }\n\n return {\n\n /**\n * Attempts to extract template by provided path from\n * a DOM element and falls back to a file loading if\n * none of the DOM nodes was found.\n *\n * @param {String} path - Path to the template or a DOM selector.\n * @returns {jQueryPromise}\n */\n loadTemplate: function (path) {\n var content = this.loadFromNode(path),\n defer;\n\n if (content) {\n defer = $.Deferred();\n\n defer.resolve(content);\n\n return defer.promise();\n }\n\n return this.loadFromFile(path);\n },\n\n /**\n * Loads template from external file by provided\n * path, which will be preliminary formatted.\n *\n * @param {String} path - Path to the template.\n * @returns {jQueryPromise}\n */\n loadFromFile: function (path) {\n var loading = $.Deferred();\n\n path = this.formatPath(path);\n\n require([path], function (template) {\n template = removeLicense(template);\n loading.resolve(template);\n }, function (err) {\n loading.reject(err);\n });\n\n return loading.promise();\n },\n\n /**\n * Attempts to extract content of a node found by provided selector.\n *\n * @param {String} selector - Node's selector (not necessary valid).\n * @returns {String|Boolean} If specified node doesn't exists\n * 'false' will be returned, otherwise returns node's content.\n */\n loadFromNode: function (selector) {\n var node;\n\n try {\n node =\n document.getElementById(selector) ||\n document.querySelector(selector);\n\n return node ? node.innerHTML : false;\n } catch (e) {\n return false;\n }\n },\n\n /**\n * Adds requirejs's plugin and file extension to\n * to the provided string if it's necessary.\n *\n * @param {String} path - Path to be processed.\n * @returns {String} Formatted path.\n */\n formatPath: function (path) {\n var result = path;\n\n if (!hasPlugin(path)) {\n result = defaultPlugin + '!' + result;\n }\n\n if (isFullPath(path)) {\n return result;\n }\n\n if (!hasFileExtension(path)) {\n result += '.' + defaultExt;\n }\n\n return result.replace(/^([^\\/]+)/g, '$1/template');\n }\n };\n});\n","Magento_Ui/js/lib/knockout/bindings/keyboard.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'ko',\n '../template/renderer'\n], function (ko, renderer) {\n 'use strict';\n\n ko.bindingHandlers.keyboard = {\n\n /**\n * Attaches keypress handlers to element\n * @param {HTMLElement} el - Element, that binding is applied to\n * @param {Function} valueAccessor - Function that returns value, passed to binding\n * @param {Object} allBindings - all bindings object\n * @param {Object} viewModel - reference to viewmodel\n */\n init: function (el, valueAccessor, allBindings, viewModel) {\n var map = valueAccessor();\n\n ko.utils.registerEventHandler(el, 'keyup', function (e) {\n var callback = map[e.keyCode];\n\n if (callback) {\n return callback.call(viewModel, e);\n }\n });\n }\n };\n\n renderer.addAttribute('keyboard');\n});\n","Magento_Ui/js/lib/knockout/bindings/tooltip.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'ko',\n 'underscore',\n 'mage/template',\n 'text!ui/template/tooltip/tooltip.html',\n '../template/renderer'\n], function ($, ko, _, template, tooltipTmpl, renderer) {\n 'use strict';\n\n var tooltip,\n defaults,\n positions,\n transformProp,\n checkedPositions = {},\n iterator = 0,\n previousTooltip,\n tooltipData,\n positionData = {},\n tooltipsCollection = {},\n isTouchDevice = (function () {\n return 'ontouchstart' in document.documentElement;\n })(),\n CLICK_EVENT = (function () {\n return isTouchDevice ? 'touchstart' : 'click';\n })();\n\n defaults = {\n tooltipWrapper: '[data-tooltip=tooltip-wrapper]',\n tooltipContentBlock: 'data-tooltip-content',\n closeButtonClass: 'action-close',\n tailClass: 'data-tooltip-tail',\n action: 'hover',\n delay: 300,\n track: false,\n step: 20,\n position: 'top',\n closeButton: false,\n showed: false,\n strict: true,\n center: false,\n closeOnScroll: true\n };\n\n tooltipData = {\n tooltipClasses: '',\n trigger: false,\n timeout: 0,\n element: false,\n event: false,\n targetElement: {},\n showed: false,\n currentID: 0\n };\n\n /**\n * Polyfill for css transform\n */\n transformProp = (function () {\n var style = document.createElement('div').style,\n base = 'Transform',\n vendors = ['webkit', 'moz', 'ms', 'o'],\n vi = vendors.length,\n property;\n\n if (typeof style.transform !== 'undefined') {\n return 'transform';\n }\n\n while (vi--) {\n property = vendors[vi] + base;\n\n if (typeof style[property] !== 'undefined') {\n return property;\n }\n }\n })();\n\n positions = {\n\n /*eslint max-depth: [0, 0]*/\n\n map: {\n horizontal: {\n s: 'w',\n p: 'left'\n },\n vertical: {\n s: 'h',\n p: 'top'\n }\n },\n\n /**\n * Wrapper function to get tooltip data (position, className, etc)\n *\n * @param {Object} s - object with sizes and positions elements\n * @returns {Object} tooltip data (position, className, etc)\n */\n top: function (s) {\n return positions._topLeftChecker(s, positions.map, 'vertical', '_bottom', 'top', 'right');\n },\n\n /**\n * Wrapper function to get tooltip data (position, className, etc)\n *\n * @param {Object} s - object with sizes and positions elements\n * @returns {Object} tooltip data (position, className, etc)\n */\n left: function (s) {\n return positions._topLeftChecker(s, positions.map, 'horizontal', '_right', 'left', 'top');\n },\n\n /**\n * Wrapper function to get tooltip data (position, className, etc)\n *\n * @param {Object} s - object with sizes and positions elements\n * @returns {Object} tooltip data (position, className, etc)\n */\n bottom: function (s) {\n return positions._bottomRightChecker(s, positions.map, 'vertical', '_top', 'bottom', 'left');\n },\n\n /**\n * Wrapper function to get tooltip data (position, className, etc)\n *\n * @param {Object} s - object with sizes and positions elements\n * @returns {Object} tooltip data (position, className, etc)\n */\n right: function (s) {\n return positions._bottomRightChecker(s, positions.map, 'horizontal', '_left', 'right', 'bottom');\n },\n\n /**\n * Check can tooltip setted on current position or not. If can't setted - delegate call.\n *\n * @param {Object} s - object with sizes and positions elements\n * @param {Object} map - mapping for get direction positions\n * @param {String} direction - vertical or horizontal\n * @param {String} className - class whats should be setted to tooltip\n * @param {String} side - parent method name\n * @param {String} delegate - method name if tooltip can't be setted in current position\n * @returns {Object} tooltip data (position, className, etc)\n */\n _topLeftChecker: function (s, map, direction, className, side, delegate) {\n var result = {\n position: {}\n },\n config = tooltip.getTooltip(tooltipData.currentID),\n startPosition = !config.strict ? s.eventPosition : s.elementPosition,\n changedDirection;\n\n checkedPositions[side] = true;\n\n if (\n startPosition[map[direction].p] - s.tooltipSize[map[direction].s] - config.step >\n s.scrollPosition[map[direction].p]\n ) {\n result.position[map[direction].p] = startPosition[map[direction].p] - s.tooltipSize[map[direction].s] -\n config.step;\n result.className = className;\n result.side = side;\n changedDirection = direction === 'vertical' ? 'horizontal' : 'vertical';\n result = positions._normalize(s, result, config, delegate, map, changedDirection);\n } else if (!checkedPositions[delegate]) {\n result = positions[delegate].apply(null, arguments);\n } else {\n result = positions.positionCenter(s, result);\n }\n\n return result;\n },\n\n /**\n * Check can tooltip setted on current position or not. If can't setted - delegate call.\n *\n * @param {Object} s - object with sizes and positions elements\n * @param {Object} map - mapping for get direction positions\n * @param {String} direction - vertical or horizontal\n * @param {String} className - class whats should be setted to tooltip\n * @param {String} side - parent method name\n * @param {String} delegate - method name if tooltip can't be setted in current position\n * @returns {Object} tooltip data (position, className, etc)\n */\n _bottomRightChecker: function (s, map, direction, className, side, delegate) {\n var result = {\n position: {}\n },\n config = tooltip.getTooltip(tooltipData.currentID),\n startPosition = !config.strict ? s.eventPosition : {\n top: s.elementPosition.top + s.elementSize.h,\n left: s.elementPosition.left + s.elementSize.w\n },\n changedDirection;\n\n checkedPositions[side] = true;\n\n if (\n startPosition[map[direction].p] + s.tooltipSize[map[direction].s] + config.step <\n s.scrollPosition[map[direction].p] + s.windowSize[map[direction].s]\n ) {\n result.position[map[direction].p] = startPosition[map[direction].p] + config.step;\n result.className = className;\n result.side = side;\n changedDirection = direction === 'vertical' ? 'horizontal' : 'vertical';\n result = positions._normalize(s, result, config, delegate, map, changedDirection);\n } else if (!checkedPositions[delegate]) {\n result = positions[delegate].apply(null, arguments);\n } else {\n result = positions.positionCenter(s, result);\n }\n\n return result;\n },\n\n /**\n * Centered tooltip if tooltip does not fit in window\n *\n * @param {Object} s - object with sizes and positions elements\n * @param {Object} data - current data (position, className, etc)\n * @returns {Object} tooltip data (position, className, etc)\n */\n positionCenter: function (s, data) {\n data = positions._positionCenter(s, data, 'horizontal', positions.map);\n data = positions._positionCenter(s, data, 'vertical', positions.map);\n\n return data;\n },\n\n /**\n * Centered tooltip side\n *\n * @param {Object} s - object with sizes and positions elements\n * @param {Object} data - current data (position, className, etc)\n * @param {String} direction - vertical or horizontal\n * @param {Object} map - mapping for get direction positions\n * @returns {Object} tooltip data (position, className, etc)\n */\n _positionCenter: function (s, data, direction, map) {\n if (s.tooltipSize[map[direction].s] < s.windowSize[map[direction].s]) {\n data.position[map[direction].p] = (s.windowSize[map[direction].s] -\n s.tooltipSize[map[direction].s]) / 2 + s.scrollPosition[map[direction].p];\n } else {\n data.position[map[direction].p] = s.scrollPosition[map[direction].p];\n data.tooltipSize = {};\n data.tooltipSize[map[direction].s] = s.windowSize[map[direction].s];\n }\n\n return data;\n },\n\n /**\n * Normalize horizontal or vertical position.\n *\n * @param {Object} s - object with sizes and positions elements\n * @param {Object} data - current data (position, className, etc)\n * @param {Object} config - tooltip config\n * @param {String} delegate - method name if tooltip can't be setted in current position\n * @param {Object} map - mapping for get direction positions\n * @param {String} direction - vertical or horizontal\n * @returns {Object} tooltip data (position, className, etc)\n */\n _normalize: function (s, data, config, delegate, map, direction) {\n var startPosition = !config.center ? s.eventPosition : {\n left: s.elementPosition.left + s.elementSize.w / 2,\n top: s.elementPosition.top + s.elementSize.h / 2\n },\n depResult;\n\n if (startPosition[map[direction].p] - s.tooltipSize[map[direction].s] / 2 >\n s.scrollPosition[map[direction].p] && startPosition[map[direction].p] +\n s.tooltipSize[map[direction].s] / 2 <\n s.scrollPosition[map[direction].p] + s.windowSize[map[direction].s]\n ) {\n data.position[map[direction].p] = startPosition[map[direction].p] - s.tooltipSize[map[direction].s] / 2;\n } else {\n\n /*eslint-disable no-lonely-if*/\n if (!checkedPositions[delegate]) {\n depResult = positions[delegate].apply(null, arguments);\n\n if (depResult.hasOwnProperty('className')) {\n data = depResult;\n } else {\n data = positions._normalizeTail(s, data, config, delegate, map, direction, startPosition);\n }\n } else {\n data = positions._normalizeTail(s, data, config, delegate, map, direction, startPosition);\n }\n }\n\n return data;\n },\n\n /**\n * Calc tail position.\n *\n * @param {Object} s - object with sizes and positions elements\n * @param {Object} data - current data (position, className, etc)\n * @param {Object} config - tooltip config\n * @param {String} delegate - method name if tooltip can't be setted in current position\n * @param {Object} map - mapping for get direction positions\n * @param {String} direction - vertical or horizontal\n * @param {Object} startPosition - start position\n * @returns {Object} tooltip data (position, className, etc)\n */\n _normalizeTail: function (s, data, config, delegate, map, direction, startPosition) {\n data.tail = {};\n\n if (s.tooltipSize[map[direction].s] < s.windowSize[map[direction].s]) {\n\n if (\n startPosition[map[direction].p] >\n s.windowSize[map[direction].s] / 2 + s.scrollPosition[map[direction].p]\n ) {\n data.position[map[direction].p] = s.windowSize[map[direction].s] +\n s.scrollPosition[map[direction].p] - s.tooltipSize[map[direction].s];\n data.tail[map[direction].p] = startPosition[map[direction].p] -\n s.tooltipSize[map[direction].s] / 2 - data.position[map[direction].p];\n } else {\n data.position[map[direction].p] = s.scrollPosition[map[direction].p];\n data.tail[map[direction].p] = startPosition[map[direction].p] -\n s.tooltipSize[map[direction].s] / 2 - data.position[map[direction].p];\n }\n } else {\n data.position[map[direction].p] = s.scrollPosition[map[direction].p];\n data.tail[map[direction].p] = s.eventPosition[map[direction].p] - s.windowSize[map[direction].s] / 2;\n data.tooltipSize = {};\n data.tooltipSize[map[direction].s] = s.windowSize[map[direction].s];\n }\n\n return data;\n }\n };\n\n tooltip = {\n\n /**\n * Set new tooltip to tooltipCollection, save config, and add unic id\n *\n * @param {Object} config - tooltip config\n * @returns {String} tooltip id\n */\n setTooltip: function (config) {\n var property = 'id-' + iterator;\n\n tooltipsCollection[property] = config;\n iterator++;\n\n return property;\n },\n\n /**\n * Get tooltip config by id\n *\n * @param {String} id - tooltip id\n * @returns {Object} tooltip config\n */\n getTooltip: function (id) {\n return tooltipsCollection[id];\n },\n\n /**\n * Set content to current tooltip\n *\n * @param {Object} tooltipElement - tooltip element\n * @param {Object} viewModel - tooltip view model\n * @param {String} id - tooltip id\n * @param {Object} bindingCtx - tooltip context\n * @param {Object} event - action event\n */\n setContent: function (tooltipElement, viewModel, id, bindingCtx, event) {\n var html = $(tooltipElement).html(),\n config = tooltip.getTooltip(id),\n body = $('body');\n\n tooltipData.currentID = id;\n tooltipData.trigger = $(event.currentTarget);\n tooltip.setTargetData(event);\n body.on('mousemove.setTargetData', tooltip.setTargetData);\n tooltip.clearTimeout(id);\n\n tooltipData.timeout = _.delay(function () {\n body.off('mousemove.setTargetData', tooltip.setTargetData);\n\n if (tooltipData.trigger[0] === tooltipData.targetElement) {\n tooltip.destroy(id);\n event.stopPropagation();\n tooltipElement = tooltip.createTooltip(id);\n tooltipElement.find('.' + defaults.tooltipContentBlock).append(html);\n tooltipElement.applyBindings(bindingCtx);\n tooltip.setHandlers(id);\n tooltip.setPosition(tooltipElement, id);\n previousTooltip = id;\n }\n\n }, config.delay);\n },\n\n /**\n * Set position to current tooltip\n *\n * @param {Object} tooltipElement - tooltip element\n * @param {String} id - tooltip id\n */\n setPosition: function (tooltipElement, id) {\n var config = tooltip.getTooltip(id);\n\n tooltip.sizeData = {\n windowSize: {\n h: $(window).outerHeight(),\n w: $(window).outerWidth()\n },\n scrollPosition: {\n top: $(window).scrollTop(),\n left: $(window).scrollLeft()\n },\n tooltipSize: {\n h: tooltipElement.outerHeight(),\n w: tooltipElement.outerWidth()\n },\n elementSize: {\n h: tooltipData.trigger.outerHeight(),\n w: tooltipData.trigger.outerWidth()\n },\n elementPosition: tooltipData.trigger.offset(),\n eventPosition: this.getEventPosition(tooltipData.event)\n };\n\n _.extend(positionData, positions[config.position](tooltip.sizeData));\n tooltipElement.css(positionData.position);\n tooltipElement.addClass(positionData.className);\n tooltip._setTooltipSize(positionData, tooltipElement);\n tooltip._setTailPosition(positionData, tooltipElement);\n checkedPositions = {};\n },\n\n /**\n * Check position data and change tooltip size if needs\n *\n * @param {Object} data - position data\n * @param {Object} tooltipElement - tooltip element\n */\n _setTooltipSize: function (data, tooltipElement) {\n if (data.tooltipSize) {\n data.tooltipSize.w ?\n tooltipElement.css('width', data.tooltipSize.w) :\n tooltipElement.css('height', data.tooltipSize.h);\n }\n },\n\n /**\n * Check position data and set position to tail\n *\n * @param {Object} data - position data\n * @param {Object} tooltipElement - tooltip element\n */\n _setTailPosition: function (data, tooltipElement) {\n var tail,\n tailMargin;\n\n if (data.tail) {\n tail = tooltipElement.find('.' + defaults.tailClass);\n\n if (data.tail.left) {\n tailMargin = parseInt(tail.css('margin-left'), 10);\n tail.css('margin-left', tailMargin + data.tail.left);\n } else {\n tailMargin = parseInt(tail.css('margin-top'), 10);\n tail.css('margin-top', tailMargin + data.tail.top);\n }\n }\n },\n\n /**\n * Resolves position for tooltip\n *\n * @param {Object} event\n * @returns {Object}\n */\n getEventPosition: function (event) {\n var position = {\n left: event.originalEvent && event.originalEvent.pageX || 0,\n top: event.originalEvent && event.originalEvent.pageY || 0\n };\n\n if (position.left === 0 && position.top === 0) {\n _.extend(position, event.target.getBoundingClientRect());\n }\n\n return position;\n },\n\n /**\n * Close tooltip if action happened outside handler and tooltip element\n *\n * @param {String} id - tooltip id\n * @param {Object} event - action event\n */\n outerClick: function (id, event) {\n var tooltipElement = $(event.target).parents(defaults.tooltipWrapper)[0],\n isTrigger = event.target === tooltipData.trigger[0] || $.contains(tooltipData.trigger[0], event.target);\n\n if (tooltipData.showed && tooltipElement !== tooltipData.element[0] && !isTrigger) {\n tooltip.destroy(id);\n }\n },\n\n /**\n * Parse keydown event and if event trigger is escape key - close tooltip\n *\n * @param {Object} event - action event\n */\n keydownHandler: function (event) {\n if (tooltipData.showed && event.keyCode === 27) {\n tooltip.destroy(tooltipData.currentID);\n }\n },\n\n /**\n * Change tooltip position when track is enabled\n *\n * @param {Object} event - current event\n */\n track: function (event) {\n var inequality = {},\n map = positions.map,\n translate = {\n left: 'translateX',\n top: 'translateY'\n },\n eventPosition = {\n left: event.pageX,\n top: event.pageY\n },\n tooltipSize = {\n w: tooltipData.element.outerWidth(),\n h: tooltipData.element.outerHeight()\n },\n direction = positionData.side === 'bottom' || positionData.side === 'top' ? 'horizontal' : 'vertical';\n\n inequality[map[direction].p] = eventPosition[map[direction].p] - (positionData.position[map[direction].p] +\n tooltipSize[map[direction].s] / 2);\n\n if (positionData.position[map[direction].p] + inequality[map[direction].p] +\n tooltip.sizeData.tooltipSize[map[direction].s] >\n tooltip.sizeData.windowSize[map[direction].s] + tooltip.sizeData.scrollPosition[map[direction].p] ||\n inequality[map[direction].p] + positionData.position[map[direction].p] <\n tooltip.sizeData.scrollPosition[map[direction].p]) {\n\n return false;\n }\n\n tooltipData.element[0].style[transformProp] = translate[map[direction].p] +\n '(' + inequality[map[direction].p] + 'px)';\n },\n\n /**\n * Set handlers to tooltip\n *\n * @param {String} id - tooltip id\n */\n setHandlers: function (id) {\n var config = tooltip.getTooltip(id);\n\n if (config.track) {\n tooltipData.trigger.on('mousemove.track', tooltip.track);\n }\n\n if (config.action === 'click') {\n $(window).on(CLICK_EVENT + '.outerClick', tooltip.outerClick.bind(null, id));\n }\n\n if (config.closeButton) {\n $('.' + config.closeButtonClass).on('click.closeButton', tooltip.destroy.bind(null, id));\n }\n\n if (config.closeOnScroll) {\n document.addEventListener('scroll', tooltip.destroy, true);\n $(window).on('scroll.tooltip', tooltip.outerClick.bind(null, id));\n }\n\n $(window).on('keydown.tooltip', tooltip.keydownHandler);\n $(window).on('resize.outerClick', tooltip.outerClick.bind(null, id));\n },\n\n /**\n * Toggle tooltip\n *\n * @param {Object} tooltipElement - tooltip element\n * @param {Object} viewModel - tooltip view model\n * @param {String} id - tooltip id\n */\n toggleTooltip: function (tooltipElement, viewModel, id) {\n if (previousTooltip === id && tooltipData.showed) {\n tooltip.destroy(id);\n\n return false;\n }\n\n tooltip.setContent.apply(null, arguments);\n\n return false;\n },\n\n /**\n * Create tooltip and append to DOM\n *\n * @param {String} id - tooltip id\n * @returns {Object} tooltip element\n */\n createTooltip: function (id) {\n var body = $('body'),\n config = tooltip.getTooltip(id);\n\n $(template(tooltipTmpl, {\n data: config\n })).appendTo(body);\n\n tooltipData.showed = true;\n tooltipData.element = $(config.tooltipWrapper);\n\n return tooltipData.element;\n },\n\n /**\n * Check action and clean timeout\n *\n * @param {String} id - tooltip id\n */\n clearTimeout: function (id) {\n var config = tooltip.getTooltip(id);\n\n if (config.action === 'hover') {\n clearTimeout(tooltipData.timeout);\n }\n },\n\n /**\n * Check previous tooltip\n */\n checkPreviousTooltip: function () {\n if (!tooltipData.timeout) {\n tooltip.destroy();\n }\n },\n\n /**\n * Destroy tooltip instance\n */\n destroy: function () {\n if (tooltipData.element) {\n tooltipData.element.remove();\n tooltipData.showed = false;\n }\n\n positionData = {};\n tooltipData.timeout = false;\n tooltip.removeHandlers();\n },\n\n /**\n * Remove tooltip handlers\n */\n removeHandlers: function () {\n $('.' + defaults.closeButtonClass).off('click.closeButton');\n tooltipData.trigger.off('mousemove.track');\n document.removeEventListener('scroll', tooltip.destroy, true);\n $(window).off('scroll.tooltip');\n $(window).off(CLICK_EVENT + '.outerClick');\n $(window).off('keydown.tooltip');\n $(window).off('resize.outerClick');\n },\n\n /**\n * Set target element\n *\n * @param {Object} event - current event\n */\n setTargetData: function (event) {\n tooltipData.event = event;\n\n //TODO: bug chrome v.49; Link to issue https://bugs.chromium.org/p/chromium/issues/detail?id=161464\n if (event.timeStamp - (tooltipData.timestamp || 0) < 1) {\n return;\n }\n\n if (event.type === 'mousemove') {\n tooltipData.targetElement = event.target;\n } else {\n tooltipData.targetElement = event.currentTarget;\n tooltipData.timestamp = event.timeStamp;\n }\n },\n\n /**\n * Merged user config with defaults configuration\n *\n * @param {Object} config - user config\n * @returns {Object} merged config\n */\n processingConfig: function (config) {\n return _.extend({}, defaults, config);\n }\n };\n\n ko.bindingHandlers.tooltip = {\n\n /**\n * Initialize tooltip\n *\n * @param {Object} elem - tooltip DOM element\n * @param {Function} valueAccessor - ko observable property, tooltip data\n * @param {Object} allBindings - all bindings on current element\n * @param {Object} viewModel - current element viewModel\n * @param {Object} bindingCtx - current element binding context\n */\n init: function (elem, valueAccessor, allBindings, viewModel, bindingCtx) {\n var config = tooltip.processingConfig(valueAccessor()),\n $parentScope = config.parentScope ? $(config.parentScope) : $(elem).parent(),\n tooltipId;\n\n $(elem).addClass('hidden');\n\n if (isTouchDevice) {\n config.action = 'click';\n }\n tooltipId = tooltip.setTooltip(config);\n\n if (config.action === 'hover') {\n $parentScope.on(\n 'mouseenter',\n config.trigger,\n tooltip.setContent.bind(null, elem, viewModel, tooltipId, bindingCtx)\n );\n $parentScope.on(\n 'mouseleave',\n config.trigger,\n tooltip.checkPreviousTooltip.bind(null, tooltipId)\n );\n } else if (config.action === 'click') {\n $parentScope.on(\n 'click',\n config.trigger,\n tooltip.toggleTooltip.bind(null, elem, viewModel, tooltipId, bindingCtx)\n );\n }\n\n return {\n controlsDescendantBindings: true\n };\n }\n };\n\n renderer.addAttribute('tooltip');\n});\n","Magento_Ui/js/lib/knockout/bindings/staticChecked.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'ko',\n '../template/renderer'\n], function (ko, renderer) {\n 'use strict';\n\n ko.bindingHandlers.staticChecked = {\n 'after': ['value', 'attr'],\n\n /**\n * Implements same functionality as a standard 'checked' binding,\n * but with a difference that it wont' change values array if\n * value of DOM element changes.\n */\n init: function (element, valueAccessor, allBindings) {\n var isCheckbox = element.type === 'checkbox',\n isRadio = element.type === 'radio',\n isValueArray,\n oldElemValue,\n useCheckedValue,\n checkedValue,\n updateModel,\n updateView;\n\n if (!isCheckbox && !isRadio) {\n return;\n }\n\n checkedValue = ko.pureComputed(function () {\n if (allBindings.has('checkedValue')) {\n return ko.utils.unwrapObservable(allBindings.get('checkedValue'));\n } else if (allBindings.has('value')) {\n return ko.utils.unwrapObservable(allBindings.get('value'));\n }\n\n return element.value;\n });\n\n isValueArray = isCheckbox && ko.utils.unwrapObservable(valueAccessor()) instanceof Array;\n oldElemValue = isValueArray ? checkedValue() : undefined;\n useCheckedValue = isRadio || isValueArray;\n\n /**\n * Updates values array if it's necessary.\n */\n updateModel = function () {\n var isChecked = element.checked,\n elemValue = useCheckedValue ? checkedValue() : isChecked,\n modelValue;\n\n if (ko.computedContext.isInitial()) {\n return;\n }\n\n if (isRadio && !isChecked) {\n return;\n }\n\n modelValue = ko.dependencyDetection.ignore(valueAccessor);\n\n if (isValueArray) {\n if (oldElemValue !== elemValue) {\n oldElemValue = elemValue;\n } else {\n ko.utils.addOrRemoveItem(modelValue, elemValue, isChecked);\n }\n } else {\n ko.expressionRewriting.writeValueToProperty(modelValue, allBindings, 'checked', elemValue, true);\n }\n };\n\n /**\n * Updates checkbox state.\n */\n updateView = function () {\n var modelValue = ko.utils.unwrapObservable(valueAccessor());\n\n if (isValueArray) {\n element.checked = ko.utils.arrayIndexOf(modelValue, checkedValue()) >= 0;\n } else if (isCheckbox) {\n element.checked = modelValue;\n } else {\n element.checked = checkedValue() === modelValue;\n }\n };\n\n ko.computed(updateModel, null, {\n disposeWhenNodeIsRemoved: element\n });\n\n ko.utils.registerEventHandler(element, 'click', updateModel);\n\n ko.computed(updateView, null, {\n disposeWhenNodeIsRemoved: element\n });\n }\n };\n\n ko.expressionRewriting._twoWayBindings.staticChecked = true;\n\n renderer.addAttribute('staticChecked');\n});\n","Magento_Ui/js/lib/knockout/bindings/bootstrap.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine(function (require) {\n 'use strict';\n\n var renderer = require('../template/renderer');\n\n renderer.addAttribute('repeat', renderer.handlers.wrapAttribute);\n\n renderer.addAttribute('outerfasteach', {\n binding: 'fastForEach',\n handler: renderer.handlers.wrapAttribute\n });\n\n renderer\n .addNode('repeat')\n .addNode('fastForEach');\n\n return {\n resizable: require('./resizable'),\n i18n: require('./i18n'),\n scope: require('./scope'),\n range: require('./range'),\n mageInit: require('./mage-init'),\n keyboard: require('./keyboard'),\n optgroup: require('./optgroup'),\n afterRender: require('./after-render'),\n autoselect: require('./autoselect'),\n datepicker: require('./datepicker'),\n outerClick: require('./outer_click'),\n fadeVisible: require('./fadeVisible'),\n collapsible: require('./collapsible'),\n staticChecked: require('./staticChecked'),\n simpleChecked: require('./simple-checked'),\n bindHtml: require('./bind-html'),\n tooltip: require('./tooltip'),\n repeat: require('knockoutjs/knockout-repeat'),\n fastForEach: require('knockoutjs/knockout-fast-foreach'),\n colorPicker: require('./color-picker')\n };\n});\n","Magento_Ui/js/lib/knockout/bindings/simple-checked.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'ko',\n '../template/renderer'\n], function (ko, renderer) {\n 'use strict';\n\n ko.bindingHandlers.simpleChecked = {\n 'after': ['attr'],\n\n /**\n * Implements same functionality as a standard 'simpleChecked' binding,\n * but with a difference that it wont' change values array if\n * value of DOM element changes.\n */\n init: function (element, valueAccessor) {\n var isCheckbox = element.type === 'checkbox',\n isRadio = element.type === 'radio',\n updateView,\n updateModel;\n\n if (!isCheckbox && !isRadio) {\n return;\n }\n\n /**\n * Updates checked observable\n */\n updateModel = function () {\n var modelValue = ko.dependencyDetection.ignore(valueAccessor),\n isChecked = element.checked;\n\n if (ko.computedContext.isInitial()) {\n return;\n }\n\n if (modelValue.peek() === isChecked) {\n return;\n }\n\n if (isRadio && !isChecked) {\n return;\n }\n\n modelValue(isChecked);\n };\n\n /**\n * Updates checkbox state\n */\n updateView = function () {\n var modelValue = ko.utils.unwrapObservable(valueAccessor());\n\n element.checked = !!modelValue;\n };\n\n ko.utils.registerEventHandler(element, 'change', updateModel);\n\n ko.computed(updateModel, null, {\n disposeWhenNodeIsRemoved: element\n });\n ko.computed(updateView, null, {\n disposeWhenNodeIsRemoved: element\n });\n }\n };\n\n ko.expressionRewriting._twoWayBindings.simpleChecked = true;\n\n renderer.addAttribute('simpleChecked');\n renderer.addAttribute('simple-checked', {\n binding: 'simpleChecked'\n });\n});\n","Magento_Ui/js/lib/knockout/bindings/range.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'ko',\n 'jquery',\n 'underscore',\n '../template/renderer'\n], function (ko, $, _, renderer) {\n 'use strict';\n\n var isTouchDevice = !_.isUndefined(document.ontouchstart),\n sliderFn = 'slider',\n sliderModule = 'jquery-ui-modules/slider';\n\n if (isTouchDevice) {\n sliderFn = 'touchSlider';\n sliderModule = 'mage/touch-slider';\n }\n\n ko.bindingHandlers.range = {\n\n /**\n * Initializes binding and a slider update.\n *\n * @param {HTMLElement} element\n * @param {Function} valueAccessor\n */\n init: function (element, valueAccessor) {\n var config = valueAccessor(),\n value = config.value;\n\n _.extend(config, {\n value: value(),\n\n /**\n * Callback which is being called when sliders' value changes.\n *\n * @param {Event} event\n * @param {Object} ui\n */\n slide: function (event, ui) {\n value(ui.value);\n }\n });\n\n require([sliderModule], function () {\n $(element)[sliderFn](config);\n });\n },\n\n /**\n * Updates sliders' plugin configuration.\n *\n * @param {HTMLElement} element\n * @param {Function} valueAccessor\n */\n update: function (element, valueAccessor) {\n var config = valueAccessor();\n\n config.value = ko.unwrap(config.value);\n\n require([sliderModule], function () {\n $(element)[sliderFn]('option', config);\n });\n }\n };\n\n renderer.addAttribute('range');\n});\n","Magento_Ui/js/lib/knockout/bindings/datepicker.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/** Creates datepicker binding and registers in to ko.bindingHandlers object */\ndefine([\n 'ko',\n 'underscore',\n 'jquery',\n 'mage/translate'\n], function (ko, _, $, $t) {\n 'use strict';\n\n var defaults = {\n dateFormat: 'mm\\/dd\\/yyyy',\n showsTime: false,\n timeFormat: null,\n buttonImage: null,\n buttonImageOnly: null,\n buttonText: $t('Select Date')\n };\n\n ko.bindingHandlers.datepicker = {\n /**\n * Initializes calendar widget on element and stores it's value to observable property.\n * Datepicker binding takes either observable property or object\n * { storage: {ko.observable}, options: {Object} }.\n * For more info about options take a look at \"mage/calendar\" and jquery.ui.datepicker widget.\n * @param {HTMLElement} el - Element, that binding is applied to\n * @param {Function} valueAccessor - Function that returns value, passed to binding\n * @param {object} allBindings\n * @param {object} viewModel\n * @param {object} bindingContext\n */\n init: function (el, valueAccessor, allBindings, viewModel, bindingContext) {\n var config = valueAccessor(),\n observable,\n options = {};\n\n _.extend(options, defaults);\n\n if (typeof config === 'object') {\n observable = config.storage;\n _.extend(options, config.options);\n } else {\n observable = config;\n }\n\n require(['mage/calendar'], function () {\n $(el).calendar(options);\n\n ko.utils.registerEventHandler(el, 'change', function () {\n observable(this.value);\n });\n });\n\n if (bindingContext.$data) {\n bindingContext.$data.value.subscribe(function (newVal) {\n if (!newVal) {\n $(el).val('');\n }\n }, this);\n }\n\n\n },\n\n /**\n * Update calendar widget on element and stores it's value to observable property.\n * Datepicker binding takes either observable property or object\n * { storage: {ko.observable}, options: {Object} }.\n * @param {HTMLElement} element - Element, that binding is applied to\n * @param {Function} valueAccessor - Function that returns value, passed to binding\n */\n update: function (element, valueAccessor) {\n var config = valueAccessor(),\n $element = $(element),\n observable,\n options = {},\n newVal;\n\n _.extend(options, defaults);\n\n if (typeof config === 'object') {\n observable = config.storage;\n _.extend(options, config.options);\n } else {\n observable = config;\n }\n\n require(['moment', 'mage/utils/misc', 'mage/calendar'], function (moment, utils) {\n if (_.isEmpty(observable())) {\n newVal = null;\n } else {\n newVal = moment(\n observable(),\n utils.convertToMomentFormat(\n options.dateFormat + (options.showsTime ? ' ' + options.timeFormat : '')\n )\n ).toDate();\n }\n\n if (!options.timeOnly) {\n $element.datepicker('setDate', newVal);\n $element.trigger('blur');\n }\n });\n }\n };\n});\n","Magento_Ui/js/lib/knockout/bindings/optgroup.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'ko',\n 'mageUtils'\n ], function (ko, utils) {\n 'use strict';\n\n var captionPlaceholder = {},\n optgroupTmpl = '<optgroup label=\"${ $.label }\"></optgroup>',\n nbspRe = / /g,\n optionsText,\n optionsValue,\n optionTitle;\n\n ko.bindingHandlers.optgroup = {\n /**\n * @param {*} element\n */\n init: function (element) {\n if (ko.utils.tagNameLower(element) !== 'select') {\n throw new Error('options binding applies only to SELECT elements');\n }\n\n // Remove all existing <option>s.\n while (element.length > 0) {\n element.remove(0);\n }\n },\n\n /**\n * @param {*} element\n * @param {*} valueAccessor\n * @param {*} allBindings\n */\n update: function (element, valueAccessor, allBindings) {\n var selectWasPreviouslyEmpty = element.length === 0,\n previousScrollTop = !selectWasPreviouslyEmpty && element.multiple ? element.scrollTop : null,\n includeDestroyed = allBindings.get('optionsIncludeDestroyed'),\n arrayToDomNodeChildrenOptions = {},\n captionValue,\n unwrappedArray = ko.utils.unwrapObservable(valueAccessor()),\n filteredArray,\n previousSelectedValues,\n itemUpdate = false,\n callback = setSelectionCallback,//eslint-disable-line no-use-before-define\n nestedOptionsLevel = -1;\n\n optionsText = ko.utils.unwrapObservable(allBindings.get('optionsText')) || 'text';\n optionsValue = ko.utils.unwrapObservable(allBindings.get('optionsValue')) || 'value';\n optionTitle = optionsText + 'title';\n\n if (element.multiple) {\n previousSelectedValues = ko.utils.arrayMap(\n selectedOptions(),//eslint-disable-line no-use-before-define\n ko.selectExtensions.readValue\n );\n } else {\n previousSelectedValues = element.selectedIndex >= 0 ?\n [ko.selectExtensions.readValue(element.options[element.selectedIndex])] :\n [];\n }\n\n if (unwrappedArray) {\n if (typeof unwrappedArray.length === 'undefined') { // Coerce single value into array\n unwrappedArray = [unwrappedArray];\n }\n\n // Filter out any entries marked as destroyed\n filteredArray = ko.utils.arrayFilter(unwrappedArray, function (item) {\n if (item && !item.label) {\n return false;\n }\n\n return includeDestroyed ||\n item === undefined ||\n item === null ||\n !ko.utils.unwrapObservable(item._destroy);\n });\n filteredArray.map(recursivePathBuilder, null);//eslint-disable-line no-use-before-define\n }\n\n /**\n * @param {*} option\n */\n arrayToDomNodeChildrenOptions.beforeRemove = function (option) {\n element.removeChild(option);\n };\n\n if (allBindings.has('optionsAfterRender')) {\n\n /**\n * @param {*} arrayEntry\n * @param {*} newOptions\n */\n callback = function (arrayEntry, newOptions) {\n setSelectionCallback(arrayEntry, newOptions);//eslint-disable-line no-use-before-define\n ko.dependencyDetection.ignore(\n allBindings.get('optionsAfterRender'),\n null,\n [newOptions[0],\n arrayEntry !== captionPlaceholder ? arrayEntry : undefined]\n );\n };\n }\n\n filteredArray = formatOptions(filteredArray);//eslint-disable-line no-use-before-define\n ko.utils.setDomNodeChildrenFromArrayMapping(\n element,\n filteredArray,\n optionNodeFromArray,//eslint-disable-line no-use-before-define\n arrayToDomNodeChildrenOptions,\n callback\n );\n\n ko.dependencyDetection.ignore(function () {\n var selectionChanged;\n\n if (allBindings.get('valueAllowUnset') && allBindings.has('value')) {\n // The model value is authoritative, so make sure its value is the one selected\n ko.selectExtensions.writeValue(\n element,\n ko.utils.unwrapObservable(allBindings.get('value')),\n true /* allowUnset */\n );\n } else {\n // Determine if the selection has changed as a result of updating the options list\n if (element.multiple) {\n // For a multiple-select box, compare the new selection count to the previous one\n // But if nothing was selected before, the selection can't have changed\n selectionChanged = previousSelectedValues.length &&\n selectedOptions().length < //eslint-disable-line no-use-before-define\n previousSelectedValues.length;\n } else {\n // For a single-select box, compare the current value to the previous value\n // But if nothing was selected before or nothing is selected now,\n // just look for a change in selection\n selectionChanged = previousSelectedValues.length && element.selectedIndex >= 0 ?\n ko.selectExtensions.readValue(element.options[element.selectedIndex]) !==\n previousSelectedValues[0] : previousSelectedValues.length || element.selectedIndex >= 0;\n }\n\n // Ensure consistency between model value and selected option.\n // If the dropdown was changed so that selection is no longer the same,\n // notify the value or selectedOptions binding.\n if (selectionChanged) {\n ko.utils.triggerEvent(element, 'change');\n }\n }\n });\n\n /*eslint-enable max-len, no-use-before-define*/\n\n if (previousScrollTop && Math.abs(previousScrollTop - element.scrollTop) > 20) {\n element.scrollTop = previousScrollTop;\n }\n\n /**\n * @returns {*}\n */\n function selectedOptions() {\n return ko.utils.arrayFilter(element.options, function (node) {\n return node.selected;\n });\n }\n\n /**\n * @param {*} object\n * @param {*} predicate\n * @param {*} defaultValue\n * @returns {*}\n */\n function applyToObject(object, predicate, defaultValue) {\n var predicateType = typeof predicate;\n\n if (predicateType === 'function') { // run it against the data value\n return predicate(object);\n } else if (predicateType === 'string') { // treat it as a property name on the data value\n return object[predicate];\n }\n\n return defaultValue;\n }\n\n /**\n * @param {*} obj\n */\n function recursivePathBuilder(obj) {\n\n obj[optionTitle] = (this && this[optionTitle] ? this[optionTitle] + '/' : '') + obj[optionsText].trim();\n\n if (Array.isArray(obj[optionsValue])) {\n obj[optionsValue].map(recursivePathBuilder, obj);\n }\n }\n\n /**\n * @param {Array} arrayEntry\n * @param {*} oldOptions\n * @returns {*[]}\n */\n function optionNodeFromArray(arrayEntry, oldOptions) {\n var option;\n\n if (oldOptions.length) {\n previousSelectedValues = oldOptions[0].selected ?\n [ko.selectExtensions.readValue(oldOptions[0])] : [];\n itemUpdate = true;\n }\n\n if (arrayEntry === captionPlaceholder) { // empty value, label === caption\n option = element.ownerDocument.createElement('option');\n ko.utils.setTextContent(option, allBindings.get('optionsCaption'));\n ko.selectExtensions.writeValue(option, undefined);\n } else if (typeof arrayEntry[optionsValue] === 'undefined') { // empty value === optgroup\n if (arrayEntry.__disableTmpl) {\n option = '<optgroup label=\"' + arrayEntry[optionsText] + '\"></optgroup>';\n } else {\n option = utils.template(optgroupTmpl, {\n label: arrayEntry[optionsText],\n title: arrayEntry[optionsText + 'title']\n });\n }\n option = ko.utils.parseHtmlFragment(option)[0];\n\n } else {\n option = element.ownerDocument.createElement('option');\n option.setAttribute('data-title', arrayEntry[optionsText + 'title']);\n ko.selectExtensions.writeValue(option, arrayEntry[optionsValue]);\n ko.utils.setTextContent(option, arrayEntry[optionsText]);\n }\n\n return [option];\n }\n\n /**\n * @param {*} newOptions\n */\n function setSelectionCallback(newOptions) {\n var isSelected;\n\n // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.\n // That's why we first added them without selection. Now it's time to set the selection.\n if (previousSelectedValues.length && newOptions.value) {\n isSelected = ko.utils.arrayIndexOf(\n previousSelectedValues,\n ko.selectExtensions.readValue(newOptions.value)\n ) >= 0;\n\n ko.utils.setOptionNodeSelectionState(newOptions.value, isSelected);\n\n // If this option was changed from being selected during a single-item update, notify the change\n if (itemUpdate && !isSelected) {\n ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, 'change']);\n }\n }\n }\n\n /**\n * @param {*} string\n * @param {Number} times\n * @returns {Array}\n */\n function strPad(string, times) {\n return new Array(times + 1).join(string);\n }\n\n /**\n * @param {*} options\n * @returns {Array}\n */\n function formatOptions(options) {\n var res = [];\n\n nestedOptionsLevel++;\n\n if (!nestedOptionsLevel) { // zero level\n // If caption is included, add it to the array\n if (allBindings.has('optionsCaption')) {\n captionValue = ko.utils.unwrapObservable(allBindings.get('optionsCaption'));\n // If caption value is null or undefined, don't show a caption\n if (//eslint-disable-line max-depth\n captionValue !== null &&\n captionValue !== undefined &&\n captionValue !== false\n ) {\n res.push(captionPlaceholder);\n }\n }\n }\n\n ko.utils.arrayForEach(options, function (option) {\n var value = applyToObject(option, optionsValue, option),\n label = applyToObject(option, optionsText, value) || '',\n disabled = applyToObject(option, 'disabled', false) || false,\n obj = {},\n space = '\\u2007\\u2007\\u2007';\n\n obj[optionTitle] = applyToObject(option, optionsText + 'title', value);\n\n if (disabled) {\n obj.disabled = disabled;\n }\n\n if (option.hasOwnProperty('__disableTmpl')) {\n obj.__disableTmpl = option.__disableTmpl;\n }\n\n label = label.replace(nbspRe, '').trim();\n\n if (Array.isArray(value)) {\n obj[optionsText] = strPad(' ', nestedOptionsLevel * 4) + label;\n res.push(obj);\n res = res.concat(formatOptions(value));\n } else {\n obj[optionsText] = strPad(space, nestedOptionsLevel * 2) + label;\n obj[optionsValue] = value;\n res.push(obj);\n }\n });\n nestedOptionsLevel--;\n\n return res;\n }\n }\n };\n});\n","Magento_Ui/js/lib/knockout/bindings/fadeVisible.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'ko'\n], function ($, ko) {\n 'use strict';\n\n ko.bindingHandlers.fadeVisible = {\n /**\n * Initially set the element to be instantly visible/hidden depending on the value.\n *\n * @param {HTMLElement} element\n * @param {Function} valueAccessor\n */\n init: function (element, valueAccessor) {\n var value = valueAccessor();\n\n // Use \"unwrapObservable\" so we can handle values that may or may not be observable\n $(element).toggle(ko.unwrap(value));\n },\n\n /**\n * Whenever the value subsequently changes, slowly fade the element in or out.\n *\n * @param {HTMLElement} element\n * @param {Function} valueAccessor\n */\n update: function (element, valueAccessor) {\n var value = valueAccessor();\n\n ko.unwrap(value) ? $(element).fadeIn() : $(element).fadeOut();\n }\n };\n});\n","Magento_Ui/js/lib/knockout/bindings/after-render.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'ko',\n '../template/renderer'\n], function (ko, renderer) {\n 'use strict';\n\n ko.bindingHandlers.afterRender = {\n\n /**\n * Binding init callback.\n */\n init: function (element, valueAccessor, allBindings, viewModel) {\n var callback = valueAccessor();\n\n if (typeof callback === 'function') {\n callback.call(viewModel, element, viewModel);\n }\n }\n };\n\n renderer.addAttribute('afterRender');\n});\n","Magento_Ui/js/lib/knockout/bindings/mage-init.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'ko',\n 'underscore',\n 'mage/apply/main'\n], function (ko, _, mage) {\n 'use strict';\n\n ko.bindingHandlers.mageInit = {\n /**\n * Initializes components assigned to HTML elements.\n *\n * @param {HTMLElement} el\n * @param {Function} valueAccessor\n */\n init: function (el, valueAccessor) {\n var data = valueAccessor();\n\n _.each(data, function (config, component) {\n mage.applyFor(el, config, component);\n });\n }\n };\n});\n","Magento_Ui/js/lib/knockout/bindings/bind-html.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'ko',\n 'underscore',\n 'mage/apply/main',\n '../template/renderer'\n], function (ko, _, mage, renderer) {\n 'use strict';\n\n /**\n * Set html to node element.\n *\n * @param {HTMLElement} el - Element to apply bindings to.\n * @param {Function} html - Observable html content.\n */\n function setHtml(el, html) {\n ko.utils.emptyDomNode(el);\n html = ko.utils.unwrapObservable(html);\n\n if (!_.isNull(html) && !_.isUndefined(html)) {\n if (!_.isString(html)) {\n html = html.toString();\n }\n\n el.innerHTML = html;\n }\n }\n\n /**\n * Apply bindings and call magento attributes parser.\n *\n * @param {HTMLElement} el - Element to apply bindings to.\n * @param {ko.bindingContext} ctx - Instance of ko.bindingContext, passed to binding initially.\n */\n function applyComponents(el, ctx) {\n ko.utils.arrayForEach(el.childNodes, ko.cleanNode);\n ko.applyBindingsToDescendants(ctx, el);\n mage.apply();\n }\n\n ko.bindingHandlers.bindHtml = {\n /**\n * Scope binding's init method.\n *\n * @returns {Object} - Knockout declaration for it to let binding control descendants.\n */\n init: function () {\n return {\n controlsDescendantBindings: true\n };\n },\n\n /**\n * Reads params passed to binding.\n * Set html to node element, apply bindings and call magento attributes parser.\n *\n * @param {HTMLElement} el - Element to apply bindings to.\n * @param {Function} valueAccessor - Function that returns value, passed to binding.\n * @param {Object} allBindings - Object, which represents all bindings applied to element.\n * @param {Object} viewModel - Object, which represents view model binded to el.\n * @param {ko.bindingContext} bindingContext - Instance of ko.bindingContext, passed to binding initially.\n */\n update: function (el, valueAccessor, allBindings, viewModel, bindingContext) {\n setHtml(el, valueAccessor());\n applyComponents(el, bindingContext);\n }\n };\n\n renderer.addAttribute('bindHtml');\n});\n","Magento_Ui/js/lib/knockout/bindings/resizable.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'ko',\n 'jquery',\n 'Magento_Ui/js/lib/view/utils/async',\n 'uiRegistry',\n 'underscore',\n '../template/renderer'\n], function (ko, $, async, registry, _, renderer) {\n 'use strict';\n\n var sizeOptions = [\n 'minHeight',\n 'maxHeight',\n 'minWidth',\n 'maxWidth'\n ],\n\n handles = {\n height: '.ui-resizable-s, .ui-resizable-n',\n width: '.ui-resizable-w, .ui-resizable-e'\n };\n\n /**\n * Recalcs visibility of handles, width and height of resizable based on content\n * @param {HTMLElement} element\n */\n function adjustSize(element) {\n var maxHeight,\n maxWidth;\n\n element = $(element);\n maxHeight = element.resizable('option').maxHeight;\n maxWidth = element.resizable('option').maxWidth;\n\n if (maxHeight && element.height() > maxHeight) {\n element.height(maxHeight + 1);\n $(handles.height).hide();\n } else {\n $(handles.height).show();\n }\n\n if (maxWidth && element.width() > maxWidth) {\n element.width(maxWidth + 1);\n $(handles.width).hide();\n } else {\n $(handles.width).show();\n }\n }\n\n /**\n * Recalcs allowed min, max width and height based on configured selectors\n * @param {Object} sizeConstraints\n * @param {String} componentName\n * @param {HTMLElement} element\n * @param {Boolean} hasWidthUpdate\n */\n function recalcAllowedSize(sizeConstraints, componentName, element, hasWidthUpdate) {\n var size;\n\n element = $(element);\n\n if (!element.data('resizable')) {\n return;\n }\n\n if (!hasWidthUpdate) {\n element.css('width', 'auto');\n }\n\n _.each(sizeConstraints, function (selector, key) {\n async.async({\n component: componentName,\n selector: selector\n }, function (elem) {\n size = key.indexOf('Height') !== -1 ? $(elem).outerHeight(true) : $(elem).outerWidth(true);\n\n if (element.data('resizable')) {\n element.resizable('option', key, size + 1);\n }\n });\n }, this);\n\n adjustSize(element);\n }\n\n /**\n * Preprocess config to separate options,\n * which must be processed further before applying\n *\n * @param {Object} config\n * @param {Object} viewModel\n * @param {*} element\n * @return {Object} config\n */\n function processConfig(config, viewModel, element) {\n var sizeConstraint,\n sizeConstraints = {},\n recalc,\n hasWidthUpdate;\n\n if (_.isEmpty(config)) {\n return {};\n }\n _.each(sizeOptions, function (key) {\n sizeConstraint = config[key];\n\n if (sizeConstraint && !_.isNumber(sizeConstraint)) {\n sizeConstraints[key] = sizeConstraint;\n delete config[key];\n }\n });\n hasWidthUpdate = _.some(sizeConstraints, function (value, key) {\n return key.indexOf('Width') !== -1;\n });\n\n recalc = recalcAllowedSize.bind(null, sizeConstraints, viewModel.name, element, hasWidthUpdate);\n config.start = recalc;\n $(window).on('resize.resizable', recalc);\n registry.get(viewModel.provider).on('reloaded', recalc);\n\n return config;\n }\n\n ko.bindingHandlers.resizable = {\n\n /**\n * Binding init callback.\n *\n * @param {*} element\n * @param {Function} valueAccessor\n * @param {Function} allBindings\n * @param {Object} viewModel\n */\n init: function (element, valueAccessor, allBindings, viewModel) {\n var config = processConfig(valueAccessor(), viewModel, element);\n\n require(['jquery-ui-modules/resizable'], function () {\n if ($.fn.resizable) {\n $(element).resizable(config);\n }\n });\n }\n };\n\n renderer.addAttribute('resizable');\n});\n","Magento_Ui/js/lib/knockout/bindings/outer_click.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/** Creates outerClick binding and registers in to ko.bindingHandlers object */\ndefine([\n 'ko',\n 'jquery',\n 'underscore',\n '../template/renderer'\n], function (ko, $, _, renderer) {\n 'use strict';\n\n var defaults = {\n onlyIfVisible: true\n };\n\n /**\n * Checks if element sis visible.\n *\n * @param {Element} el\n * @returns {Boolean}\n */\n function isVisible(el) {\n var style = window.getComputedStyle(el),\n visibility = {\n display: 'none',\n visibility: 'hidden',\n opacity: '0'\n },\n visible = true;\n\n _.each(visibility, function (val, key) {\n if (style[key] === val) {\n visible = false;\n }\n });\n\n return visible;\n }\n\n /**\n * Document click handler which in case if event target is not\n * a descendant of provided container element,\n * invokes specified in configuration callback.\n *\n * @param {HTMLElement} container\n * @param {Object} config\n * @param {EventObject} e\n */\n function onOuterClick(container, config, e) {\n var target = e.target,\n callback = config.callback;\n\n if (container === target || container.contains(target)) {\n return;\n }\n\n if (config.onlyIfVisible) {\n if (!_.isNull(container.offsetParent) && isVisible(container)) {\n callback();\n }\n } else {\n callback();\n }\n }\n\n /**\n * Prepares configuration for the binding based\n * on a default properties and provided options.\n *\n * @param {(Object|Function)} [options={}]\n * @returns {Object}\n */\n function buildConfig(options) {\n var config = {};\n\n if (_.isFunction(options)) {\n options = {\n callback: options\n };\n } else if (!_.isObject(options)) {\n options = {};\n }\n\n return _.extend(config, defaults, options);\n }\n\n ko.bindingHandlers.outerClick = {\n\n /**\n * Initializes outer click binding.\n */\n init: function (element, valueAccessor) {\n var config = buildConfig(valueAccessor()),\n outerClick = onOuterClick.bind(null, element, config),\n isTouchDevice = typeof document.ontouchstart !== 'undefined';\n\n if (isTouchDevice) {\n $(document).on('touchstart', outerClick);\n\n ko.utils.domNodeDisposal.addDisposeCallback(element, function () {\n $(document).off('touchstart', outerClick);\n });\n } else {\n $(document).on('click', outerClick);\n\n ko.utils.domNodeDisposal.addDisposeCallback(element, function () {\n $(document).off('click', outerClick);\n });\n }\n }\n };\n\n renderer.addAttribute('outerClick');\n});\n","Magento_Ui/js/lib/knockout/bindings/autoselect.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'ko',\n 'jquery',\n '../template/renderer'\n], function (ko, $, renderer) {\n 'use strict';\n\n /**\n * 'Focus' event handler.\n *\n * @param {EventObject} e\n */\n function onFocus(e) {\n e.target.select();\n }\n\n ko.bindingHandlers.autoselect = {\n\n /**\n * Adds event handler which automatically\n * selects inputs' element text when field gets focused.\n */\n init: function (element, valueAccessor) {\n var enabled = ko.unwrap(valueAccessor());\n\n if (enabled !== false) {\n $(element).on('focus', onFocus);\n }\n }\n };\n\n renderer.addAttribute('autoselect');\n});\n","Magento_Ui/js/lib/knockout/bindings/color-picker.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'ko',\n 'jquery',\n '../template/renderer',\n 'spectrum',\n 'tinycolor'\n], function (ko, $, renderer, spectrum, tinycolor) {\n 'use strict';\n\n /**\n * Change color picker status to be enabled or disabled\n *\n * @param {HTMLElement} element - Element to apply colorpicker enable/disable status to.\n * @param {Object} viewModel - Object, which represents view model binded to el.\n */\n function changeColorPickerStateBasedOnViewModel(element, viewModel) {\n $(element).spectrum(viewModel.disabled() ? 'disable' : 'enable');\n }\n\n ko.bindingHandlers.colorPicker = {\n /**\n * Binding init callback.\n *\n * @param {*} element\n * @param {Function} valueAccessor\n * @param {Function} allBindings\n * @param {Object} viewModel\n */\n init: function (element, valueAccessor, allBindings, viewModel) {\n var config = valueAccessor(),\n\n /** change value */\n changeValue = function (value) {\n if (value == null) {\n value = '';\n }\n config.value(value.toString());\n };\n\n config.change = changeValue;\n\n config.hide = changeValue;\n\n /** show value */\n config.show = function () {\n if (!viewModel.focused()) {\n viewModel.focused(true);\n }\n\n return true;\n };\n\n $(element).spectrum(config);\n\n changeColorPickerStateBasedOnViewModel(element, viewModel);\n },\n\n /**\n * Reads params passed to binding, parses component declarations.\n * Fetches for those found and attaches them to the new context.\n *\n * @param {HTMLElement} element - Element to apply bindings to.\n * @param {Function} valueAccessor - Function that returns value, passed to binding.\n * @param {Object} allBindings - Object, which represents all bindings applied to element.\n * @param {Object} viewModel - Object, which represents view model binded to element.\n */\n update: function (element, valueAccessor, allBindings, viewModel) {\n var config = valueAccessor();\n\n /** Initialise value as empty if it is undefined when color picker input is reset **/\n if (config.value() === undefined) {\n config.value('');\n }\n\n if (tinycolor(config.value()).isValid() || config.value() === '') {\n $(element).spectrum('set', config.value());\n\n if (config.value() !== '') {\n config.value($(element).spectrum('get').toString());\n }\n }\n\n changeColorPickerStateBasedOnViewModel(element, viewModel);\n }\n };\n\n renderer.addAttribute('colorPicker');\n});\n","Magento_Ui/js/lib/knockout/bindings/scope.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n/** Creates scope binding and registers in to ko.bindingHandlers object */\ndefine([\n 'ko',\n 'uiRegistry',\n 'mage/translate',\n '../template/renderer',\n 'jquery',\n '../../logger/console-logger'\n], function (ko, registry, $t, renderer, $, consoleLogger) {\n 'use strict';\n\n /**\n * Creates child context with passed component param as $data. Extends context with $t helper.\n * Applies bindings to descendant nodes.\n * @param {HTMLElement} el - element to apply bindings to.\n * @param {ko.bindingContext} bindingContext - instance of ko.bindingContext, passed to binding initially.\n * @param {Promise} promise - instance of jQuery promise\n * @param {Object} component - component instance to attach to new context\n */\n function applyComponents(el, bindingContext, promise, component) {\n promise.resolve();\n component = bindingContext.createChildContext(component);\n\n ko.utils.extend(component, {\n $t: $t\n });\n\n ko.utils.arrayForEach(ko.virtualElements.childNodes(el), ko.cleanNode);\n\n ko.applyBindingsToDescendants(component, el);\n }\n\n ko.bindingHandlers.scope = {\n\n /**\n * Scope binding's init method.\n * @returns {Object} - Knockout declaration for it to let binding control descendants.\n */\n init: function () {\n return {\n controlsDescendantBindings: true\n };\n },\n\n /**\n * Reads params passed to binding, parses component declarations.\n * Fetches for those found and attaches them to the new context.\n * @param {HTMLElement} el - Element to apply bindings to.\n * @param {Function} valueAccessor - Function that returns value, passed to binding.\n * @param {Object} allBindings - Object, which represents all bindings applied to element.\n * @param {Object} viewModel - Object, which represents view model binded to el.\n * @param {ko.bindingContext} bindingContext - Instance of ko.bindingContext, passed to binding initially.\n */\n update: function (el, valueAccessor, allBindings, viewModel, bindingContext) {\n var component = valueAccessor(),\n promise = $.Deferred(),\n apply = applyComponents.bind(this, el, bindingContext, promise),\n loggerUtils = consoleLogger.utils;\n\n if (typeof component === 'string') {\n loggerUtils.asyncLog(\n promise,\n {\n data: {\n component: component\n },\n messages: loggerUtils.createMessages(\n 'requestingComponent',\n 'requestingComponentIsLoaded',\n 'requestingComponentIsFailed'\n )\n }\n );\n\n registry.get(component, apply);\n } else if (typeof component === 'function') {\n component(apply);\n }\n }\n };\n\n ko.virtualElements.allowedBindings.scope = true;\n\n renderer\n .addNode('scope')\n .addAttribute('scope', {\n name: 'ko-scope'\n });\n});\n","Magento_Ui/js/lib/knockout/bindings/collapsible.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'ko',\n 'jquery',\n 'underscore',\n '../template/renderer'\n], function (ko, $, _, renderer) {\n 'use strict';\n\n var collapsible,\n defaults;\n\n defaults = {\n closeOnOuter: true,\n onTarget: false,\n openClass: '_active',\n as: '$collapsible'\n };\n\n collapsible = {\n\n /**\n * Sets 'opened' property to true.\n */\n open: function () {\n this.opened(true);\n },\n\n /**\n * Sets 'opened' property to false.\n */\n close: function () {\n this.opened(false);\n },\n\n /**\n * Toggles value of the 'opened' property.\n */\n toggle: function () {\n this.opened(!this.opened());\n }\n };\n\n /**\n * Document click handler which in case if event target is not\n * a descendant of provided container element, closes collapsible model.\n *\n * @param {HTMLElement} container\n * @param {Object} model\n * @param {EventObject} e\n */\n function onOuterClick(container, model, e) {\n var target = e.target;\n\n if (target !== container && !container.contains(target)) {\n model.close();\n }\n }\n\n /**\n * Creates 'css' binding which toggles\n * class specified in 'name' parameter.\n *\n * @param {Object} model\n * @param {String} name\n * @returns {Object}\n */\n function getClassBinding(model, name) {\n var binding = {};\n\n binding[name] = model.opened;\n\n return {\n css: binding\n };\n }\n\n /**\n * Prepares configuration for the binding based\n * on a default properties and provided options.\n *\n * @param {Object} [options={}]\n * @returns {Object} Complete instance configuration.\n */\n function buildConfig(options) {\n if (typeof options !== 'object') {\n options = {};\n }\n\n return _.extend({}, defaults, options);\n }\n\n ko.bindingHandlers.collapsible = {\n\n /**\n * Initializes 'collapsible' binding.\n */\n init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) {\n var $collapsible = Object.create(collapsible),\n config = buildConfig(valueAccessor()),\n outerClick,\n bindings;\n\n _.bindAll($collapsible, 'open', 'close', 'toggle');\n\n $collapsible.opened = ko.observable(!!config.opened);\n\n bindingCtx[config.as] = $collapsible;\n\n if (config.closeOnOuter) {\n outerClick = onOuterClick.bind(null, element, $collapsible);\n\n $(document).on('click', outerClick);\n\n ko.utils.domNodeDisposal.addDisposeCallback(element, function () {\n $(document).off('click', outerClick);\n });\n }\n\n if (config.openClass) {\n bindings = getClassBinding($collapsible, config.openClass);\n\n ko.applyBindingsToNode(element, bindings, bindingCtx);\n }\n\n if (config.onTarget) {\n $(element).on('click', $collapsible.toggle);\n }\n\n if (viewModel && _.isFunction(viewModel.on)) {\n viewModel.on({\n close: $collapsible.close,\n open: $collapsible.open,\n toggleOpened: $collapsible.toggle\n });\n }\n }\n };\n\n ko.bindingHandlers.closeCollapsible = {\n\n /**\n * Creates listener for the click event on provided DOM element,\n * which closes associated with it collapsible model.\n */\n init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) {\n var name = valueAccessor() || defaults.as,\n $collapsible = bindingCtx[name];\n\n if ($collapsible) {\n $(element).on('click', $collapsible.close);\n }\n }\n };\n\n ko.bindingHandlers.openCollapsible = {\n\n /**\n * Creates listener for the click event on provided DOM element,\n * which opens associated with it collapsible model.\n */\n init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) {\n var name = valueAccessor() || defaults.as,\n $collapsible = bindingCtx[name];\n\n if ($collapsible) {\n $(element).on('click', $collapsible.open);\n }\n }\n };\n\n ko.bindingHandlers.toggleCollapsible = {\n\n /**\n * Creates listener for the click event on provided DOM element,\n * which toggles associated with it collapsible model.\n */\n init: function (element, valueAccessor, allBindings, viewModel, bindingCtx) {\n var name = valueAccessor() || defaults.as,\n $collapsible = bindingCtx[name];\n\n if ($collapsible) {\n $(element).on('click', $collapsible.toggle);\n }\n }\n };\n\n renderer\n .addAttribute('collapsible')\n .addAttribute('openCollapsible')\n .addAttribute('closeCollapsible')\n .addAttribute('toggleCollapsible');\n});\n","Magento_Ui/js/lib/knockout/bindings/i18n.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'jquery',\n 'ko',\n 'module',\n '../template/renderer',\n 'mage/translate'\n], function ($, ko, module, renderer) {\n 'use strict';\n\n var locations = {\n 'legend': 'Caption for the fieldset element',\n 'label': 'Label for an input element.',\n 'button': 'Push button',\n 'a': 'Link label',\n 'b': 'Bold text',\n 'strong': 'Strong emphasized text',\n 'i': 'Italic text',\n 'em': 'Emphasized text',\n 'u': 'Underlined text',\n 'sup': 'Superscript text',\n 'sub': 'Subscript text',\n 'span': 'Span element',\n 'small': 'Smaller text',\n 'big': 'Bigger text',\n 'address': 'Contact information',\n 'blockquote': 'Long quotation',\n 'q': 'Short quotation',\n 'cite': 'Citation',\n 'caption': 'Table caption',\n 'abbr': 'Abbreviated phrase',\n 'acronym': 'An acronym',\n 'var': 'Variable part of a text',\n 'dfn': 'Term',\n 'strike': 'Strikethrough text',\n 'del': 'Deleted text',\n 'ins': 'Inserted text',\n 'h1': 'Heading level 1',\n 'h2': 'Heading level 2',\n 'h3': 'Heading level 3',\n 'h4': 'Heading level 4',\n 'h5': 'Heading level 5',\n 'h6': 'Heading level 6',\n 'center': 'Centered text',\n 'select': 'List options',\n 'img': 'Image',\n 'input': 'Form element'\n },\n\n /**\n * Generates [data-translate] attribute's value\n * @param {Object} translationData\n * @param {String} location\n */\n composeTranslateAttr = function (translationData, location) {\n var obj = [{\n 'shown': translationData.shown,\n 'translated': translationData.translated,\n 'original': translationData.original,\n 'location': locations[location] || 'Text'\n }];\n\n return JSON.stringify(obj);\n },\n\n /**\n * Sets text for the element\n * @param {Object} el\n * @param {String} text\n */\n setText = function (el, text) {\n $(el).text(text);\n },\n\n /**\n * Sets [data-translate] attribute for the element\n * @param {Object} el - The element which is binded\n * @param {String} original - The original value of the element\n */\n setTranslateProp = function (el, original) {\n var location = $(el).prop('tagName').toLowerCase(),\n translated = $.mage.__(original),\n translationData = {\n shown: translated,\n translated: translated,\n original: original\n },\n translateAttr = composeTranslateAttr(translationData, location);\n\n $(el).attr('data-translate', translateAttr);\n\n setText(el, translationData.shown);\n },\n\n /**\n * Checks if node represents ko virtual node (nodeType === 8, nodeName === '#comment').\n *\n * @param {HTMLElement} node\n * @returns {Boolean}\n */\n isVirtualElement = function (node) {\n return node.nodeType === 8;\n },\n\n /**\n * Checks if it's real DOM element\n * in case of virtual element, returns span wrapper\n * @param {Object} el\n * @param {bool} isUpdate\n * @return {Object} el\n */\n getRealElement = function (el, isUpdate) {\n if (isVirtualElement(el)) {\n if (isUpdate) {\n return $(el).next('span');\n }\n\n return $('<span></span>').insertAfter(el);\n }\n\n return el;\n },\n\n /**\n * execute i18n binding\n * @param {Object} element\n * @param {Function} valueAccessor\n * @param {bool} isUpdate\n */\n execute = function (element, valueAccessor, isUpdate) {\n var original = ko.unwrap(valueAccessor() || ''),\n el = getRealElement(element, isUpdate),\n inlineTranslation = (module.config() || {}).inlineTranslation;\n\n if (inlineTranslation) {\n setTranslateProp(el, original);\n } else {\n setText(el, $.mage.__(original));\n }\n };\n\n /**\n * i18n binding\n * @property {Function} init\n * @property {Function} update\n */\n ko.bindingHandlers.i18n = {\n\n /**\n * init i18n binding\n * @param {Object} element\n * @param {Function} valueAccessor\n */\n init: function (element, valueAccessor) {\n execute(element, valueAccessor);\n },\n\n /**\n * update i18n binding\n * @param {Object} element\n * @param {Function} valueAccessor\n */\n update: function (element, valueAccessor) {\n execute(element, valueAccessor, true);\n }\n };\n\n ko.virtualElements.allowedBindings.i18n = true;\n\n renderer\n .addNode('translate', {\n binding: 'i18n'\n })\n .addAttribute('translate', {\n binding: 'i18n'\n });\n});\n","Magento_Ui/js/lib/registry/registry.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'jquery',\n 'underscore'\n], function ($, _) {\n 'use strict';\n\n var privateData = new WeakMap();\n\n /**\n * Extracts private item storage associated\n * with a provided registry instance.\n *\n * @param {Object} container\n * @returns {Object}\n */\n function getItems(container) {\n return privateData.get(container).items;\n }\n\n /**\n * Extracts private requests array associated\n * with a provided registry instance.\n *\n * @param {Object} container\n * @returns {Array}\n */\n function getRequests(container) {\n return privateData.get(container).requests;\n }\n\n /**\n * Wrapper function used for convenient access to the elements.\n * See 'async' method for examples of usage and comparison\n * with a regular 'get' method.\n *\n * @param {(String|Object|Function)} name - Key of the requested element.\n * @param {Registry} registry - Instance of a registry\n * where to search for the element.\n * @param {(Function|String)} [method] - Optional callback function\n * or a name of the elements' method which\n * will be invoked when element is available in registry.\n * @returns {*}\n */\n function async(name, registry, method) {\n var args = _.toArray(arguments).slice(3);\n\n if (_.isString(method)) {\n registry.get(name, function (component) {\n component[method].apply(component, args);\n });\n } else if (_.isFunction(method)) {\n registry.get(name, method);\n } else if (!args.length) {\n return registry.get(name);\n }\n }\n\n /**\n * Checks that every property of the query object\n * is present and equal to the corresponding\n * property in target object.\n * Note that non-strict comparison is used.\n *\n * @param {Object} query - Query object.\n * @param {Object} target - Target object.\n * @returns {Boolean}\n */\n function compare(query, target) {\n var matches = true,\n index,\n keys,\n key;\n\n if (!_.isObject(query) || !_.isObject(target)) {\n return false;\n }\n\n keys = Object.getOwnPropertyNames(query);\n index = keys.length;\n\n while (matches && index--) {\n key = keys[index];\n\n /* eslint-disable eqeqeq */\n if (target[key] != query[key]) {\n matches = false;\n }\n\n /* eslint-enable eqeqeq */\n }\n\n return matches;\n }\n\n /**\n * Explodes incoming string into object if\n * string is defined as a set of key = value pairs.\n *\n * @param {(String|*)} query - String to be processed.\n * @returns {Object|*} Either created object or an unmodified incoming\n * value if conversion was not possible.\n * @example Sample conversions.\n * 'key = value, key2 = value2'\n * => {key: 'value', key2: 'value2'}\n */\n function explode(query) {\n var result = {},\n index,\n data;\n\n if (typeof query !== 'string' || !~query.indexOf('=')) {\n return query;\n }\n\n query = query.split(',');\n index = query.length;\n\n while (index--) {\n data = query[index].split('=');\n\n result[data[0].trim()] = data[1].trim();\n }\n\n return result;\n }\n\n /**\n * Extracts items from the provided data object\n * which matches specified search criteria.\n *\n * @param {Object} data - Data object where to perform a lookup.\n * @param {(String|Object|Function)} query - Search criteria.\n * @param {Boolean} findAll - Flag that defines whether to\n * search for all applicable items or to stop on a first found entry.\n * @returns {Array|Object|*}\n */\n function find(data, query, findAll) {\n var iterator,\n item;\n\n query = explode(query);\n\n if (typeof query === 'string') {\n item = data[query];\n\n if (findAll) {\n return item ? [item] : [];\n }\n\n return item;\n }\n\n iterator = !_.isFunction(query) ?\n compare.bind(null, query) :\n query;\n\n return findAll ?\n _.filter(data, iterator) :\n _.find(data, iterator);\n }\n\n /**\n * @constructor\n */\n function Registry() {\n var data = {\n items: {},\n requests: []\n };\n\n this._updateRequests = _.debounce(this._updateRequests.bind(this), 10);\n privateData.set(this, data);\n }\n\n Registry.prototype = {\n constructor: Registry,\n\n /**\n * Retrieves item from registry which matches specified search criteria.\n *\n * @param {(Object|String|Function|Array)} query - Search condition (see examples).\n * @param {Function} [callback] - Callback that will be invoked when\n * all of the requested items are available.\n * @returns {*}\n *\n * @example Requesting item by it's name.\n * var obj = {index: 'test', sample: true};\n *\n * registry.set('first', obj);\n * registry.get('first') === obj;\n * => true\n *\n * @example Requesting item with a specific properties.\n * registry.get('sample = 1, index = test') === obj;\n * => true\n * registry.get('sample = 0, index = foo') === obj;\n * => false\n *\n * @example Declaring search criteria as an object.\n * registry.get({sample: true}) === obj;\n * => true;\n *\n * @example Providing custom search handler.\n * registry.get(function (item) { return item.sample === true; }) === obj;\n * => true\n *\n * @example Sample asynchronous request declaration.\n * registry.get('index = test', function (item) {});\n *\n * @example Requesting multiple elements.\n * registry.set('second', {index: 'test2'});\n * registry.get(['first', 'second'], function (first, second) {});\n */\n get: function (query, callback) {\n if (typeof callback !== 'function') {\n return find(getItems(this), query);\n }\n\n this._addRequest(query, callback);\n },\n\n /**\n * Sets provided item to the registry.\n *\n * @param {String} id - Item's identifier.\n * @param {*} item - Item's data.\n * returns {Registry} Chainable.\n */\n set: function (id, item) {\n getItems(this)[id] = item;\n\n this._updateRequests();\n\n return this;\n },\n\n /**\n * Removes specified item from registry.\n * Note that search query is not applicable.\n *\n * @param {String} id - Item's identifier.\n * @returns {Registry} Chainable.\n */\n remove: function (id) {\n delete getItems(this)[id];\n\n return this;\n },\n\n /**\n * Retrieves a collection of elements that match\n * provided search criteria.\n *\n * @param {(Object|String|Function)} query - Search query.\n * See 'get' method for the syntax examples.\n * @returns {Array} Found elements.\n */\n filter: function (query) {\n return find(getItems(this), query, true);\n },\n\n /**\n * Checks that at least one element in collection\n * matches provided search criteria.\n *\n * @param {(Object|String|Function)} query - Search query.\n * See 'get' method for the syntax examples.\n * @returns {Boolean}\n */\n has: function (query) {\n return !!this.get(query);\n },\n\n /**\n * Checks that registry contains a provided item.\n *\n * @param {*} item - Item to be checked.\n * @returns {Boolean}\n */\n contains: function (item) {\n return _.contains(getItems(this), item);\n },\n\n /**\n * Extracts identifier of an item if it's present in registry.\n *\n * @param {*} item - Item whose identifier will be extracted.\n * @returns {String|Undefined}\n */\n indexOf: function (item) {\n return _.findKey(getItems(this), function (elem) {\n return item === elem;\n });\n },\n\n /**\n * Same as a 'get' method except that it returns\n * a promise object instead of invoking provided callback.\n *\n * @param {(String|Function|Object|Array)} query - Search query.\n * See 'get' method for the syntax examples.\n * @returns {jQueryPromise}\n */\n promise: function (query) {\n var defer = $.Deferred(),\n callback = defer.resolve.bind(defer);\n\n this.get(query, callback);\n\n return defer.promise();\n },\n\n /**\n * Creates a wrapper function over the provided search query\n * in order to provide somehow more convenient access to the\n * registry's items.\n *\n * @param {(String|Object|Function)} query - Search criteria.\n * See 'get' method for the syntax examples.\n * @returns {Function}\n *\n * @example Comparison with a 'get' method on retrieving items.\n * var module = registry.async('name');\n *\n * module();\n * => registry.get('name');\n *\n * @example Asynchronous request.\n * module(function (component) {});\n * => registry.get('name', function (component) {});\n *\n * @example Requesting item and invoking it's method with specified parameters.\n * module('trigger', true);\n * => registry.get('name', function (component) {\n * component.trigger(true);\n * });\n */\n async: function (query) {\n return async.bind(null, query, this);\n },\n\n /**\n * Creates new instance of a Registry.\n *\n * @returns {Registry} New instance.\n */\n create: function () {\n return new Registry;\n },\n\n /**\n * Adds new request to the queue or resolves it immediately\n * if all of the required items are available.\n *\n * @private\n * @param {(Object|String|Function|Array)} queries - Search criteria.\n * See 'get' method for the syntax examples.\n * @param {Function} callback - Callback that will be invoked when\n * all of the requested items are available.\n * @returns {Registry}\n */\n _addRequest: function (queries, callback) {\n var request;\n\n if (!Array.isArray(queries)) {\n queries = queries ? [queries] : [];\n }\n\n request = {\n queries: queries.map(explode),\n callback: callback\n };\n\n this._canResolve(request) ?\n this._resolveRequest(request) :\n getRequests(this).push(request);\n\n return this;\n },\n\n /**\n * Updates requests list resolving applicable items.\n *\n * @private\n * @returns {Registry} Chainable.\n */\n _updateRequests: function () {\n getRequests(this)\n .filter(this._canResolve, this)\n .forEach(this._resolveRequest, this);\n\n return this;\n },\n\n /**\n * Resolves provided request invoking it's callback\n * with items specified in query parameters.\n *\n * @private\n * @param {Object} request - Request object.\n * @returns {Registry} Chainable.\n */\n _resolveRequest: function (request) {\n var requests = getRequests(this),\n items = request.queries.map(this.get, this),\n index = requests.indexOf(request);\n\n request.callback.apply(null, items);\n\n if (~index) {\n requests.splice(index, 1);\n }\n\n return this;\n },\n\n /**\n * Checks if provided request can be resolved.\n *\n * @private\n * @param {Object} request - Request object.\n * @returns {Boolean}\n */\n _canResolve: function (request) {\n var queries = request.queries;\n\n return queries.every(this.has, this);\n }\n };\n\n return new Registry;\n});\n","Magento_Ui/js/lib/view/utils/dom-observer.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'jquery',\n 'underscore',\n 'domReady!'\n], function ($, _) {\n 'use strict';\n\n var counter = 1,\n watchers,\n globalObserver,\n disabledNodes = [];\n\n watchers = {\n selectors: {},\n nodes: {}\n };\n\n /**\n * Checks if node represents an element node (nodeType === 1).\n *\n * @param {HTMLElement} node\n * @returns {Boolean}\n */\n function isElementNode(node) {\n return node.nodeType === 1;\n }\n\n /**\n * Extracts all child descendant\n * elements of a specified node.\n *\n * @param {HTMLElement} node\n * @returns {Array}\n */\n function extractChildren(node) {\n var children = node.querySelectorAll('*');\n\n return _.toArray(children);\n }\n\n /**\n * Extracts node identifier. If ID is not specified,\n * then it will be created for the provided node.\n *\n * @param {HTMLElement} node\n * @returns {Number}\n */\n function getNodeId(node) {\n var id = node._observeId;\n\n if (!id) {\n id = node._observeId = counter++;\n }\n\n return id;\n }\n\n /**\n * Invokes callback passing node to it.\n *\n * @param {HTMLElement} node\n * @param {Object} data\n */\n function trigger(node, data) {\n var id = getNodeId(node),\n ids = data.invoked;\n\n if (_.contains(ids, id)) {\n return;\n }\n\n data.callback(node);\n data.invoked.push(id);\n }\n\n /**\n * Adds node to the observer list.\n *\n * @param {HTMLElement} node\n * @returns {Object}\n */\n function createNodeData(node) {\n var nodes = watchers.nodes,\n id = getNodeId(node);\n\n nodes[id] = nodes[id] || {};\n\n return nodes[id];\n }\n\n /**\n * Returns data associated with a specified node.\n *\n * @param {HTMLElement} node\n * @returns {Object|Undefined}\n */\n function getNodeData(node) {\n var nodeId = node._observeId;\n\n return watchers.nodes[nodeId];\n }\n\n /**\n * Removes data associated with a specified node.\n *\n * @param {HTMLElement} node\n */\n function removeNodeData(node) {\n var nodeId = node._observeId;\n\n delete watchers.nodes[nodeId];\n }\n\n /**\n * Adds removal listener for a specified node.\n *\n * @param {HTMLElement} node\n * @param {Object} data\n */\n function addRemovalListener(node, data) {\n var nodeData = createNodeData(node);\n\n (nodeData.remove = nodeData.remove || []).push(data);\n }\n\n /**\n * Adds listener for the nodes which matches specified selector.\n *\n * @param {String} selector - CSS selector.\n * @param {Object} data\n */\n function addSelectorListener(selector, data) {\n var storage = watchers.selectors;\n\n (storage[selector] = storage[selector] || []).push(data);\n }\n\n /**\n * Calls handlers associated with an added node.\n * Adds listeners for the node removal.\n *\n * @param {HTMLElement} node - Added node.\n */\n function processAdded(node) {\n _.each(watchers.selectors, function (listeners, selector) {\n listeners.forEach(function (data) {\n if (!data.ctx.contains(node) || !$(node, data.ctx).is(selector)) {\n return;\n }\n\n if (data.type === 'add') {\n trigger(node, data);\n } else if (data.type === 'remove') {\n addRemovalListener(node, data);\n }\n });\n });\n }\n\n /**\n * Calls handlers associated with a removed node.\n *\n * @param {HTMLElement} node - Removed node.\n */\n function processRemoved(node) {\n var nodeData = getNodeData(node),\n listeners = nodeData && nodeData.remove;\n\n if (!listeners) {\n return;\n }\n\n listeners.forEach(function (data) {\n trigger(node, data);\n });\n\n removeNodeData(node);\n }\n\n /**\n * Removes all non-element nodes from provided array\n * and appends to it descendant elements.\n *\n * @param {Array} nodes\n * @returns {Array}\n */\n function formNodesList(nodes) {\n var result = [],\n children;\n\n nodes = _.toArray(nodes).filter(isElementNode);\n\n nodes.forEach(function (node) {\n result.push(node);\n\n children = extractChildren(node);\n result = result.concat(children);\n });\n\n return result;\n }\n\n /**\n * Collects all removed and added nodes from\n * mutation records into separate arrays\n * while removing duplicates between both types of changes.\n *\n * @param {Array} mutations - An array of mutation records.\n * @returns {Object} Object with 'removed' and 'added' nodes arrays.\n */\n function formChangesLists(mutations) {\n var removed = [],\n added = [];\n\n mutations.forEach(function (record) {\n removed = removed.concat(_.toArray(record.removedNodes));\n added = added.concat(_.toArray(record.addedNodes));\n });\n\n removed = removed.filter(function (node) {\n var addIndex = added.indexOf(node),\n wasAdded = !!~addIndex;\n\n if (wasAdded) {\n added.splice(addIndex, 1);\n }\n\n return !wasAdded;\n });\n\n return {\n removed: formNodesList(removed),\n added: formNodesList(added)\n };\n }\n\n /**\n * Verify if the DOM node is a child of a defined disabled node, if so we shouldn't observe provided mutation.\n *\n * @param {Object} mutation - a single mutation\n * @returns {Boolean}\n */\n function shouldObserveMutation(mutation) {\n var isDisabled;\n\n if (disabledNodes.length > 0) {\n // Iterate through the disabled nodes and determine if this mutation is occurring inside one of them\n isDisabled = _.find(disabledNodes, function (node) {\n return node === mutation.target || $.contains(node, mutation.target);\n });\n\n // If we find a matching node we should not observe the mutation\n return !isDisabled;\n }\n\n return true;\n }\n\n /**\n * Should we observe these mutations? Check the first and last mutation to determine if this is a disabled mutation,\n * we check both the first and last in case one has been removed from the DOM during the process of the mutation.\n *\n * @param {Array} mutations - An array of mutation records.\n * @returns {Boolean}\n */\n function shouldObserveMutations(mutations) {\n var firstMutation,\n lastMutation;\n\n if (mutations.length > 0) {\n firstMutation = mutations[0];\n lastMutation = mutations[mutations.length - 1];\n\n return shouldObserveMutation(firstMutation) && shouldObserveMutation(lastMutation);\n }\n\n return true;\n }\n\n globalObserver = new MutationObserver(function (mutations) {\n var changes;\n\n if (shouldObserveMutations(mutations)) {\n changes = formChangesLists(mutations);\n\n changes.removed.forEach(processRemoved);\n changes.added.forEach(processAdded);\n }\n });\n\n globalObserver.observe(document.body, {\n subtree: true,\n childList: true\n });\n\n return {\n /**\n * Disable a node from being observed by the mutations, you may want to disable specific aspects of the\n * application which are heavy on DOM changes. The observer running on some actions could cause significant\n * delays and degrade the performance of that specific part of the application exponentially.\n *\n * @param {HTMLElement} node - a HTML node within the document\n */\n disableNode: function (node) {\n disabledNodes.push(node);\n },\n\n /**\n * Adds listener for the appearance of nodes that matches provided\n * selector and which are inside of the provided context. Callback will be\n * also invoked on elements which a currently present.\n *\n * @param {String} selector - CSS selector.\n * @param {Function} callback - Function that will invoked when node appears.\n * @param {HTMLElement} [ctx=document.body] - Context inside of which to search for the node.\n */\n get: function (selector, callback, ctx) {\n var data,\n nodes;\n\n data = {\n ctx: ctx || document.body,\n type: 'add',\n callback: callback,\n invoked: []\n };\n\n nodes = $(selector, data.ctx).toArray();\n\n nodes.forEach(function (node) {\n trigger(node, data);\n });\n\n addSelectorListener(selector, data);\n },\n\n /**\n * Adds listener for the nodes removal.\n *\n * @param {(jQueryObject|HTMLElement|Array|String)} selector\n * @param {Function} callback - Function that will invoked when node is removed.\n * @param {HTMLElement} [ctx=document.body] - Context inside of which to search for the node.\n */\n remove: function (selector, callback, ctx) {\n var nodes = [],\n data;\n\n data = {\n ctx: ctx || document.body,\n type: 'remove',\n callback: callback,\n invoked: []\n };\n\n if (typeof selector === 'object') {\n nodes = !_.isUndefined(selector.length) ?\n _.toArray(selector) :\n [selector];\n } else if (_.isString(selector)) {\n nodes = $(selector, ctx).toArray();\n\n addSelectorListener(selector, data);\n }\n\n nodes.forEach(function (node) {\n addRemovalListener(node, data);\n });\n },\n\n /**\n * Removes listeners.\n *\n * @param {String} selector\n * @param {Function} [fn]\n */\n off: function (selector, fn) {\n var selectors = watchers.selectors,\n listeners = selectors[selector];\n\n if (selector && !fn) {\n delete selectors[selector];\n } else if (listeners && fn) {\n selectors[selector] = listeners.filter(function (data) {\n return data.callback !== fn;\n });\n }\n }\n };\n});\n","Magento_Ui/js/lib/view/utils/bindings.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'ko',\n 'jquery',\n 'underscore'\n], function (ko, $, _) {\n 'use strict';\n\n /**\n * Checks if provided value is a dom element.\n *\n * @param {*} node - Value to be checked.\n * @returns {Boolean}\n */\n function isDomElement(node) {\n return typeof node === 'object' && node.tagName && node.nodeType;\n }\n\n /**\n * Removes from the provided array all non-root nodes located inside\n * of the comment element as long as the closing comment tags.\n *\n * @param {(Array|ArrayLike)} nodes - An array of nodes to be processed.\n * @returns {Array}\n */\n function normalize(nodes) {\n var result;\n\n nodes = _.toArray(nodes);\n result = nodes.slice();\n\n nodes.forEach(function (node) {\n if (node.nodeType === 8) {\n result = !ko.virtualElements.hasBindingValue(node) ?\n _.without(result, node) :\n _.difference(result, ko.virtualElements.childNodes(node));\n }\n });\n\n return result;\n }\n\n /**\n * Extends binding context of each item in the collection.\n *\n * @param {...Object} extenders - Multiple extender objects to be applied to the context.\n * @returns {jQueryCollection} Chainable.\n */\n $.fn.extendCtx = function () {\n var nodes = normalize(this),\n extenders = _.toArray(arguments);\n\n nodes.forEach(function (node) {\n var ctx = ko.contextFor(node),\n data = [ctx].concat(extenders);\n\n _.extend.apply(_, data);\n });\n\n return this;\n };\n\n /**\n * Evaluates bindings specified in each DOM element of collection.\n *\n * @param {(HTMLElement|Object)} [ctx] - Context to use for bindings evaluation.\n * If not specified then current context of a collections' item will be used.\n * @returns {jQueryCollection} Chainable.\n */\n $.fn.applyBindings = function (ctx) {\n var nodes = normalize(this),\n nodeCtx;\n\n if (isDomElement(ctx)) {\n ctx = ko.contextFor(ctx);\n }\n\n nodes.forEach(function (node) {\n nodeCtx = ctx || ko.contextFor(node);\n\n ko.applyBindings(nodeCtx, node);\n });\n\n return this;\n };\n\n /**\n * Adds specified bindings to each DOM element in\n * collection and evaluates them with provided context.\n *\n * @param {(Object|Function)} data - Either bindings object or a function\n * which returns bindings data for each element in collection.\n * @param {(HTMLElement|Object)} [ctx] - Context to use for bindings evaluation.\n * If not specified then current context of a collections' item will be used.\n * @returns {jQueryCollection} Chainable.\n */\n $.fn.bindings = function (data, ctx) {\n var nodes = normalize(this),\n bindings = data,\n nodeCtx;\n\n if (isDomElement(ctx)) {\n ctx = ko.contextFor(ctx);\n }\n\n nodes.forEach(function (node) {\n nodeCtx = ctx || ko.contextFor(node);\n\n if (_.isFunction(data)) {\n bindings = data(nodeCtx, node);\n }\n\n ko.applyBindingsToNode(node, bindings, nodeCtx);\n });\n\n return this;\n };\n});\n","Magento_Ui/js/lib/view/utils/raf.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n 'use strict';\n\n var processMap = new WeakMap(),\n origRaf,\n raf;\n\n origRaf = window.requestAnimationFrame ||\n window.webkitRequestAnimationFrame ||\n window.mozRequestAnimationFrame ||\n window.onRequestAnimationFrame ||\n window.msRequestAnimationFrame ||\n function (callback) {\n if (typeof callback != 'function') {\n throw new Error('raf argument \"callback\" must be of type function');\n }\n window.setTimeout(callback, 1000 / 60);\n };\n\n /**\n * Creates new process object or extracts the\n * the existing one.\n *\n * @param {*} id - Process identifier.\n * @param {Number} fps - Required FPS count.\n * @returns {Object}\n */\n function getProcess(id, fps) {\n var process = processMap.get(id);\n\n if (!process) {\n process = {};\n processMap.set(id, process);\n }\n\n if (process.fps !== fps) {\n process.fps = fps;\n process.interval = 1000 / fps;\n process.update = Date.now();\n }\n\n return process;\n }\n\n /**\n * Proxy method which delegates call to the 'requestAnimationFrame'\n * function and optionally can keep track of the FPS with which\n * provided function is called.\n *\n * @param {Function} callback - Callback function to be passed to 'requestAnimationFrame'.\n * @param {Number} [fps] - If specified, will update FPS counter for the provided function.\n * @returns {Number|Boolean} ID of request or a flag which indicates\n * whether callback fits specified FPS.\n */\n raf = function (callback, fps) {\n var rafId = origRaf(callback);\n\n return fps ? raf.tick(callback, fps) : rafId;\n };\n\n /**\n * Updates FPS counter for the specified process\n * and returns a flag which indicates whether\n * counter value is equal or greater than the required FPS.\n *\n * @param {*} id - Process identifier.\n * @param {Number} fps - Required FPS count.\n * @returns {Boolean}\n */\n raf.tick = function (id, fps) {\n var process = getProcess(id, fps),\n now = Date.now(),\n delta = now - process.update,\n interval = process.interval;\n\n if (fps >= 60 || delta >= interval) {\n process.update = now - delta % interval;\n\n return true;\n }\n\n return false;\n };\n\n return raf;\n});\n","Magento_Ui/js/lib/view/utils/async.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'ko',\n 'jquery',\n 'underscore',\n 'uiRegistry',\n './dom-observer',\n 'Magento_Ui/js/lib/knockout/extender/bound-nodes',\n './bindings'\n], function (ko, $, _, registry, domObserver, boundedNodes) {\n 'use strict';\n\n /**\n * Checks if provided value is a dom element.\n *\n * @param {*} node - Value to be checked.\n * @returns {Boolean}\n */\n function isDomElement(node) {\n return typeof node === 'object' && node.tagName && node.nodeType;\n }\n\n /**\n * Parses provided string and extracts\n * component, context and selector data from it.\n *\n * @param {String} str - String to be processed.\n * @returns {Object} Data retrieved from string.\n *\n * @example Sample format.\n * '{{component}}:{{ctx}} -> {{selector}}'\n *\n * component - Name of component.\n * ctx - Selector of the root node upon which component is binded.\n * selector - Selector of DOM elements located\n * inside of a previously specified context.\n */\n function parseSelector(str) {\n var data = str.trim().split('->'),\n result = {},\n componentData;\n\n if (data.length === 1) {\n if (!~data[0].indexOf(':')) {\n result.selector = data[0];\n } else {\n componentData = data[0];\n }\n } else {\n componentData = data[0];\n result.selector = data[1];\n }\n\n if (componentData) {\n componentData = componentData.split(':');\n\n result.component = componentData[0];\n result.ctx = componentData[1];\n }\n\n _.each(result, function (value, key) {\n result[key] = value.trim();\n });\n\n return result;\n }\n\n /**\n * Internal method used to normalize argumnets passed\n * to 'async' module methods.\n *\n * @param {(String|Object)} selector\n * @param {(HTMLElement|Object|String)} [ctx]\n * @returns {Object}\n */\n function parseData(selector, ctx) {\n var data = {};\n\n if (arguments.length === 2) {\n data.selector = selector;\n\n if (isDomElement(ctx)) {\n data.ctx = ctx;\n } else {\n data.component = ctx;\n data.ctx = '*';\n }\n } else {\n data = _.isString(selector) ?\n parseSelector(selector) :\n selector;\n }\n\n return data;\n }\n\n /**\n * Creates promise that will be resolved\n * when requested component is registred.\n *\n * @param {String} name - Name of component.\n * @returns {jQueryPromise}\n */\n function waitComponent(name) {\n var deffer = $.Deferred();\n\n if (_.isString(name)) {\n registry.get(name, function (component) {\n deffer.resolve(component);\n });\n } else {\n deffer.resolve(name);\n }\n\n return deffer.promise();\n }\n\n /**\n * Creates listener for the nodes binded to provided component.\n *\n * @param {Object} data - Listener data.\n * @param {Object} component - Associated with nodes component.\n */\n function setRootListener(data, component) {\n boundedNodes.get(component, function (root) {\n if (!$(root).is(data.ctx || '*')) {\n return;\n }\n\n data.selector ?\n domObserver.get(data.selector, data.fn, root) :\n data.fn(root);\n });\n }\n\n /*eslint-disable no-unused-vars*/\n /**\n * Sets listener for the appearance of elements which\n * matches specified selector data.\n *\n * @param {(String|Object)} selector - Valid css selector or a string\n * in format acceptable by 'parseSelector' method or an object with\n * 'component', 'selector' and 'ctx' properties.\n * @param {(HTMLElement|Object|String)} [ctx] - Optional context parameter\n * which might be a DOM element, component instance or components' name.\n * @param {Function} fn - Callback that will be invoked\n * when required DOM element appears.\n *\n * @example\n * Creating listener of the 'span' nodes appearance,\n * located inside of 'div' nodes, which are binded to 'cms_page_listing' component:\n *\n * $.async('cms_page_listing:div -> span', function (node) {});\n *\n * @example Another syntaxes of the previous example.\n * $.async({\n * component: 'cms_page_listing',\n * ctx: 'div',\n * selector: 'span'\n * }, function (node) {});\n *\n * @example Listens for appearance of any child node inside of specified component.\n * $.async('> *', 'cms_page_lsiting', function (node) {});\n *\n * @example Listens for appearance of 'span' nodes inside of specific context.\n * $.async('span', document.getElementById('test'), function (node) {});\n */\n $.async = function (selector, ctx, fn) {\n var args = _.toArray(arguments),\n data = parseData.apply(null, _.initial(args));\n\n data.fn = _.last(args);\n\n if (data.component) {\n waitComponent(data.component)\n .then(setRootListener.bind(null, data));\n } else {\n domObserver.get(data.selector, data.fn, data.ctx);\n }\n };\n\n /*eslint-enable no-unused-vars*/\n\n _.extend($.async, {\n\n /*eslint-disable no-unused-vars*/\n /**\n * Returns collection of elements found by provided selector data.\n *\n * @param {(String|Object)} selector - See 'async' definition.\n * @param {(HTMLElement|Object|String)} [ctx] - See 'async' definition.\n * @returns {Array} An array of DOM elements.\n */\n get: function (selector, ctx) {\n var data = parseData.apply(null, arguments),\n component = data.component,\n nodes;\n\n if (!component) {\n return $(data.selector, data.ctx).toArray();\n } else if (_.isString(component)) {\n component = registry.get(component);\n }\n\n if (!component) {\n return [];\n }\n\n nodes = boundedNodes.get(component);\n nodes = $(nodes).filter(data.ctx).toArray();\n\n return data.selector ?\n $(data.selector, nodes).toArray() :\n nodes;\n },\n\n /*eslint-enable no-unused-vars*/\n\n /**\n * Sets removal listener of the specified nodes.\n *\n * @param {(HTMLElement|Array|ArrayLike)} nodes - Nodes whose removal to track.\n * @param {Function} fn - Callback that will be invoked when node is removed.\n */\n remove: function (nodes, fn) {\n domObserver.remove(nodes, fn);\n },\n\n parseSelector: parseSelector\n });\n\n return $;\n});\n","Magento_Ui/js/lib/logger/console-output-handler.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n './levels-pool'\n], function (logLevels) {\n 'use strict';\n\n var levels = logLevels.getLevels();\n\n /**\n * @param {LogFormatter} formatter\n */\n function ConsoleOutputHandler(formatter) {\n /**\n * @protected\n * @type {LogFormatter}\n */\n this.formatter_ = formatter;\n }\n\n /**\n * Display data of the provided entry to the console.\n *\n * @param {LogEntry} entry - Entry to be displayed.\n */\n ConsoleOutputHandler.prototype.show = function (entry) {\n var displayString = this.formatter_.process(entry);\n\n switch (entry.level) {\n case levels.ERROR:\n console.error(displayString);\n break;\n\n case levels.WARN:\n console.warn(displayString);\n break;\n\n case levels.INFO:\n console.info(displayString);\n break;\n\n case levels.DEBUG:\n console.log(displayString);\n break;\n }\n };\n\n /**\n * Displays the array of entries.\n *\n * @param {Array<LogEntry>} entries\n */\n ConsoleOutputHandler.prototype.dump = function (entries) {\n entries.forEach(this.show, this);\n };\n\n return ConsoleOutputHandler;\n});\n","Magento_Ui/js/lib/logger/logger.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n './levels-pool'\n], function (logLevels) {\n 'use strict';\n\n var levels = logLevels.getLevels();\n\n /**\n * @param {LogOutputHandler} outputHandler\n * @param {LogEntryFactory} entryFactory\n */\n function Logger(outputHandler, entryFactory) {\n /**\n * An array of log entries.\n *\n * @protected\n * @type {Array<LogEntry>}\n */\n this.entries_ = [];\n\n /**\n * Current display level.\n *\n * @protected\n * @type {Number}\n */\n this.displayLevel_ = levels.ERROR;\n\n /**\n * An array of display criteria.\n *\n * @protected\n * @type {Array<LogCriteria>}\n */\n this.displayCriteria_ = [];\n\n /**\n * @protected\n * @type {LogEntryFactory}\n */\n this.entryFactory_ = entryFactory;\n\n /**\n * @protected\n * @type {Array<LogOutputHandler>}\n */\n this.outputHandlers_ = [outputHandler];\n\n this.addDisplayCriteria(this.matchesLevel_);\n }\n\n /**\n * Swaps current display level with the provided one.\n *\n * @param {Number} level - Level's code.\n */\n Logger.prototype.setDisplayLevel = function (level) {\n var levelName = logLevels.getNameByCode(level);\n\n if (!levelName) {\n throw new TypeError('The provided level is not defined in the levels list.');\n }\n\n this.displayLevel_ = level;\n };\n\n /**\n * Sets up the criteria by which log entries will be filtered out from the output.\n *\n * @param {LogCriteria} criteria\n */\n Logger.prototype.addDisplayCriteria = function (criteria) {\n this.displayCriteria_.push(criteria);\n };\n\n /**\n * Removes previously defined criteria.\n *\n * @param {LogCriteria} criteria\n */\n Logger.prototype.removeDisplayCriteria = function (criteria) {\n var index = this.displayCriteria_.indexOf(criteria);\n\n if (~index) {\n this.displayCriteria_.splice(index, 1);\n }\n };\n\n /**\n * @param {String} message\n * @param {Object} [messageData]\n * @returns {LogEntry}\n */\n Logger.prototype.error = function (message, messageData) {\n return this.log_(message, levels.ERROR, messageData);\n };\n\n /**\n * @param {String} message\n * @param {Object} [messageData]\n * @returns {LogEntry}\n */\n Logger.prototype.warn = function (message, messageData) {\n return this.log_(message, levels.WARN, messageData);\n };\n\n /**\n * @param {String} message\n * @param {Object} [messageData]\n * @returns {LogEntry}\n */\n Logger.prototype.info = function (message, messageData) {\n return this.log_(message, levels.INFO, messageData);\n };\n\n /**\n * @param {String} message\n * @param {Object} [messageData]\n * @returns {LogEntry}\n */\n Logger.prototype.debug = function (message, messageData) {\n return this.log_(message, levels.DEBUG, messageData);\n };\n\n /**\n * @protected\n * @param {String} message\n * @param {Number} level\n * @param {Object} [messageData]\n * @returns {LogEntry}\n */\n Logger.prototype.log_ = function (message, level, messageData) {\n var entry = this.createEntry_(message, level, messageData);\n\n this.entries_.push(entry);\n\n if (this.matchesCriteria_(entry)) {\n this.processOutput_(entry);\n }\n\n return entry;\n };\n\n /**\n * @protected\n * @param {String} message\n * @param {Number} level\n * @param {Object} [messageData]\n * @returns {LogEntry}\n */\n Logger.prototype.createEntry_ = function (message, level, messageData) {\n return this.entryFactory_.createEntry(message, level, messageData);\n };\n\n /**\n * Returns an array of log entries that have been added to the logger.\n *\n * @param {LogCriteria} [criteria] - Optional filter criteria.\n * @returns {Array<LogEntry>}\n */\n Logger.prototype.getEntries = function (criteria) {\n if (criteria) {\n return this.entries_.filter(criteria);\n }\n\n return this.entries_;\n };\n\n /**\n * @param {LogCriteria} [criteria]\n */\n Logger.prototype.dump = function (criteria) {\n var entries;\n\n if (!criteria) {\n criteria = this.matchesCriteria_;\n }\n\n entries = this.entries_.filter(criteria, this);\n\n this.outputHandlers_.forEach(function (handler) {\n handler.dump(entries);\n });\n };\n\n /**\n * @protected\n * @param {LogEntry} entry\n */\n Logger.prototype.processOutput_ = function (entry) {\n this.outputHandlers_.forEach(function (handler) {\n handler.show(entry);\n });\n };\n\n /**\n * @protected\n * @param {LogEntry} entry\n * @returns {Boolean}\n */\n Logger.prototype.matchesCriteria_ = function (entry) {\n return this.displayCriteria_.every(function (criteria) {\n return criteria.call(this, entry);\n }, this);\n };\n\n /**\n * Checks that the level of provided entry passes the \"displayLevel_\" threshold.\n *\n * @protected\n * @param {LogEntry} entry - Entry to be checked.\n * @returns {Boolean}\n */\n Logger.prototype.matchesLevel_ = function (entry) {\n return entry.level <= this.displayLevel_;\n };\n\n return Logger;\n});\n","Magento_Ui/js/lib/logger/console-logger.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n './logger',\n './entry-factory',\n './console-output-handler',\n './formatter',\n './message-pool',\n './levels-pool',\n 'Magento_Ui/js/lib/core/storage/local',\n 'underscore',\n './logger-utils'\n], function (Logger, entryFactory, ConsoleHandler, Formatter, messagePoll, levelsPoll, storage, _, LoggerUtils) {\n 'use strict';\n\n var STORAGE_NAMESPACE = 'CONSOLE_LOGGER';\n\n /**\n * Singleton Logger's sub-class instance of which is configured to display its\n * messages to the console. It also provides the support of predefined messages\n * and persists its display level.\n */\n function ConsoleLogger() {\n var formatter = new Formatter(),\n consoleHandler = new ConsoleHandler(formatter),\n savedLevel = storage.get(STORAGE_NAMESPACE),\n utils = new LoggerUtils(this);\n\n Logger.call(this, consoleHandler, entryFactory);\n\n if (savedLevel) {\n this.displayLevel_ = savedLevel;\n }\n\n this.utils = utils;\n this.messages = messagePoll;\n this.levels = levelsPoll.getLevels();\n }\n\n _.extend(ConsoleLogger, Logger);\n\n ConsoleLogger.prototype = Object.create(Logger.prototype);\n ConsoleLogger.prototype.constructor = ConsoleLogger;\n\n /**\n * Overrides parent method to save the provided display level.\n *\n * @override\n */\n ConsoleLogger.prototype.setDisplayLevel = function (level) {\n Logger.prototype.setDisplayLevel.call(this, level);\n\n storage.set(STORAGE_NAMESPACE, level);\n };\n\n /**\n * Adds the support of predefined messages.\n *\n * @protected\n * @override\n */\n ConsoleLogger.prototype.createEntry_ = function (message, level, data) {\n var code;\n\n if (messagePoll.hasMessage(message)) {\n data = data || {};\n code = message;\n message = messagePoll.getMessage(code);\n\n data.messageCode = code;\n }\n\n return Logger.prototype.createEntry_.call(this, message, level, data);\n };\n\n return new ConsoleLogger();\n});\n","Magento_Ui/js/lib/logger/entry.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n './levels-pool'\n], function (logLevels) {\n 'use strict';\n\n /**\n * @param {String} message\n * @param {Number} level\n * @param {Object} [data]\n */\n function LogEntry(message, level, data) {\n /**\n * @readonly\n * @type {Number}\n */\n this.timestamp = Date.now();\n\n /**\n * @readonly\n * @type {Number}\n */\n this.level = level;\n\n /**\n * @readonly\n * @type {String}\n */\n this.levelName = logLevels.getNameByCode(level);\n\n /**\n * @readonly\n * @type {Object}\n */\n this.data = data;\n\n /**\n * @readonly\n * @type {String}\n */\n this.message = message;\n }\n\n return LogEntry;\n});\n","Magento_Ui/js/lib/logger/levels-pool.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'underscore'\n], function (_) {\n 'use strict';\n\n var LEVELS,\n CODE_MAP;\n\n LEVELS = {\n NONE: 0,\n ERROR: 1,\n WARN: 2,\n INFO: 3,\n DEBUG: 4,\n ALL: 5\n };\n\n CODE_MAP = _.invert(LEVELS);\n\n return {\n /**\n * Returns the list of available log levels.\n *\n * @returns {Object}\n */\n getLevels: function () {\n return LEVELS;\n },\n\n /**\n * Returns name of the log level that matches to the provided code.\n *\n * @returns {String}\n */\n getNameByCode: function (code) {\n return CODE_MAP[code];\n }\n };\n});\n","Magento_Ui/js/lib/logger/formatter.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'moment',\n 'mage/utils/template'\n], function (moment, mageTemplate) {\n 'use strict';\n\n /**\n * @param {String} dateFormat\n * @param {String} template\n */\n function LogFormatter(dateFormat, template) {\n /**\n * @protected\n * @type {String}\n */\n this.dateFormat_ = 'YYYY-MM-DD hh:mm:ss';\n\n /**\n * @protected\n * @type {String}\n */\n this.template_ = '[${ $.date }] [${ $.entry.levelName }] ${ $.message }';\n\n if (dateFormat) {\n this.dateFormat_ = dateFormat;\n }\n\n if (template) {\n this.template_ = template;\n }\n }\n\n /**\n * @param {LogEntry} entry\n * @returns {String}\n */\n LogFormatter.prototype.process = function (entry) {\n var message = mageTemplate.template(entry.message, entry.data),\n date = moment(entry.timestamp).format(this.dateFormat_);\n\n return mageTemplate.template(this.template_, {\n date: date,\n entry: entry,\n message: message\n });\n };\n\n return LogFormatter;\n});\n","Magento_Ui/js/lib/logger/entry-factory.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n './entry'\n], function (LogEntry) {\n 'use strict';\n\n return {\n /**\n * @param {String} message\n * @param {Number} level\n * @param {Object} [messageData]\n * @returns {LogEntry}\n */\n createEntry: function (message, level, messageData) {\n return new LogEntry(message, level, messageData);\n }\n };\n});\n","Magento_Ui/js/lib/logger/message-pool.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine(function () {\n 'use strict';\n\n var MESSAGES = {\n templateStartLoading:\n 'The \"${ $.template }\" template requested by the \"${$.component}\" component started loading.',\n templateLoadedFromServer:\n 'The \"${ $.template }\" template requested by the \"${$.component}\" component was loaded from server.\"',\n templateLoadedFromCache:\n 'The \"${ $.template }\" template requested by the \"${$.component}\" component was loaded from cache.\"',\n templateLoadingFail: 'Failed to load the \"${ $.template }\" template requested by \"${$.component}\".',\n componentStartInitialization:\n 'Component \"${$.component}\" start initialization with instance name \"${$.componentName}\".',\n componentStartLoading: ' Started loading the \"${$.component}\" component.',\n componentFinishLoading: 'The \"${$.component}\" component was loaded.',\n componentLoadingFail: 'Failed to load the \"${$.component}\" component.',\n depsLoadingFail: 'Could not get the declared \"${$.deps}\" dependency for the \"${$.component}\" instance.',\n depsStartRequesting: 'Requesting the \"${$.deps}\" dependency for the \"${$.component}\" instance.',\n depsFinishRequesting: 'The \"${$.deps}\" dependency for the \"${$.component}\" instance was received.',\n requestingComponent: 'Requesting the \"${$.component}\" component.',\n requestingComponentIsLoaded: 'The requested \"${$.component}\" component was received.',\n requestingComponentIsFailed: 'Could not get the requested \"${$.component}\" component.'\n };\n\n return {\n /**\n * Returns message that matches the provided code.\n *\n * @param {String} code - Message's identifier\n * @returns {String}\n */\n getMessage: function (code) {\n return MESSAGES[code];\n },\n\n /**\n * Adds a new message to the poll.\n *\n * @param {String} code - Message's identifier.\n * @param {String} message - Text of the message\n */\n addMessage: function (code, message) {\n MESSAGES[code] = message;\n },\n\n /**\n * Tells whether message with provide code exists in the poll.\n *\n * @param {String} code - Message's identifier.\n * @returns {Boolean}\n */\n hasMessage: function (code) {\n return MESSAGES.hasOwnProperty(code);\n }\n };\n});\n","Magento_Ui/js/lib/logger/logger-utils.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([], function () {\n 'use strict';\n\n /**\n * Utils methods for logger\n * @param {Logger} logger\n */\n function LogUtils(logger) {\n this.logger = logger;\n\n }\n\n /**\n * Method for logging asynchronous operations\n * @param {Promise} promise\n * @param {Object} config\n */\n LogUtils.prototype.asyncLog = function (promise, config) {\n var levels,\n messages,\n wait;\n\n config = config || {};\n levels = config.levels || this.createLevels();\n messages = config.messages || this.createMessages();\n wait = config.wait || 5000;\n\n this.logger[levels.requested](messages.requested, config.data);\n setTimeout(function () {\n promise.state() === 'pending' ?\n this.logger[levels.failed](messages.failed, config.data) :\n this.logger[levels.loaded](messages.loaded, config.data);\n }.bind(this), wait);\n };\n\n /**\n * Method that creates object of messages\n * @param {String} requested - log message that showing that request for class is started\n * @param {String} loaded - log message that show when requested class is loaded\n * @param {String} failed - log message that show when requested class is failed\n * @returns {Object}\n */\n LogUtils.prototype.createMessages = function (requested, loaded, failed) {\n return {\n requested: requested || '',\n loaded: loaded || '',\n failed: failed || ''\n };\n };\n\n /**\n * Method that creates object of log levels\n * @param {String} requested - log message that showing that request for class is started\n * @param {String} loaded - log message that show when requested class is loaded\n * @param {String} failed - log message that show when requested class is failed\n * @returns {Object}\n */\n LogUtils.prototype.createLevels = function (requested, loaded, failed) {\n return {\n requested: requested || 'info',\n loaded: loaded || 'info',\n failed: failed || 'warn'\n };\n };\n\n return LogUtils;\n});\n","Magento_Ui/js/lib/core/events.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\ndefine([\n 'ko',\n 'underscore'\n], function (ko, _) {\n 'use strict';\n\n var eventsMap = new WeakMap();\n\n /**\n * Returns events map or a specific event\n * data associated with a provided object.\n *\n * @param {Object} obj - Key in the events weakmap.\n * @param {String} [name] - Name of the event.\n * @returns {Map|Array|Boolean}\n */\n function getEvents(obj, name) {\n var events = eventsMap.get(obj);\n\n if (!events) {\n return false;\n }\n\n return name ? events.get(name) : events;\n }\n\n /**\n * Adds new event handler.\n *\n * @param {Object} obj - Key in the events weakmap.\n * @param {String} ns - Callback namespace.\n * @param {Function} callback - Event callback.\n * @param {String} name - Name of the event.\n */\n function addHandler(obj, ns, callback, name) {\n var events = getEvents(obj),\n observable,\n data;\n\n observable = !ko.isObservable(obj[name]) ?\n ko.getObservable(obj, name) :\n obj[name];\n\n if (observable) {\n observable.subscribe(callback);\n\n return;\n }\n\n if (!events) {\n events = new Map();\n\n eventsMap.set(obj, events);\n }\n\n data = {\n callback: callback,\n ns: ns\n };\n\n events.has(name) ?\n events.get(name).push(data) :\n events.set(name, [data]);\n }\n\n /**\n * Invokes provided callbacks with a specified arguments.\n *\n * @param {Array} handlers\n * @param {Array} args\n * @returns {Boolean}\n */\n function trigger(handlers, args) {\n var bubble = true,\n callback;\n\n handlers.forEach(function (handler) {\n callback = handler.callback;\n\n if (callback.apply(null, args) === false) {\n bubble = false;\n }\n });\n\n return bubble;\n }\n\n return {\n\n /**\n * Calls callback when name event is triggered.\n * @param {String} events\n * @param {Function} callback\n * @param {Function} ns\n * @return {Object} reference to this\n */\n on: function (events, callback, ns) {\n var iterator;\n\n if (arguments.length < 2) {\n ns = callback;\n }\n\n iterator = addHandler.bind(null, this, ns);\n\n _.isObject(events) ?\n _.each(events, iterator) :\n iterator(callback, events);\n\n return this;\n },\n\n /**\n * Removed callback from listening to target event\n * @param {String} ns\n * @return {Object} reference to this\n */\n off: function (ns) {\n var storage = getEvents(this);\n\n if (!storage) {\n return this;\n }\n\n storage.forEach(function (handlers, name) {\n handlers = handlers.filter(function (handler) {\n return !ns ? false : handler.ns !== ns;\n });\n\n handlers.length ?\n storage.set(name, handlers) :\n storage.delete(name);\n });\n\n return this;\n },\n\n /**\n * Triggers event and executes all attached callbacks.\n *\n * @param {String} name - Name of the event to be triggered.\n * @returns {Boolean}\n */\n trigger: function (name) {\n var handlers,\n args;\n\n handlers = getEvents(this, name),\n args = _.toArray(arguments).slice(1);\n\n if (!handlers || !name) {\n return true;\n }\n\n return trigger(handlers, args);\n }\n };\n});\n","Magento_Ui/js/lib/core/class.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'underscore',\n 'mageUtils',\n 'mage/utils/wrapper'\n], function (_, utils, wrapper) {\n 'use strict';\n\n var Class;\n\n /**\n * Returns property of an object if\n * it's his own property.\n *\n * @param {Object} obj - Object whose property should be retrieved.\n * @param {String} prop - Name of the property.\n * @returns {*} Value of the property or false.\n */\n function getOwn(obj, prop) {\n return _.isObject(obj) && obj.hasOwnProperty(prop) && obj[prop];\n }\n\n /**\n * Creates constructor function which allows\n * initialization without usage of a 'new' operator.\n *\n * @param {Object} protoProps - Prototypal properties of a new constructor.\n * @param {Function} constructor\n * @returns {Function} Created constructor.\n */\n function createConstructor(protoProps, constructor) {\n var UiClass = constructor;\n\n if (!UiClass) {\n\n /**\n * Default constructor function.\n */\n UiClass = function () {\n var obj = this;\n\n if (!_.isObject(obj) || Object.getPrototypeOf(obj) !== UiClass.prototype) {\n obj = Object.create(UiClass.prototype);\n }\n\n obj.initialize.apply(obj, arguments);\n\n return obj;\n };\n }\n\n UiClass.prototype = protoProps;\n UiClass.prototype.constructor = UiClass;\n\n return UiClass;\n }\n\n Class = createConstructor({\n\n /**\n * Entry point to the initialization of constructor's instance.\n *\n * @param {Object} [options={}]\n * @returns {Class} Chainable.\n */\n initialize: function (options) {\n this.initConfig(options);\n\n return this;\n },\n\n /**\n * Recursively extends data specified in constructors' 'defaults'\n * property with provided options object. Evaluates resulting\n * object using string templates (see: mage/utils/template.js).\n *\n * @param {Object} [options={}]\n * @returns {Class} Chainable.\n */\n initConfig: function (options) {\n var defaults = this.constructor.defaults,\n config = utils.extend({}, defaults, options || {}),\n ignored = config.ignoreTmpls || {},\n cached = utils.omit(config, ignored);\n\n config = utils.template(config, this, false, true);\n\n _.each(cached, function (value, key) {\n utils.nested(config, key, value);\n });\n\n return _.extend(this, config);\n }\n });\n\n _.extend(Class, {\n defaults: {\n ignoreTmpls: {\n templates: true\n }\n },\n\n /**\n * Creates new constructor based on a current prototype properties,\n * extending them with properties specified in 'exender' object.\n *\n * @param {Object} [extender={}]\n * @returns {Function} New constructor.\n */\n extend: function (extender) {\n var parent = this,\n parentProto = parent.prototype,\n childProto = Object.create(parentProto),\n child = createConstructor(childProto, getOwn(extender, 'constructor')),\n defaults;\n\n extender = extender || {};\n defaults = extender.defaults;\n\n delete extender.defaults;\n\n _.each(extender, function (method, name) {\n childProto[name] = wrapper.wrapSuper(parentProto[name], method);\n });\n\n child.defaults = utils.extend({}, parent.defaults || {});\n\n if (defaults) {\n utils.extend(child.defaults, defaults);\n extender.defaults = defaults;\n }\n\n return _.extend(child, {\n __super__: parentProto,\n extend: parent.extend\n });\n }\n });\n\n return Class;\n});\n","Magento_Ui/js/lib/core/collection.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'underscore',\n 'mageUtils',\n 'uiRegistry',\n 'uiElement'\n], function (_, utils, registry, Element) {\n 'use strict';\n\n /**\n * Removes non plain object items from the specified array.\n *\n * @param {Array} container - Array whose value should be filtered.\n * @returns {Array}\n */\n function compact(container) {\n return _.values(container).filter(utils.isObject);\n }\n\n /**\n * Defines index of an item in a specified container.\n *\n * @param {*} item - Item whose index should be defined.\n * @param {Array} container - Container upon which to perform search.\n * @returns {Number}\n */\n function _findIndex(item, container) {\n var index = _.findKey(container, function (value) {\n return value === item;\n });\n\n if (typeof index === 'undefined') {\n index = _.findKey(container, function (value) {\n return value && value.name === item;\n });\n }\n\n return typeof index === 'undefined' ? -1 : index;\n }\n\n /**\n * Inserts specified item into container at a specified position.\n *\n * @param {*} item - Item to be inserted into container.\n * @param {Array} container - Container of items.\n * @param {*} [position=-1] - Position at which item should be inserted.\n * Position can represent:\n * - specific index in container\n * - item which might already be present in container\n * - structure with one of these properties: after, before\n * @returns {Boolean|*}\n * - true if element has changed its' position\n * - false if nothing has changed\n * - inserted value if it wasn't present in container\n */\n function _insertAt(item, container, position) {\n var currentIndex = _findIndex(item, container),\n newIndex,\n target;\n\n if (typeof position === 'undefined') {\n position = -1;\n } else if (typeof position === 'string') {\n position = isNaN(+position) ? position : +position;\n }\n\n newIndex = position;\n\n if (~currentIndex) {\n target = container.splice(currentIndex, 1)[0];\n\n if (typeof item === 'string') {\n item = target;\n }\n }\n\n if (typeof position !== 'number') {\n target = position.after || position.before || position;\n\n newIndex = _findIndex(target, container);\n\n if (~newIndex && (position.after || newIndex >= currentIndex)) {\n newIndex++;\n }\n }\n\n if (newIndex < 0) {\n newIndex += container.length + 1;\n }\n\n container[newIndex] ?\n container.splice(newIndex, 0, item) :\n container[newIndex] = item;\n\n return !~currentIndex ? item : currentIndex !== newIndex;\n }\n\n return Element.extend({\n defaults: {\n template: 'ui/collection',\n _elems: [],\n ignoreTmpls: {\n childDefaults: true\n }\n },\n\n /**\n * Initializes observable properties.\n *\n * @returns {Model} Chainable.\n */\n initObservable: function () {\n this._super()\n .observe({\n elems: []\n });\n\n return this;\n },\n\n /**\n * Called when another element was added to current component.\n *\n * @param {Object} elem - Instance of an element that was added.\n * @returns {Collection} Chainable.\n */\n initElement: function (elem) {\n elem.initContainer(this);\n\n return this;\n },\n\n /**\n * Returns instance of a child found by provided index.\n *\n * @param {String} index - Index of a child.\n * @returns {Object}\n */\n getChild: function (index) {\n return _.findWhere(this.elems(), {\n index: index\n });\n },\n\n /**\n * Requests specified components to insert\n * them into 'elems' array starting from provided position.\n *\n * @param {(String|Array)} elems - Name of the component to insert.\n * @param {Number} [position=-1] - Position at which to insert elements.\n * @returns {Collection} Chainable.\n */\n insertChild: function (elems, position) {\n var container = this._elems,\n insert = this._insert.bind(this),\n update;\n\n if (!Array.isArray(elems)) {\n elems = [elems];\n }\n\n elems.map(function (item) {\n return item.elem ?\n _insertAt(item.elem, container, item.position) :\n _insertAt(item, container, position);\n }).forEach(function (item) {\n if (item === true) {\n update = true;\n } else if (_.isString(item)) {\n registry.get(item, insert);\n } else if (utils.isObject(item)) {\n insert(item);\n }\n });\n\n if (update) {\n this._updateCollection();\n }\n\n return this;\n },\n\n /**\n * Removes specified child from collection.\n *\n * @param {(Object|String)} elem - Child or index of a child to be removed.\n * @param {Boolean} skipUpdate - skip collection update when element to be destroyed.\n *\n * @returns {Collection} Chainable.\n */\n removeChild: function (elem, skipUpdate) {\n if (_.isString(elem)) {\n elem = this.getChild(elem);\n }\n\n if (elem) {\n utils.remove(this._elems, elem);\n\n if (!skipUpdate) {\n this._updateCollection();\n }\n }\n\n return this;\n },\n\n /**\n * Destroys collection children with its' elements.\n */\n destroyChildren: function () {\n this.elems.each(function (elem) {\n elem.destroy(true);\n });\n\n this._updateCollection();\n },\n\n /**\n * Clear data. Call method \"clear\"\n * in child components\n *\n * @returns {Object} Chainable.\n */\n clear: function () {\n var elems = this.elems();\n\n _.each(elems, function (elem) {\n if (_.isFunction(elem.clear)) {\n elem.clear();\n }\n }, this);\n\n return this;\n },\n\n /**\n * Checks if specified child exists in collection.\n *\n * @param {String} index - Index of a child.\n * @returns {Boolean}\n */\n hasChild: function (index) {\n return !!this.getChild(index);\n },\n\n /**\n * Creates 'async' wrapper for the specified child\n * using uiRegistry 'async' method and caches it\n * in a '_requested' components object.\n *\n * @param {String} index - Index of a child.\n * @returns {Function} Async module wrapper.\n */\n requestChild: function (index) {\n var name = this.formChildName(index);\n\n return this.requestModule(name);\n },\n\n /**\n * Creates complete child name based on a provided index.\n *\n * @param {String} index - Index of a child.\n * @returns {String}\n */\n formChildName: function (index) {\n return this.name + '.' + index;\n },\n\n /**\n * Retrieves requested region.\n * Creates region if it was not created yet\n *\n * @returns {ObservableArray}\n */\n getRegion: function (name) {\n var regions = this.regions = this.regions || {};\n\n if (!regions[name]) {\n regions[name] = [];\n\n this.observe.call(regions, name);\n }\n\n return regions[name];\n },\n\n /**\n * Checks if the specified region has any elements\n * associated with it.\n *\n * @param {String} name\n * @returns {Boolean}\n */\n regionHasElements: function (name) {\n var region = this.getRegion(name);\n\n return region().length > 0;\n },\n\n /**\n * Replaces specified regions' data with a provided one.\n * Creates region if it was not created yet.\n *\n * @param {Array} items - New regions' data.\n * @param {String} name - Name of the region.\n * @returns {Collection} Chainable.\n */\n updateRegion: function (items, name) {\n this.getRegion(name)(items);\n\n return this;\n },\n\n /**\n * Destroys collection along with its' elements.\n */\n destroy: function () {\n this._super();\n\n this.elems.each('destroy');\n },\n\n /**\n * Inserts provided component into 'elems' array at a specified position.\n * @private\n *\n * @param {Object} elem - Element to insert.\n */\n _insert: function (elem) {\n var index = _.findKey(this._elems, function (value) {\n return value === elem.name;\n });\n\n if (typeof index !== 'undefined') {\n this._elems[index] = elem;\n }\n\n this._updateCollection()\n .initElement(elem);\n },\n\n /**\n * Synchronizes multiple elements arrays with a core '_elems' container.\n * Performs elemets grouping by theirs 'displayArea' property.\n * @private\n *\n * @returns {Collection} Chainable.\n */\n _updateCollection: function () {\n var _elems = compact(this._elems),\n grouped;\n\n grouped = _elems.filter(function (elem) {\n return elem.displayArea && _.isString(elem.displayArea);\n });\n grouped = _.groupBy(grouped, 'displayArea');\n\n _.each(grouped, this.updateRegion, this);\n\n _.each(this.regions, function (items) {\n var hasObsoleteComponents = items().length && !_.intersection(_elems, items()).length;\n\n if (hasObsoleteComponents) {\n items.removeAll();\n }\n });\n\n this.elems(_elems);\n\n return this;\n },\n\n /**\n * Tries to call specified method of a current component,\n * otherwise delegates attempt to its' children.\n *\n * @param {String} target - Name of the method.\n * @param {...*} parameters - Arguments that will be passed to method.\n * @returns {*} Result of the method calls.\n */\n delegate: function (target) {\n var args = _.toArray(arguments);\n\n target = this[target];\n\n if (_.isFunction(target)) {\n return target.apply(this, args.slice(1));\n }\n\n return this._delegate(args);\n },\n\n /**\n * Calls 'delegate' method of all of it's children components.\n * @private\n *\n * @param {Array} args - An array of arguments to pass to the next delegation call.\n * @returns {Array} An array of delegation results.\n */\n _delegate: function (args) {\n var result;\n\n result = this.elems.map(function (elem) {\n var target;\n\n if (!_.isFunction(elem.delegate)) {\n target = elem[args[0]];\n\n if (_.isFunction(target)) {\n return target.apply(elem, args.slice(1));\n }\n } else {\n return elem.delegate.apply(elem, args);\n }\n });\n\n return _.flatten(result);\n }\n });\n});\n","Magento_Ui/js/lib/core/storage/local.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\ndefine([\n 'underscore',\n 'uiRegistry',\n 'mageUtils',\n 'uiEvents'\n], function (_, registry, utils, EventsBus) {\n 'use strict';\n\n var root = 'appData',\n localStorage,\n hasSupport,\n storage;\n\n /**\n * Flag which indicates whether localStorage is supported.\n */\n hasSupport = (function () {\n var key = '_storageSupported';\n\n try {\n localStorage = window.localStorage;\n localStorage.setItem(key, 'true');\n\n if (localStorage.getItem(key) === 'true') {\n localStorage.removeItem(key);\n\n return true;\n }\n\n return false;\n } catch (e) {\n return false;\n }\n })();\n\n if (!hasSupport) {\n localStorage = {\n _data: {},\n\n /**\n * Sets value of the specified item.\n *\n * @param {String} key - Key of the property.\n * @param {*} value - Properties' value.\n */\n setItem: function (key, value) {\n this._data[key] = value + '';\n },\n\n /**\n * Retrieves specified item.\n *\n * @param {String} key - Key of the property to be retrieved.\n */\n getItem: function (key) {\n return this._data[key];\n },\n\n /**\n * Removes specified item.\n *\n * @param {String} key - Key of the property to be removed.\n */\n removeItem: function (key) {\n delete this._data[key];\n },\n\n /**\n * Removes all items.\n */\n clear: function () {\n this._data = {};\n }\n };\n }\n\n /**\n * Extracts and parses data stored in localStorage by the\n * key specified in 'root' variable.\n *\n * @returns {Object}\n */\n function getRoot() {\n var data = localStorage.getItem(root),\n result = {};\n\n if (!_.isNull(data) && typeof data != 'undefined') {\n result = JSON.parse(data);\n }\n\n return result;\n }\n\n /**\n * Writes provided data to the localStorage.\n *\n * @param {*} data - Data to be stored.\n */\n function setRoot(data) {\n localStorage.setItem(root, JSON.stringify(data));\n }\n\n /**\n * Provides methods to work with a localStorage\n * as a single nested structure.\n */\n storage = _.extend({\n\n /**\n * Retrieves value of the specified property.\n *\n * @param {String} path - Path to the property.\n *\n * @example Retrieving data.\n * localStorage =>\n * 'appData' => '\n * \"one\": {\"two\": \"three\"}\n * '\n * storage.get('one.two')\n * => \"three\"\n *\n * storage.get('one')\n * => {\"two\": \"three\"}\n */\n get: function (path) {\n var data = getRoot();\n\n return utils.nested(data, path);\n },\n\n /**\n * Sets specified data to the localStorage.\n *\n * @param {String} path - Path of the property.\n * @param {*} value - Value of the property.\n *\n * @example Setting data.\n * storage.set('one.two', 'four');\n * => localStorage =>\n * 'appData' => '\n * \"one\": {\"two\": \"four\"}\n * '\n */\n set: function (path, value) {\n var data = getRoot();\n\n utils.nested(data, path, value);\n\n setRoot(data);\n },\n\n /**\n * Removes specified data from the localStorage.\n *\n * @param {String} path - Path to the property that should be removed.\n *\n * @example Removing data.\n * storage.remove('one.two', 'four');\n * => localStorage =>\n * 'appData' => '\n * \"one\": {}\n * '\n */\n remove: function (path) {\n var data = getRoot();\n\n utils.nestedRemove(data, path);\n\n setRoot(data);\n }\n }, EventsBus);\n\n registry.set('localStorage', storage);\n\n return storage;\n});\n","Magento_Ui/js/lib/core/element/element.js":"/**\n * Copyright \u00a9 Magento, Inc. All rights reserved.\n * See COPYING.txt for license details.\n */\n\n/**\n * @api\n */\ndefine([\n 'ko',\n 'underscore',\n 'mageUtils',\n 'uiRegistry',\n 'uiEvents',\n 'uiClass',\n './links',\n '../storage/local'\n], function (ko, _, utils, registry, Events, Class, links) {\n 'use strict';\n\n var Element;\n\n /**\n * Creates observable property using knockouts'\n * 'observableArray' or 'observable' methods,\n * depending on a type of 'value' parameter.\n *\n * @param {Object} obj - Object to whom property belongs.\n * @param {String} key - Key of the property.\n * @param {*} value - Initial value.\n */\n function observable(obj, key, value) {\n var method = Array.isArray(value) ? 'observableArray' : 'observable';\n\n if (_.isFunction(obj[key]) && !ko.isObservable(obj[key])) {\n return;\n }\n\n if (ko.isObservable(value)) {\n value = value();\n }\n\n ko.isObservable(obj[key]) ?\n obj[key](value) :\n obj[key] = ko[method](value);\n }\n\n /**\n * Creates observable property using 'track' method.\n *\n * @param {Object} obj - Object to whom property belongs.\n * @param {String} key - Key of the property.\n * @param {*} value - Initial value.\n */\n function accessor(obj, key, value) {\n if (_.isFunction(obj[key]) || ko.isObservable(obj[key])) {\n return;\n }\n\n obj[key] = value;\n\n if (!ko.es5.isTracked(obj, key)) {\n ko.track(obj, [key]);\n }\n }\n\n Element = _.extend({\n defaults: {\n _requested: {},\n containers: [],\n exports: {},\n imports: {},\n links: {},\n listens: {},\n name: '',\n ns: '${ $.name.split(\".\")[0] }',\n provider: '',\n registerNodes: true,\n source: null,\n statefull: {},\n template: '',\n tracks: {},\n storageConfig: {\n provider: 'localStorage',\n namespace: '${ $.name }',\n path: '${ $.storageConfig.provider }:${ $.storageConfig.namespace }'\n },\n maps: {\n imports: {},\n exports: {}\n },\n modules: {\n storage: '${ $.storageConfig.provider }'\n }\n },\n\n /**\n * Initializes model instance.\n *\n * @returns {Element} Chainable.\n */\n initialize: function () {\n this._super()\n .initObservable()\n .initModules()\n .initStatefull()\n .initLinks()\n .initUnique();\n\n return this;\n },\n\n /**\n * Initializes observable properties.\n *\n * @returns {Element} Chainable.\n */\n initObservable: function () {\n _.each(this.tracks, function (enabled, key) {\n if (enabled) {\n this.track(key);\n }\n }, this);\n\n return this;\n },\n\n /**\n * Parses 'modules' object and creates\n * async wrappers for specified components.\n *\n * @returns {Element} Chainable.\n */\n initModules: function () {\n _.each(this.modules, function (name, property) {\n if (name) {\n this[property] = this.requestModule(name);\n }\n }, this);\n\n if (!_.isFunction(this.source)) {\n this.source = registry.get(this.provider);\n }\n\n return this;\n },\n\n /**\n * Called when current element was injected to another component.\n *\n * @param {Object} parent - Instance of a 'parent' component.\n * @returns {Collection} Chainable.\n */\n initContainer: function (parent) {\n this.containers.push(parent);\n\n return this;\n },\n\n /**\n * Initializes statefull properties\n * based on the keys of 'statefull' object.\n *\n * @returns {Element} Chainable.\n */\n initStatefull: function () {\n _.each(this.statefull, function (path, key) {\n if (path) {\n this.setStatefull(key, path);\n }\n }, this);\n\n return this;\n },\n\n /**\n * Initializes links between properties.\n *\n * @returns {Element} Chainbale.\n */\n initLinks: function () {\n return this.setListeners(this.listens)\n .setLinks(this.links, 'imports')\n .setLinks(this.links, 'exports')\n .setLinks(this.exports, 'exports')\n .setLinks(this.imports, 'imports');\n },\n\n /**\n * Initializes listeners of the unique property.\n *\n * @returns {Element} Chainable.\n */\n initUnique: function () {\n var update = this.onUniqueUpdate.bind(this),\n uniqueNs = this.uniqueNs;\n\n this.hasUnique = this.uniqueProp && uniqueNs;\n\n if (this.hasUnique) {\n this.source.on(uniqueNs, update, this.name);\n }\n\n return this;\n },\n\n /**\n * Makes specified property to be stored automatically.\n *\n * @param {String} key - Name of the property\n * that will be stored.\n * @param {String} [path=key] - Path to the property in storage.\n * @returns {Element} Chainable.\n */\n setStatefull: function (key, path) {\n var link = {};\n\n path = !_.isString(path) || !path ? key : path;\n link[key] = this.storageConfig.path + '.' + path;\n\n this.setLinks(link, 'imports')\n .setLinks(link, 'exports');\n\n return this;\n },\n\n /**\n * Updates property specified in uniqueNs\n * if elements' unique property is set to 'true'.\n *\n * @returns {Element} Chainable.\n */\n setUnique: function () {\n var property = this.uniqueProp;\n\n if (this[property]()) {\n this.source.set(this.uniqueNs, this.name);\n }\n\n return this;\n },\n\n /**\n * Creates 'async' wrapper for the specified component\n * using uiRegistry 'async' method and caches it\n * in a '_requested' components object.\n *\n * @param {String} name - Name of requested component.\n * @returns {Function} Async module wrapper.\n */\n requestModule: function (name) {\n var requested = this._requested;\n\n if (!requested[name]) {\n requested[name] = registry.async(name);\n }\n\n return requested[name];\n },\n\n /**\n * Returns path to elements' template.\n *\n * @returns {String}\n */\n getTemplate: function () {\n return this.template;\n },\n\n /**\n * Checks if template was specified for an element.\n *\n * @returns {Boolean}\n */\n hasTemplate: function () {\n return !!this.template;\n },\n\n /**\n * Returns value of the nested property.\n *\n * @param {String} path - Path to the property.\n * @returns {*} Value of the property.\n */\n get: function (path) {\n return utils.nested(this, path);\n },\n\n /**\n * Sets provided value as a value of the specified nested property.\n * Triggers changes notifications, if value has mutated.\n *\n * @param {String} path - Path to property.\n * @param {*} value - New value of the property.\n * @returns {Element} Chainable.\n */\n set: function (path, value) {\n var data = this.get(path),\n diffs;\n\n diffs = !_.isFunction(data) && !this.isTracked(path) ?\n utils.compare(data, value, path) :\n false;\n\n utils.nested(this, path, value);\n\n if (diffs) {\n this._notifyChanges(diffs);\n }\n\n return this;\n },\n\n /**\n * Removes nested property from the object.\n *\n * @param {String} path - Path to the property.\n * @returns {Element} Chainable.\n */\n remove: function (path) {\n var data = utils.nested(this, path),\n diffs;\n\n if (_.isUndefined(data) || _.isFunction(data)) {\n return this;\n }\n\n diffs = utils.compare(data, undefined, path);\n\n utils.nestedRemove(this, path);\n\n this._notifyChanges(diffs);\n\n return this;\n },\n\n /**\n * Creates observable properties for the current object.\n *\n * If 'useTrack' flag is set to 'true' then each property will be\n * created with a ES5 get/set accessor descriptors, instead of\n * making them an observable functions.\n * See 'knockout-es5' library for more information.\n *\n * @param {Boolean} [useAccessors=false] - Whether to create an\n * observable function or to use property accesessors.\n * @param {(Object|String|Array)} properties - List of observable properties.\n * @returns {Element} Chainable.\n *\n * @example Sample declaration and equivalent knockout methods.\n * this.key = 'value';\n * this.array = ['value'];\n *\n * this.observe(['key', 'array']);\n * =>\n * this.key = ko.observable('value');\n * this.array = ko.observableArray(['value']);\n *\n * @example Another syntaxes of the previous example.\n * this.observe({\n * key: 'value',\n * array: ['value']\n * });\n */\n observe: function (useAccessors, properties) {\n var model = this,\n trackMethod;\n\n if (typeof useAccessors !== 'boolean') {\n properties = useAccessors;\n useAccessors = false;\n }\n\n trackMethod = useAccessors ? accessor : observable;\n\n if (_.isString(properties)) {\n properties = properties.split(' ');\n }\n\n if (Array.isArray(properties)) {\n properties.forEach(function (key) {\n trackMethod(model, key, model[key]);\n });\n } else if (typeof properties === 'object') {\n _.each(properties, function (value, key) {\n trackMethod(model, key, value);\n });\n }\n\n return this;\n },\n\n /**\n * Delegates call to 'observe' method but\n * with a predefined 'useAccessors' flag.\n *\n * @param {(String|Array|Object)} properties - List of observable properties.\n * @returns {Element} Chainable.\n */\n track: function (properties) {\n this.observe(true, properties);\n\n return this;\n },\n\n /**\n * Checks if specified property is tracked.\n *\n * @param {String} property - Property to be checked.\n * @returns {Boolean}\n */\n isTracked: function (property) {\n return ko.es5.isTracked(this, property);\n },\n\n /**\n * Invokes subscribers for the provided changes.\n *\n * @param {Object} diffs - Object with changes descriptions.\n * @returns {Element} Chainable.\n */\n _notifyChanges: function (diffs) {\n diffs.changes.forEach(function (change) {\n this.trigger(change.path, change.value, change);\n }, this);\n\n _.each(diffs.containers, function (changes, name) {\n var value = utils.nested(this, name);\n\n this.trigger(name, value, changes);\n }, this);\n\n return this;\n },\n\n /**\n * Extracts all stored data and sets it to element.\n *\n * @returns {Element} Chainable.\n */\n restore: function () {\n var ns = this.storageConfig.namespace,\n storage = this.storage();\n\n if (storage) {\n utils.extend(this, storage.get(ns));\n }\n\n return this;\n },\n\n /**\n * Stores value of the specified property in components' storage module.\n *\n * @param {String} property\n * @param {*} [data=this[property]]\n * @returns {Element} Chainable.\n */\n store: function (property, data) {\n var ns = this.storageConfig.namespace,\n path = utils.fullPath(ns, property);\n\n if (arguments.length < 2) {\n data = this.get(property);\n }\n\n this.storage('set', path, data);\n\n return this;\n },\n\n /**\n * Extracts specified property from storage.\n *\n * @param {String} [property] - Name of the property\n * to be extracted. If not specified then all of the\n * stored will be returned.\n * @returns {*}\n */\n getStored: function (property) {\n var ns = this.storageConfig.namespace,\n path = utils.fullPath(ns, property),\n storage = this.storage(),\n data;\n\n if (storage) {\n data = storage.get(path);\n }\n\n return data;\n },\n\n /**\n * Removes stored property.\n *\n * @param {String} property - Property to be removed from storage.\n * @returns {Element} Chainable.\n */\n removeStored: function (property) {\n var ns = this.storageConfig.namespace,\n path = utils.fullPath(ns, property);\n\n this.storage('remove', path);\n\n return this;\n },\n\n /**\n * Destroys current instance along with all of its' children.\n * @param {Boolean} skipUpdate - skip collection update when element to be destroyed.\n */\n destroy: function (skipUpdate) {\n this._dropHandlers()\n ._clearRefs(skipUpdate);\n },\n\n /**\n * Removes events listeners.\n * @private\n *\n * @returns {Element} Chainable.\n */\n _dropHandlers: function () {\n this.off();\n\n if (_.isFunction(this.source)) {\n this.source().off(this.name);\n } else if (this.source) {\n this.source.off(this.name);\n }\n\n return this;\n },\n\n /**\n * Removes all references to current instance and\n * calls 'destroy' method on all of its' children.\n * @private\n * @param {Boolean} skipUpdate - skip collection update when element to be destroyed.\n *\n * @returns {Element} Chainable.\n */\n _clearRefs: function (skipUpdate) {\n registry.remove(this.name);\n\n this.containers.forEach(function (parent) {\n parent.removeChild(this, skipUpdate);\n }, this);\n\n return this;\n },\n\n /**\n * Overrides 'EventsBus.trigger' method to implement events bubbling.\n *\n * @param {...*} arguments - Any number of arguments that should be passed to the events' handler.\n * @returns {Boolean} False if event bubbling was canceled.\n */\n bubble: function () {\n var args = _.toArray(arguments),\n bubble = this.trigger.apply(this, args),\n result;\n\n if (!bubble) {\n return false;\n }\n\n this.containers.forEach(function (parent) {\n result = parent.bubble.apply(parent, args);\n\n if (result === false) {\n bubble = false;\n }\n });\n\n return !!bubble;\n },\n\n /**\n * Callback which fires when property under uniqueNs has changed.\n */\n onUniqueUpdate: function (name) {\n var active = name === this.name,\n property = this.uniqueProp;\n\n this[property](active);\n },\n\n /**\n * Clean data form data source.\n *\n * @returns {Element}\n */\n cleanData: function () {\n if (this.source && this.source.componentType === 'dataSource') {\n if (this.elems) {\n _.each(this.elems(), function (val) {\n val.cleanData();\n });\n } else {\n this.source.remove(this.dataScope);\n }\n }\n\n return this;\n },\n\n /**\n * Fallback data.\n */\n cacheData: function () {\n this.cachedComponent = utils.copy(this);\n },\n\n /**\n * Update configuration in component.\n *\n * @param {*} oldValue\n * @param {*} newValue\n * @param {String} path - path to value.\n * @returns {Element}\n */\n updateConfig: function (oldValue, newValue, path) {\n var names = path.split('.'),\n index = _.lastIndexOf(names, 'config') + 1;\n\n names = names.splice(index, names.length - index).join('.');\n this.set(names, newValue);\n\n return this;\n }\n }, Events, links);\n\n return Class.extend(Element);\n});\n"}
}});