{ "version": 3, "sources": ["../../node_modules/tinycolor2/esm/tinycolor.js", "../../node_scripts/bundle/esbuild/inject/tinycolor-inject.js", "../../scripts/_common/carousel/styles/carousel.scss", "../../scripts/_common/carousel/carouselNative.js", "../../scripts/_common/carousel/services/carouselService.js", "../../scripts/_common/carousel/directives/carouselDirectives.js", "../../scripts/_common/carousel/controllers/carouselController.js", "../../scripts/_common/carousel/carousel.module.js", "../../scripts/_common/rating/styles/rating.scss", "../../scripts/_common/rating/directives/ratingDirectives.js", "../../scripts/_common/rating/controllers/ratingController.js", "../../scripts/_common/rating/rating.module.js", "../../scripts/_common/rotate/screenfull.cjs", "../../scripts/_common/rotate/threesixty.js", "../../scripts/_common/rotate/styles/rotate.scss", "../../scripts/_common/rotate/controllers/rotateController.js", "../../scripts/_common/rotate/directives/rotateDirectives.js", "../../scripts/_common/rotate/rotate.module.js", "../../scripts/_common/lozad-adv/lozadAdv.constants.ts", "../../scripts/_common/lozad-adv/lozadAdv.ctrl.ts", "../../scripts/_common/lozad-adv/lozadAdv.directive.ts", "../../node_modules/mimic-function/index.js", "../../node_modules/debounce-fn/index.js", "../../scripts/_common/lozad-adv/lozadAdv.service.ts", "../../scripts/_common/lozad-adv/lozadAdv.module.js", "../../scripts/_common/iframe-responsive/styles/iframe-responsive.scss", "../../scripts/_common/iframe-responsive/controllers/iframeResponsiveController.js", "../../scripts/_common/iframe-responsive/templates/iframeResponsiveTemplates.js", "../../scripts/_common/iframe-responsive/directives/iframeResponsiveDirective.js", "../../scripts/_common/iframe-responsive/services/iframeResponsiveService.js", "../../scripts/_common/iframe-responsive/iframeResponsive.module.js", "../../scripts/_partials/videos/controllers/videosController.js", "../../scripts/_partials/videos/directives/videosDirective.js", "../../scripts/_partials/videos/videos.module.js", "../../scripts/_common/zoomer/styles/zoomer.scss", "../../scripts/_common/zoomer/controllers/zoomerController.js", "../../scripts/_common/zoomer/directives/zoomerDirectives.js", "../../scripts/_common/zoomer/zoomer.module.js", "../../scripts/_partials/custom-options/styles/customOptions.scss", "../../scripts/_partials/custom-options/controllers/customOptionsController.js", "../../scripts/_partials/custom-options/directives/customOptionsDirectives.js", "../../scripts/_partials/custom-options/services/customOptionsService.js", "../../scripts/_partials/custom-options/customOptions.module.js", "../../scripts/_partials/colors-viewer/styles/colors-viewer.scss", "../../scripts/_partials/colors-viewer/controllers/colorsViewerController.js", "../../scripts/_partials/colors-viewer/directives/colorsViewerDirectives.js", "../../scripts/_partials/colors-viewer/colorsViewer.module.js", "../../scripts/_partials/sizes-viewer/styles/sizes-viewer.scss", "../../scripts/_partials/sizes-viewer/controllers/sizesViewerController.js", "../../scripts/_partials/sizes-viewer/directives/sizesViewerDirectives.js", "../../scripts/_partials/sizes-viewer/sizesViewer.module.js", "../../scripts/_partials/buy-one-click/styles/buyOneClick.scss", "../../scripts/_partials/buy-one-click/controllers/buyOneClickTriggerController.js", "../../scripts/_partials/buy-one-click/controllers/buyOneClickFormController.js", "../../scripts/_partials/buy-one-click/directives/buyOneClickDirectives.js", "../../scripts/_common/PubSub/PubSub.js", "../../scripts/_partials/buy-one-click/services/buyOneClickService.js", "../../scripts/_partials/buy-one-click/buyOneClick.module.js", "../../scripts/_partials/pre-order/styles/styles.scss", "../../scripts/_partials/pre-order/controllers/preOrderTriggerController.js", "../../scripts/_partials/pre-order/controllers/preOrderFormController.js", "../../scripts/_partials/pre-order/directives/preOrderDirectives.js", "../../scripts/_partials/pre-order/services/preOrderService.js", "../../scripts/_partials/pre-order/preOrder.module.js", "../../styles/partials/gallery.scss", "../../styles/partials/product-color.scss", "../../styles/views/product.scss", "../../scripts/product/controllers/productController.js", "../../scripts/product/services/productService.js", "../../scripts/product/productQuickview.module.js", "../../node_modules/angular-ui-bootstrap/src/tooltip/tooltip.css", "../../node_modules/angular-ui-bootstrap/src/position/position.js", "../../node_modules/angular-ui-bootstrap/src/position/index-nocss.js", "../../node_modules/angular-ui-bootstrap/src/stackedMap/stackedMap.js", "../../node_modules/angular-ui-bootstrap/src/stackedMap/index.js", "../../node_modules/angular-ui-bootstrap/template/tooltip/tooltip-popup.html.js", "../../node_modules/angular-ui-bootstrap/template/tooltip/tooltip-html-popup.html.js", "../../node_modules/angular-ui-bootstrap/template/tooltip/tooltip-template-popup.html.js", "../../node_modules/angular-ui-bootstrap/src/tooltip/tooltip.js", "../../node_modules/angular-ui-bootstrap/src/tooltip/index-nocss.js", "../../node_modules/angular-ui-bootstrap/template/popover/popover.html.js", "../../node_modules/angular-ui-bootstrap/template/popover/popover-html.html.js", "../../node_modules/angular-ui-bootstrap/template/popover/popover-template.html.js", "../../node_modules/angular-ui-bootstrap/src/popover/popover.js", "../../node_modules/angular-ui-bootstrap/src/popover/index-nocss.js", "../../node_modules/angular-ui-bootstrap/src/popover/index.js", "../../bundle_config/catalog.js", "../../scripts/catalog/catalog.module.js", "../../scripts/_partials/product-view/productView.module.js", "../../scripts/_partials/quickview/quickview.module.js", "../../scripts/_partials/quickview/controllers/quickviewController.js", "../../scripts/_partials/quickview/directives/quickviewDirectives.js", "../../scripts/_partials/quickview/services/quickviewService.js", "../../scripts/_partials/price-amount-list/priceAmountList.module.js", "../../scripts/_partials/price-amount-list/controllers/priceAmountListController.js", "../../scripts/_partials/price-amount-list/directives/priceAmountListDirectives.js", "../../scripts/_partials/products-carousel/productsCarousel.module.js", "../../scripts/_partials/products-carousel/controllers/productsCarouselController.js", "../../scripts/_partials/products-carousel/directives/productsCarouselDirectives.js", "../../scripts/_partials/products-carousel/services/productsCarouselService.js", "../../scripts/_partials/photo-view-list/photoViewList.module.js", "../../scripts/_partials/photo-view-list/photo-view-list.ctrl.js", "../../scripts/_partials/photo-view-list/photo-view-list.directive.js", "../../scripts/_partials/product-view/services/productViewService.js", "../../scripts/_partials/product-view/directives/productViewDirectives.js", "../../scripts/_partials/product-view/controllers/productViewCarouselPhotosController.js", "../../scripts/_partials/product-view/controllers/productViewChangeModeController.js", "../../scripts/_partials/product-view/controllers/productViewItemController.js", "../../scripts/_partials/product-view/productViewItem.controls.js", "../../scripts/_partials/product-view/controllers/productViewModeController.js", "../../scripts/_partials/product-view/controllers/productViewImageListController.js", "../../scripts/_partials/product-view/controllers/productViewImageController.js", "../../scripts/_partials/catalog-filter/catalogFilter.module.js", "../../vendors/rangeSlider/rangeSlider.module.js", "../../vendors/rangeSlider/angular.rangeSlider.js", "../../scripts/_common/popover/popover.module.js", "../../scripts/_common/popover/controllers/popoverController.js", "../../scripts/_common/popover/controllers/popoverControlController.js", "../../scripts/_common/popover/controllers/PopoverOverlayController.js", "../../scripts/_common/popover/directives/popoverDirectives.js", "../../scripts/_common/popover/services/popoverService.js", "../../scripts/_partials/catalog-filter/services/catalogFilterService.js", "../../scripts/_partials/catalog-filter/directives/catalogFilterDirectives.js", "../../scripts/_partials/catalog-filter/controllers/catalogFilterController.js", "../../scripts/_partials/catalog-filter/controllers/catalogFilterSortController.js", "../../scripts/catalog/contollers/catalogController.js", "../../scripts/appDependency.js"], "sourcesContent": ["// This file is autogenerated. It's used to publish ESM to npm.\nfunction _typeof(obj) {\n \"@babel/helpers - typeof\";\n\n return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (obj) {\n return typeof obj;\n } : function (obj) {\n return obj && \"function\" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n }, _typeof(obj);\n}\n\n// https://github.com/bgrins/TinyColor\n// Brian Grinstead, MIT License\n\nvar trimLeft = /^\\s+/;\nvar trimRight = /\\s+$/;\nfunction tinycolor(color, opts) {\n color = color ? color : \"\";\n opts = opts || {};\n\n // If input is already a tinycolor, return itself\n if (color instanceof tinycolor) {\n return color;\n }\n // If we are called as a function, call using new instead\n if (!(this instanceof tinycolor)) {\n return new tinycolor(color, opts);\n }\n var rgb = inputToRGB(color);\n this._originalInput = color, this._r = rgb.r, this._g = rgb.g, this._b = rgb.b, this._a = rgb.a, this._roundA = Math.round(100 * this._a) / 100, this._format = opts.format || rgb.format;\n this._gradientType = opts.gradientType;\n\n // Don't let the range of [0,255] come back in [0,1].\n // Potentially lose a little bit of precision here, but will fix issues where\n // .5 gets interpreted as half of the total, instead of half of 1\n // If it was supposed to be 128, this was already taken care of by `inputToRgb`\n if (this._r < 1) this._r = Math.round(this._r);\n if (this._g < 1) this._g = Math.round(this._g);\n if (this._b < 1) this._b = Math.round(this._b);\n this._ok = rgb.ok;\n}\ntinycolor.prototype = {\n isDark: function isDark() {\n return this.getBrightness() < 128;\n },\n isLight: function isLight() {\n return !this.isDark();\n },\n isValid: function isValid() {\n return this._ok;\n },\n getOriginalInput: function getOriginalInput() {\n return this._originalInput;\n },\n getFormat: function getFormat() {\n return this._format;\n },\n getAlpha: function getAlpha() {\n return this._a;\n },\n getBrightness: function getBrightness() {\n //http://www.w3.org/TR/AERT#color-contrast\n var rgb = this.toRgb();\n return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;\n },\n getLuminance: function getLuminance() {\n //http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef\n var rgb = this.toRgb();\n var RsRGB, GsRGB, BsRGB, R, G, B;\n RsRGB = rgb.r / 255;\n GsRGB = rgb.g / 255;\n BsRGB = rgb.b / 255;\n if (RsRGB <= 0.03928) R = RsRGB / 12.92;else R = Math.pow((RsRGB + 0.055) / 1.055, 2.4);\n if (GsRGB <= 0.03928) G = GsRGB / 12.92;else G = Math.pow((GsRGB + 0.055) / 1.055, 2.4);\n if (BsRGB <= 0.03928) B = BsRGB / 12.92;else B = Math.pow((BsRGB + 0.055) / 1.055, 2.4);\n return 0.2126 * R + 0.7152 * G + 0.0722 * B;\n },\n setAlpha: function setAlpha(value) {\n this._a = boundAlpha(value);\n this._roundA = Math.round(100 * this._a) / 100;\n return this;\n },\n toHsv: function toHsv() {\n var hsv = rgbToHsv(this._r, this._g, this._b);\n return {\n h: hsv.h * 360,\n s: hsv.s,\n v: hsv.v,\n a: this._a\n };\n },\n toHsvString: function toHsvString() {\n var hsv = rgbToHsv(this._r, this._g, this._b);\n var h = Math.round(hsv.h * 360),\n s = Math.round(hsv.s * 100),\n v = Math.round(hsv.v * 100);\n return this._a == 1 ? \"hsv(\" + h + \", \" + s + \"%, \" + v + \"%)\" : \"hsva(\" + h + \", \" + s + \"%, \" + v + \"%, \" + this._roundA + \")\";\n },\n toHsl: function toHsl() {\n var hsl = rgbToHsl(this._r, this._g, this._b);\n return {\n h: hsl.h * 360,\n s: hsl.s,\n l: hsl.l,\n a: this._a\n };\n },\n toHslString: function toHslString() {\n var hsl = rgbToHsl(this._r, this._g, this._b);\n var h = Math.round(hsl.h * 360),\n s = Math.round(hsl.s * 100),\n l = Math.round(hsl.l * 100);\n return this._a == 1 ? \"hsl(\" + h + \", \" + s + \"%, \" + l + \"%)\" : \"hsla(\" + h + \", \" + s + \"%, \" + l + \"%, \" + this._roundA + \")\";\n },\n toHex: function toHex(allow3Char) {\n return rgbToHex(this._r, this._g, this._b, allow3Char);\n },\n toHexString: function toHexString(allow3Char) {\n return \"#\" + this.toHex(allow3Char);\n },\n toHex8: function toHex8(allow4Char) {\n return rgbaToHex(this._r, this._g, this._b, this._a, allow4Char);\n },\n toHex8String: function toHex8String(allow4Char) {\n return \"#\" + this.toHex8(allow4Char);\n },\n toRgb: function toRgb() {\n return {\n r: Math.round(this._r),\n g: Math.round(this._g),\n b: Math.round(this._b),\n a: this._a\n };\n },\n toRgbString: function toRgbString() {\n return this._a == 1 ? \"rgb(\" + Math.round(this._r) + \", \" + Math.round(this._g) + \", \" + Math.round(this._b) + \")\" : \"rgba(\" + Math.round(this._r) + \", \" + Math.round(this._g) + \", \" + Math.round(this._b) + \", \" + this._roundA + \")\";\n },\n toPercentageRgb: function toPercentageRgb() {\n return {\n r: Math.round(bound01(this._r, 255) * 100) + \"%\",\n g: Math.round(bound01(this._g, 255) * 100) + \"%\",\n b: Math.round(bound01(this._b, 255) * 100) + \"%\",\n a: this._a\n };\n },\n toPercentageRgbString: function toPercentageRgbString() {\n return this._a == 1 ? \"rgb(\" + Math.round(bound01(this._r, 255) * 100) + \"%, \" + Math.round(bound01(this._g, 255) * 100) + \"%, \" + Math.round(bound01(this._b, 255) * 100) + \"%)\" : \"rgba(\" + Math.round(bound01(this._r, 255) * 100) + \"%, \" + Math.round(bound01(this._g, 255) * 100) + \"%, \" + Math.round(bound01(this._b, 255) * 100) + \"%, \" + this._roundA + \")\";\n },\n toName: function toName() {\n if (this._a === 0) {\n return \"transparent\";\n }\n if (this._a < 1) {\n return false;\n }\n return hexNames[rgbToHex(this._r, this._g, this._b, true)] || false;\n },\n toFilter: function toFilter(secondColor) {\n var hex8String = \"#\" + rgbaToArgbHex(this._r, this._g, this._b, this._a);\n var secondHex8String = hex8String;\n var gradientType = this._gradientType ? \"GradientType = 1, \" : \"\";\n if (secondColor) {\n var s = tinycolor(secondColor);\n secondHex8String = \"#\" + rgbaToArgbHex(s._r, s._g, s._b, s._a);\n }\n return \"progid:DXImageTransform.Microsoft.gradient(\" + gradientType + \"startColorstr=\" + hex8String + \",endColorstr=\" + secondHex8String + \")\";\n },\n toString: function toString(format) {\n var formatSet = !!format;\n format = format || this._format;\n var formattedString = false;\n var hasAlpha = this._a < 1 && this._a >= 0;\n var needsAlphaFormat = !formatSet && hasAlpha && (format === \"hex\" || format === \"hex6\" || format === \"hex3\" || format === \"hex4\" || format === \"hex8\" || format === \"name\");\n if (needsAlphaFormat) {\n // Special case for \"transparent\", all other non-alpha formats\n // will return rgba when there is transparency.\n if (format === \"name\" && this._a === 0) {\n return this.toName();\n }\n return this.toRgbString();\n }\n if (format === \"rgb\") {\n formattedString = this.toRgbString();\n }\n if (format === \"prgb\") {\n formattedString = this.toPercentageRgbString();\n }\n if (format === \"hex\" || format === \"hex6\") {\n formattedString = this.toHexString();\n }\n if (format === \"hex3\") {\n formattedString = this.toHexString(true);\n }\n if (format === \"hex4\") {\n formattedString = this.toHex8String(true);\n }\n if (format === \"hex8\") {\n formattedString = this.toHex8String();\n }\n if (format === \"name\") {\n formattedString = this.toName();\n }\n if (format === \"hsl\") {\n formattedString = this.toHslString();\n }\n if (format === \"hsv\") {\n formattedString = this.toHsvString();\n }\n return formattedString || this.toHexString();\n },\n clone: function clone() {\n return tinycolor(this.toString());\n },\n _applyModification: function _applyModification(fn, args) {\n var color = fn.apply(null, [this].concat([].slice.call(args)));\n this._r = color._r;\n this._g = color._g;\n this._b = color._b;\n this.setAlpha(color._a);\n return this;\n },\n lighten: function lighten() {\n return this._applyModification(_lighten, arguments);\n },\n brighten: function brighten() {\n return this._applyModification(_brighten, arguments);\n },\n darken: function darken() {\n return this._applyModification(_darken, arguments);\n },\n desaturate: function desaturate() {\n return this._applyModification(_desaturate, arguments);\n },\n saturate: function saturate() {\n return this._applyModification(_saturate, arguments);\n },\n greyscale: function greyscale() {\n return this._applyModification(_greyscale, arguments);\n },\n spin: function spin() {\n return this._applyModification(_spin, arguments);\n },\n _applyCombination: function _applyCombination(fn, args) {\n return fn.apply(null, [this].concat([].slice.call(args)));\n },\n analogous: function analogous() {\n return this._applyCombination(_analogous, arguments);\n },\n complement: function complement() {\n return this._applyCombination(_complement, arguments);\n },\n monochromatic: function monochromatic() {\n return this._applyCombination(_monochromatic, arguments);\n },\n splitcomplement: function splitcomplement() {\n return this._applyCombination(_splitcomplement, arguments);\n },\n // Disabled until https://github.com/bgrins/TinyColor/issues/254\n // polyad: function (number) {\n // return this._applyCombination(polyad, [number]);\n // },\n triad: function triad() {\n return this._applyCombination(polyad, [3]);\n },\n tetrad: function tetrad() {\n return this._applyCombination(polyad, [4]);\n }\n};\n\n// If input is an object, force 1 into \"1.0\" to handle ratios properly\n// String input requires \"1.0\" as input, so 1 will be treated as 1\ntinycolor.fromRatio = function (color, opts) {\n if (_typeof(color) == \"object\") {\n var newColor = {};\n for (var i in color) {\n if (color.hasOwnProperty(i)) {\n if (i === \"a\") {\n newColor[i] = color[i];\n } else {\n newColor[i] = convertToPercentage(color[i]);\n }\n }\n }\n color = newColor;\n }\n return tinycolor(color, opts);\n};\n\n// Given a string or object, convert that input to RGB\n// Possible string inputs:\n//\n// \"red\"\n// \"#f00\" or \"f00\"\n// \"#ff0000\" or \"ff0000\"\n// \"#ff000000\" or \"ff000000\"\n// \"rgb 255 0 0\" or \"rgb (255, 0, 0)\"\n// \"rgb 1.0 0 0\" or \"rgb (1, 0, 0)\"\n// \"rgba (255, 0, 0, 1)\" or \"rgba 255, 0, 0, 1\"\n// \"rgba (1.0, 0, 0, 1)\" or \"rgba 1.0, 0, 0, 1\"\n// \"hsl(0, 100%, 50%)\" or \"hsl 0 100% 50%\"\n// \"hsla(0, 100%, 50%, 1)\" or \"hsla 0 100% 50%, 1\"\n// \"hsv(0, 100%, 100%)\" or \"hsv 0 100% 100%\"\n//\nfunction inputToRGB(color) {\n var rgb = {\n r: 0,\n g: 0,\n b: 0\n };\n var a = 1;\n var s = null;\n var v = null;\n var l = null;\n var ok = false;\n var format = false;\n if (typeof color == \"string\") {\n color = stringInputToObject(color);\n }\n if (_typeof(color) == \"object\") {\n if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) {\n rgb = rgbToRgb(color.r, color.g, color.b);\n ok = true;\n format = String(color.r).substr(-1) === \"%\" ? \"prgb\" : \"rgb\";\n } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) {\n s = convertToPercentage(color.s);\n v = convertToPercentage(color.v);\n rgb = hsvToRgb(color.h, s, v);\n ok = true;\n format = \"hsv\";\n } else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.l)) {\n s = convertToPercentage(color.s);\n l = convertToPercentage(color.l);\n rgb = hslToRgb(color.h, s, l);\n ok = true;\n format = \"hsl\";\n }\n if (color.hasOwnProperty(\"a\")) {\n a = color.a;\n }\n }\n a = boundAlpha(a);\n return {\n ok: ok,\n format: color.format || format,\n r: Math.min(255, Math.max(rgb.r, 0)),\n g: Math.min(255, Math.max(rgb.g, 0)),\n b: Math.min(255, Math.max(rgb.b, 0)),\n a: a\n };\n}\n\n// Conversion Functions\n// --------------------\n\n// `rgbToHsl`, `rgbToHsv`, `hslToRgb`, `hsvToRgb` modified from:\n// \n\n// `rgbToRgb`\n// Handle bounds / percentage checking to conform to CSS color spec\n// \n// *Assumes:* r, g, b in [0, 255] or [0, 1]\n// *Returns:* { r, g, b } in [0, 255]\nfunction rgbToRgb(r, g, b) {\n return {\n r: bound01(r, 255) * 255,\n g: bound01(g, 255) * 255,\n b: bound01(b, 255) * 255\n };\n}\n\n// `rgbToHsl`\n// Converts an RGB color value to HSL.\n// *Assumes:* r, g, and b are contained in [0, 255] or [0, 1]\n// *Returns:* { h, s, l } in [0,1]\nfunction rgbToHsl(r, g, b) {\n r = bound01(r, 255);\n g = bound01(g, 255);\n b = bound01(b, 255);\n var max = Math.max(r, g, b),\n min = Math.min(r, g, b);\n var h,\n s,\n l = (max + min) / 2;\n if (max == min) {\n h = s = 0; // achromatic\n } else {\n var d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n switch (max) {\n case r:\n h = (g - b) / d + (g < b ? 6 : 0);\n break;\n case g:\n h = (b - r) / d + 2;\n break;\n case b:\n h = (r - g) / d + 4;\n break;\n }\n h /= 6;\n }\n return {\n h: h,\n s: s,\n l: l\n };\n}\n\n// `hslToRgb`\n// Converts an HSL color value to RGB.\n// *Assumes:* h is contained in [0, 1] or [0, 360] and s and l are contained [0, 1] or [0, 100]\n// *Returns:* { r, g, b } in the set [0, 255]\nfunction hslToRgb(h, s, l) {\n var r, g, b;\n h = bound01(h, 360);\n s = bound01(s, 100);\n l = bound01(l, 100);\n function hue2rgb(p, q, t) {\n if (t < 0) t += 1;\n if (t > 1) t -= 1;\n if (t < 1 / 6) return p + (q - p) * 6 * t;\n if (t < 1 / 2) return q;\n if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;\n return p;\n }\n if (s === 0) {\n r = g = b = l; // achromatic\n } else {\n var q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n var p = 2 * l - q;\n r = hue2rgb(p, q, h + 1 / 3);\n g = hue2rgb(p, q, h);\n b = hue2rgb(p, q, h - 1 / 3);\n }\n return {\n r: r * 255,\n g: g * 255,\n b: b * 255\n };\n}\n\n// `rgbToHsv`\n// Converts an RGB color value to HSV\n// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]\n// *Returns:* { h, s, v } in [0,1]\nfunction rgbToHsv(r, g, b) {\n r = bound01(r, 255);\n g = bound01(g, 255);\n b = bound01(b, 255);\n var max = Math.max(r, g, b),\n min = Math.min(r, g, b);\n var h,\n s,\n v = max;\n var d = max - min;\n s = max === 0 ? 0 : d / max;\n if (max == min) {\n h = 0; // achromatic\n } else {\n switch (max) {\n case r:\n h = (g - b) / d + (g < b ? 6 : 0);\n break;\n case g:\n h = (b - r) / d + 2;\n break;\n case b:\n h = (r - g) / d + 4;\n break;\n }\n h /= 6;\n }\n return {\n h: h,\n s: s,\n v: v\n };\n}\n\n// `hsvToRgb`\n// Converts an HSV color value to RGB.\n// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]\n// *Returns:* { r, g, b } in the set [0, 255]\nfunction hsvToRgb(h, s, v) {\n h = bound01(h, 360) * 6;\n s = bound01(s, 100);\n v = bound01(v, 100);\n var i = Math.floor(h),\n f = h - i,\n p = v * (1 - s),\n q = v * (1 - f * s),\n t = v * (1 - (1 - f) * s),\n mod = i % 6,\n r = [v, q, p, p, t, v][mod],\n g = [t, v, v, q, p, p][mod],\n b = [p, p, t, v, v, q][mod];\n return {\n r: r * 255,\n g: g * 255,\n b: b * 255\n };\n}\n\n// `rgbToHex`\n// Converts an RGB color to hex\n// Assumes r, g, and b are contained in the set [0, 255]\n// Returns a 3 or 6 character hex\nfunction rgbToHex(r, g, b, allow3Char) {\n var hex = [pad2(Math.round(r).toString(16)), pad2(Math.round(g).toString(16)), pad2(Math.round(b).toString(16))];\n\n // Return a 3 character hex if possible\n if (allow3Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1)) {\n return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);\n }\n return hex.join(\"\");\n}\n\n// `rgbaToHex`\n// Converts an RGBA color plus alpha transparency to hex\n// Assumes r, g, b are contained in the set [0, 255] and\n// a in [0, 1]. Returns a 4 or 8 character rgba hex\nfunction rgbaToHex(r, g, b, a, allow4Char) {\n var hex = [pad2(Math.round(r).toString(16)), pad2(Math.round(g).toString(16)), pad2(Math.round(b).toString(16)), pad2(convertDecimalToHex(a))];\n\n // Return a 4 character hex if possible\n if (allow4Char && hex[0].charAt(0) == hex[0].charAt(1) && hex[1].charAt(0) == hex[1].charAt(1) && hex[2].charAt(0) == hex[2].charAt(1) && hex[3].charAt(0) == hex[3].charAt(1)) {\n return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0);\n }\n return hex.join(\"\");\n}\n\n// `rgbaToArgbHex`\n// Converts an RGBA color to an ARGB Hex8 string\n// Rarely used, but required for \"toFilter()\"\nfunction rgbaToArgbHex(r, g, b, a) {\n var hex = [pad2(convertDecimalToHex(a)), pad2(Math.round(r).toString(16)), pad2(Math.round(g).toString(16)), pad2(Math.round(b).toString(16))];\n return hex.join(\"\");\n}\n\n// `equals`\n// Can be called with any tinycolor input\ntinycolor.equals = function (color1, color2) {\n if (!color1 || !color2) return false;\n return tinycolor(color1).toRgbString() == tinycolor(color2).toRgbString();\n};\ntinycolor.random = function () {\n return tinycolor.fromRatio({\n r: Math.random(),\n g: Math.random(),\n b: Math.random()\n });\n};\n\n// Modification Functions\n// ----------------------\n// Thanks to less.js for some of the basics here\n// \n\nfunction _desaturate(color, amount) {\n amount = amount === 0 ? 0 : amount || 10;\n var hsl = tinycolor(color).toHsl();\n hsl.s -= amount / 100;\n hsl.s = clamp01(hsl.s);\n return tinycolor(hsl);\n}\nfunction _saturate(color, amount) {\n amount = amount === 0 ? 0 : amount || 10;\n var hsl = tinycolor(color).toHsl();\n hsl.s += amount / 100;\n hsl.s = clamp01(hsl.s);\n return tinycolor(hsl);\n}\nfunction _greyscale(color) {\n return tinycolor(color).desaturate(100);\n}\nfunction _lighten(color, amount) {\n amount = amount === 0 ? 0 : amount || 10;\n var hsl = tinycolor(color).toHsl();\n hsl.l += amount / 100;\n hsl.l = clamp01(hsl.l);\n return tinycolor(hsl);\n}\nfunction _brighten(color, amount) {\n amount = amount === 0 ? 0 : amount || 10;\n var rgb = tinycolor(color).toRgb();\n rgb.r = Math.max(0, Math.min(255, rgb.r - Math.round(255 * -(amount / 100))));\n rgb.g = Math.max(0, Math.min(255, rgb.g - Math.round(255 * -(amount / 100))));\n rgb.b = Math.max(0, Math.min(255, rgb.b - Math.round(255 * -(amount / 100))));\n return tinycolor(rgb);\n}\nfunction _darken(color, amount) {\n amount = amount === 0 ? 0 : amount || 10;\n var hsl = tinycolor(color).toHsl();\n hsl.l -= amount / 100;\n hsl.l = clamp01(hsl.l);\n return tinycolor(hsl);\n}\n\n// Spin takes a positive or negative amount within [-360, 360] indicating the change of hue.\n// Values outside of this range will be wrapped into this range.\nfunction _spin(color, amount) {\n var hsl = tinycolor(color).toHsl();\n var hue = (hsl.h + amount) % 360;\n hsl.h = hue < 0 ? 360 + hue : hue;\n return tinycolor(hsl);\n}\n\n// Combination Functions\n// ---------------------\n// Thanks to jQuery xColor for some of the ideas behind these\n// \n\nfunction _complement(color) {\n var hsl = tinycolor(color).toHsl();\n hsl.h = (hsl.h + 180) % 360;\n return tinycolor(hsl);\n}\nfunction polyad(color, number) {\n if (isNaN(number) || number <= 0) {\n throw new Error(\"Argument to polyad must be a positive number\");\n }\n var hsl = tinycolor(color).toHsl();\n var result = [tinycolor(color)];\n var step = 360 / number;\n for (var i = 1; i < number; i++) {\n result.push(tinycolor({\n h: (hsl.h + i * step) % 360,\n s: hsl.s,\n l: hsl.l\n }));\n }\n return result;\n}\nfunction _splitcomplement(color) {\n var hsl = tinycolor(color).toHsl();\n var h = hsl.h;\n return [tinycolor(color), tinycolor({\n h: (h + 72) % 360,\n s: hsl.s,\n l: hsl.l\n }), tinycolor({\n h: (h + 216) % 360,\n s: hsl.s,\n l: hsl.l\n })];\n}\nfunction _analogous(color, results, slices) {\n results = results || 6;\n slices = slices || 30;\n var hsl = tinycolor(color).toHsl();\n var part = 360 / slices;\n var ret = [tinycolor(color)];\n for (hsl.h = (hsl.h - (part * results >> 1) + 720) % 360; --results;) {\n hsl.h = (hsl.h + part) % 360;\n ret.push(tinycolor(hsl));\n }\n return ret;\n}\nfunction _monochromatic(color, results) {\n results = results || 6;\n var hsv = tinycolor(color).toHsv();\n var h = hsv.h,\n s = hsv.s,\n v = hsv.v;\n var ret = [];\n var modification = 1 / results;\n while (results--) {\n ret.push(tinycolor({\n h: h,\n s: s,\n v: v\n }));\n v = (v + modification) % 1;\n }\n return ret;\n}\n\n// Utility Functions\n// ---------------------\n\ntinycolor.mix = function (color1, color2, amount) {\n amount = amount === 0 ? 0 : amount || 50;\n var rgb1 = tinycolor(color1).toRgb();\n var rgb2 = tinycolor(color2).toRgb();\n var p = amount / 100;\n var rgba = {\n r: (rgb2.r - rgb1.r) * p + rgb1.r,\n g: (rgb2.g - rgb1.g) * p + rgb1.g,\n b: (rgb2.b - rgb1.b) * p + rgb1.b,\n a: (rgb2.a - rgb1.a) * p + rgb1.a\n };\n return tinycolor(rgba);\n};\n\n// Readability Functions\n// ---------------------\n// false\n// tinycolor.isReadable(\"#000\", \"#111\",{level:\"AA\",size:\"large\"}) => false\ntinycolor.isReadable = function (color1, color2, wcag2) {\n var readability = tinycolor.readability(color1, color2);\n var wcag2Parms, out;\n out = false;\n wcag2Parms = validateWCAG2Parms(wcag2);\n switch (wcag2Parms.level + wcag2Parms.size) {\n case \"AAsmall\":\n case \"AAAlarge\":\n out = readability >= 4.5;\n break;\n case \"AAlarge\":\n out = readability >= 3;\n break;\n case \"AAAsmall\":\n out = readability >= 7;\n break;\n }\n return out;\n};\n\n// `mostReadable`\n// Given a base color and a list of possible foreground or background\n// colors for that base, returns the most readable color.\n// Optionally returns Black or White if the most readable color is unreadable.\n// *Example*\n// tinycolor.mostReadable(tinycolor.mostReadable(\"#123\", [\"#124\", \"#125\"],{includeFallbackColors:false}).toHexString(); // \"#112255\"\n// tinycolor.mostReadable(tinycolor.mostReadable(\"#123\", [\"#124\", \"#125\"],{includeFallbackColors:true}).toHexString(); // \"#ffffff\"\n// tinycolor.mostReadable(\"#a8015a\", [\"#faf3f3\"],{includeFallbackColors:true,level:\"AAA\",size:\"large\"}).toHexString(); // \"#faf3f3\"\n// tinycolor.mostReadable(\"#a8015a\", [\"#faf3f3\"],{includeFallbackColors:true,level:\"AAA\",size:\"small\"}).toHexString(); // \"#ffffff\"\ntinycolor.mostReadable = function (baseColor, colorList, args) {\n var bestColor = null;\n var bestScore = 0;\n var readability;\n var includeFallbackColors, level, size;\n args = args || {};\n includeFallbackColors = args.includeFallbackColors;\n level = args.level;\n size = args.size;\n for (var i = 0; i < colorList.length; i++) {\n readability = tinycolor.readability(baseColor, colorList[i]);\n if (readability > bestScore) {\n bestScore = readability;\n bestColor = tinycolor(colorList[i]);\n }\n }\n if (tinycolor.isReadable(baseColor, bestColor, {\n level: level,\n size: size\n }) || !includeFallbackColors) {\n return bestColor;\n } else {\n args.includeFallbackColors = false;\n return tinycolor.mostReadable(baseColor, [\"#fff\", \"#000\"], args);\n }\n};\n\n// Big List of Colors\n// ------------------\n// \nvar names = tinycolor.names = {\n aliceblue: \"f0f8ff\",\n antiquewhite: \"faebd7\",\n aqua: \"0ff\",\n aquamarine: \"7fffd4\",\n azure: \"f0ffff\",\n beige: \"f5f5dc\",\n bisque: \"ffe4c4\",\n black: \"000\",\n blanchedalmond: \"ffebcd\",\n blue: \"00f\",\n blueviolet: \"8a2be2\",\n brown: \"a52a2a\",\n burlywood: \"deb887\",\n burntsienna: \"ea7e5d\",\n cadetblue: \"5f9ea0\",\n chartreuse: \"7fff00\",\n chocolate: \"d2691e\",\n coral: \"ff7f50\",\n cornflowerblue: \"6495ed\",\n cornsilk: \"fff8dc\",\n crimson: \"dc143c\",\n cyan: \"0ff\",\n darkblue: \"00008b\",\n darkcyan: \"008b8b\",\n darkgoldenrod: \"b8860b\",\n darkgray: \"a9a9a9\",\n darkgreen: \"006400\",\n darkgrey: \"a9a9a9\",\n darkkhaki: \"bdb76b\",\n darkmagenta: \"8b008b\",\n darkolivegreen: \"556b2f\",\n darkorange: \"ff8c00\",\n darkorchid: \"9932cc\",\n darkred: \"8b0000\",\n darksalmon: \"e9967a\",\n darkseagreen: \"8fbc8f\",\n darkslateblue: \"483d8b\",\n darkslategray: \"2f4f4f\",\n darkslategrey: \"2f4f4f\",\n darkturquoise: \"00ced1\",\n darkviolet: \"9400d3\",\n deeppink: \"ff1493\",\n deepskyblue: \"00bfff\",\n dimgray: \"696969\",\n dimgrey: \"696969\",\n dodgerblue: \"1e90ff\",\n firebrick: \"b22222\",\n floralwhite: \"fffaf0\",\n forestgreen: \"228b22\",\n fuchsia: \"f0f\",\n gainsboro: \"dcdcdc\",\n ghostwhite: \"f8f8ff\",\n gold: \"ffd700\",\n goldenrod: \"daa520\",\n gray: \"808080\",\n green: \"008000\",\n greenyellow: \"adff2f\",\n grey: \"808080\",\n honeydew: \"f0fff0\",\n hotpink: \"ff69b4\",\n indianred: \"cd5c5c\",\n indigo: \"4b0082\",\n ivory: \"fffff0\",\n khaki: \"f0e68c\",\n lavender: \"e6e6fa\",\n lavenderblush: \"fff0f5\",\n lawngreen: \"7cfc00\",\n lemonchiffon: \"fffacd\",\n lightblue: \"add8e6\",\n lightcoral: \"f08080\",\n lightcyan: \"e0ffff\",\n lightgoldenrodyellow: \"fafad2\",\n lightgray: \"d3d3d3\",\n lightgreen: \"90ee90\",\n lightgrey: \"d3d3d3\",\n lightpink: \"ffb6c1\",\n lightsalmon: \"ffa07a\",\n lightseagreen: \"20b2aa\",\n lightskyblue: \"87cefa\",\n lightslategray: \"789\",\n lightslategrey: \"789\",\n lightsteelblue: \"b0c4de\",\n lightyellow: \"ffffe0\",\n lime: \"0f0\",\n limegreen: \"32cd32\",\n linen: \"faf0e6\",\n magenta: \"f0f\",\n maroon: \"800000\",\n mediumaquamarine: \"66cdaa\",\n mediumblue: \"0000cd\",\n mediumorchid: \"ba55d3\",\n mediumpurple: \"9370db\",\n mediumseagreen: \"3cb371\",\n mediumslateblue: \"7b68ee\",\n mediumspringgreen: \"00fa9a\",\n mediumturquoise: \"48d1cc\",\n mediumvioletred: \"c71585\",\n midnightblue: \"191970\",\n mintcream: \"f5fffa\",\n mistyrose: \"ffe4e1\",\n moccasin: \"ffe4b5\",\n navajowhite: \"ffdead\",\n navy: \"000080\",\n oldlace: \"fdf5e6\",\n olive: \"808000\",\n olivedrab: \"6b8e23\",\n orange: \"ffa500\",\n orangered: \"ff4500\",\n orchid: \"da70d6\",\n palegoldenrod: \"eee8aa\",\n palegreen: \"98fb98\",\n paleturquoise: \"afeeee\",\n palevioletred: \"db7093\",\n papayawhip: \"ffefd5\",\n peachpuff: \"ffdab9\",\n peru: \"cd853f\",\n pink: \"ffc0cb\",\n plum: \"dda0dd\",\n powderblue: \"b0e0e6\",\n purple: \"800080\",\n rebeccapurple: \"663399\",\n red: \"f00\",\n rosybrown: \"bc8f8f\",\n royalblue: \"4169e1\",\n saddlebrown: \"8b4513\",\n salmon: \"fa8072\",\n sandybrown: \"f4a460\",\n seagreen: \"2e8b57\",\n seashell: \"fff5ee\",\n sienna: \"a0522d\",\n silver: \"c0c0c0\",\n skyblue: \"87ceeb\",\n slateblue: \"6a5acd\",\n slategray: \"708090\",\n slategrey: \"708090\",\n snow: \"fffafa\",\n springgreen: \"00ff7f\",\n steelblue: \"4682b4\",\n tan: \"d2b48c\",\n teal: \"008080\",\n thistle: \"d8bfd8\",\n tomato: \"ff6347\",\n turquoise: \"40e0d0\",\n violet: \"ee82ee\",\n wheat: \"f5deb3\",\n white: \"fff\",\n whitesmoke: \"f5f5f5\",\n yellow: \"ff0\",\n yellowgreen: \"9acd32\"\n};\n\n// Make it easy to access colors via `hexNames[hex]`\nvar hexNames = tinycolor.hexNames = flip(names);\n\n// Utilities\n// ---------\n\n// `{ 'name1': 'val1' }` becomes `{ 'val1': 'name1' }`\nfunction flip(o) {\n var flipped = {};\n for (var i in o) {\n if (o.hasOwnProperty(i)) {\n flipped[o[i]] = i;\n }\n }\n return flipped;\n}\n\n// Return a valid alpha value [0,1] with all invalid values being set to 1\nfunction boundAlpha(a) {\n a = parseFloat(a);\n if (isNaN(a) || a < 0 || a > 1) {\n a = 1;\n }\n return a;\n}\n\n// Take input from [0, n] and return it as [0, 1]\nfunction bound01(n, max) {\n if (isOnePointZero(n)) n = \"100%\";\n var processPercent = isPercentage(n);\n n = Math.min(max, Math.max(0, parseFloat(n)));\n\n // Automatically convert percentage into number\n if (processPercent) {\n n = parseInt(n * max, 10) / 100;\n }\n\n // Handle floating point rounding errors\n if (Math.abs(n - max) < 0.000001) {\n return 1;\n }\n\n // Convert into [0, 1] range if it isn't already\n return n % max / parseFloat(max);\n}\n\n// Force a number between 0 and 1\nfunction clamp01(val) {\n return Math.min(1, Math.max(0, val));\n}\n\n// Parse a base-16 hex value into a base-10 integer\nfunction parseIntFromHex(val) {\n return parseInt(val, 16);\n}\n\n// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1\n// \nfunction isOnePointZero(n) {\n return typeof n == \"string\" && n.indexOf(\".\") != -1 && parseFloat(n) === 1;\n}\n\n// Check to see if string passed in is a percentage\nfunction isPercentage(n) {\n return typeof n === \"string\" && n.indexOf(\"%\") != -1;\n}\n\n// Force a hex value to have 2 characters\nfunction pad2(c) {\n return c.length == 1 ? \"0\" + c : \"\" + c;\n}\n\n// Replace a decimal with it's percentage value\nfunction convertToPercentage(n) {\n if (n <= 1) {\n n = n * 100 + \"%\";\n }\n return n;\n}\n\n// Converts a decimal to a hex value\nfunction convertDecimalToHex(d) {\n return Math.round(parseFloat(d) * 255).toString(16);\n}\n// Converts a hex value to a decimal\nfunction convertHexToDecimal(h) {\n return parseIntFromHex(h) / 255;\n}\nvar matchers = function () {\n // \n var CSS_INTEGER = \"[-\\\\+]?\\\\d+%?\";\n\n // \n var CSS_NUMBER = \"[-\\\\+]?\\\\d*\\\\.\\\\d+%?\";\n\n // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome.\n var CSS_UNIT = \"(?:\" + CSS_NUMBER + \")|(?:\" + CSS_INTEGER + \")\";\n\n // Actual matching.\n // Parentheses and commas are optional, but not required.\n // Whitespace can take the place of commas or opening paren\n var PERMISSIVE_MATCH3 = \"[\\\\s|\\\\(]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")\\\\s*\\\\)?\";\n var PERMISSIVE_MATCH4 = \"[\\\\s|\\\\(]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")[,|\\\\s]+(\" + CSS_UNIT + \")\\\\s*\\\\)?\";\n return {\n CSS_UNIT: new RegExp(CSS_UNIT),\n rgb: new RegExp(\"rgb\" + PERMISSIVE_MATCH3),\n rgba: new RegExp(\"rgba\" + PERMISSIVE_MATCH4),\n hsl: new RegExp(\"hsl\" + PERMISSIVE_MATCH3),\n hsla: new RegExp(\"hsla\" + PERMISSIVE_MATCH4),\n hsv: new RegExp(\"hsv\" + PERMISSIVE_MATCH3),\n hsva: new RegExp(\"hsva\" + PERMISSIVE_MATCH4),\n hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,\n hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,\n hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,\n hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/\n };\n}();\n\n// `isValidCSSUnit`\n// Take in a single string / number and check to see if it looks like a CSS unit\n// (see `matchers` above for definition).\nfunction isValidCSSUnit(color) {\n return !!matchers.CSS_UNIT.exec(color);\n}\n\n// `stringInputToObject`\n// Permissive string parsing. Take in a number of formats, and output an object\n// based on detected format. Returns `{ r, g, b }` or `{ h, s, l }` or `{ h, s, v}`\nfunction stringInputToObject(color) {\n color = color.replace(trimLeft, \"\").replace(trimRight, \"\").toLowerCase();\n var named = false;\n if (names[color]) {\n color = names[color];\n named = true;\n } else if (color == \"transparent\") {\n return {\n r: 0,\n g: 0,\n b: 0,\n a: 0,\n format: \"name\"\n };\n }\n\n // Try to match string input using regular expressions.\n // Keep most of the number bounding out of this function - don't worry about [0,1] or [0,100] or [0,360]\n // Just return an object and let the conversion functions handle that.\n // This way the result will be the same whether the tinycolor is initialized with string or object.\n var match;\n if (match = matchers.rgb.exec(color)) {\n return {\n r: match[1],\n g: match[2],\n b: match[3]\n };\n }\n if (match = matchers.rgba.exec(color)) {\n return {\n r: match[1],\n g: match[2],\n b: match[3],\n a: match[4]\n };\n }\n if (match = matchers.hsl.exec(color)) {\n return {\n h: match[1],\n s: match[2],\n l: match[3]\n };\n }\n if (match = matchers.hsla.exec(color)) {\n return {\n h: match[1],\n s: match[2],\n l: match[3],\n a: match[4]\n };\n }\n if (match = matchers.hsv.exec(color)) {\n return {\n h: match[1],\n s: match[2],\n v: match[3]\n };\n }\n if (match = matchers.hsva.exec(color)) {\n return {\n h: match[1],\n s: match[2],\n v: match[3],\n a: match[4]\n };\n }\n if (match = matchers.hex8.exec(color)) {\n return {\n r: parseIntFromHex(match[1]),\n g: parseIntFromHex(match[2]),\n b: parseIntFromHex(match[3]),\n a: convertHexToDecimal(match[4]),\n format: named ? \"name\" : \"hex8\"\n };\n }\n if (match = matchers.hex6.exec(color)) {\n return {\n r: parseIntFromHex(match[1]),\n g: parseIntFromHex(match[2]),\n b: parseIntFromHex(match[3]),\n format: named ? \"name\" : \"hex\"\n };\n }\n if (match = matchers.hex4.exec(color)) {\n return {\n r: parseIntFromHex(match[1] + \"\" + match[1]),\n g: parseIntFromHex(match[2] + \"\" + match[2]),\n b: parseIntFromHex(match[3] + \"\" + match[3]),\n a: convertHexToDecimal(match[4] + \"\" + match[4]),\n format: named ? \"name\" : \"hex8\"\n };\n }\n if (match = matchers.hex3.exec(color)) {\n return {\n r: parseIntFromHex(match[1] + \"\" + match[1]),\n g: parseIntFromHex(match[2] + \"\" + match[2]),\n b: parseIntFromHex(match[3] + \"\" + match[3]),\n format: named ? \"name\" : \"hex\"\n };\n }\n return false;\n}\nfunction validateWCAG2Parms(parms) {\n // return valid WCAG2 parms for isReadable.\n // If input parms are invalid, return {\"level\":\"AA\", \"size\":\"small\"}\n var level, size;\n parms = parms || {\n level: \"AA\",\n size: \"small\"\n };\n level = (parms.level || \"AA\").toUpperCase();\n size = (parms.size || \"small\").toLowerCase();\n if (level !== \"AA\" && level !== \"AAA\") {\n level = \"AA\";\n }\n if (size !== \"small\" && size !== \"large\") {\n size = \"small\";\n }\n return {\n level: level,\n size: size\n };\n}\n\nexport { tinycolor as default };\n", "\uFEFFimport tinycolor from 'tinycolor2';\n\nwindow.tinycolor = window.tinycolor != null ? window.tinycolor : tinycolor;\nexport { tinycolor };\nexport default window.tinycolor;\n", ".carousel {\r\n position: relative;\r\n box-sizing: border-box;\r\n transform: translate3d(0, 0, 0);\r\n}\r\n\r\n.carousel-main-list {\r\n -webkit-user-select: none;\r\n -moz-user-select: none;\r\n user-select: none;\r\n}\r\n\r\n.carousel-inner {\r\n overflow: hidden;\r\n position: relative;\r\n}\r\n\r\n.carousel-list {\r\n white-space: nowrap;\r\n font-size: 0;\r\n line-height: 0;\r\n transition-property: transform;\r\n transform: translate3d(0, 0, 0);\r\n overflow: hidden;\r\n}\r\n\r\n.carousel-item {\r\n -webkit-backface-visibility: visible;\r\n backface-visibility: visible;\r\n transform: translateZ(0) scale(1, 1);\r\n}\r\n\r\n.carousel-dots {\r\n padding: 0;\r\n margin: 0;\r\n list-style: none;\r\n display: block;\r\n text-align: center;\r\n margin-top: 10px;\r\n line-height: 1;\r\n}\r\n\r\n.carousel-dots-item {\r\n display: inline-block;\r\n vertical-align: middle;\r\n cursor: pointer;\r\n padding: 0.3125rem;\r\n font-size: 0;\r\n line-height: 0;\r\n opacity: 0.5;\r\n}\r\n\r\n.carousel-dots-item-inner {\r\n border-radius: 50%;\r\n height: 0.5rem;\r\n width: 0.5rem;\r\n display: inline-block;\r\n box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.5);\r\n}\r\n\r\n.carousel-dots-selected {\r\n opacity: 1;\r\n}\r\n\r\n.carousel-nav-prev,\r\n.carousel-nav-next {\r\n position: absolute;\r\n text-align: center;\r\n padding: 0;\r\n margin: 0;\r\n border: 0;\r\n background: transparent none;\r\n font-size: 1rem;\r\n cursor: pointer;\r\n}\r\n.carousel-nav-prev:focus,\r\n.carousel-nav-next:focus {\r\n outline: none;\r\n}\r\n.carousel-nav-prev::after,\r\n.carousel-nav-next::after {\r\n margin: 0;\r\n}\r\n.carousel-nav-prev:disabled,\r\n.carousel-nav-next:disabled {\r\n display: none;\r\n}\r\n\r\n.carousel-vertical.carousel-wrap-nav-outside {\r\n margin-top: 2rem;\r\n margin-bottom: 2rem;\r\n}\r\n.carousel-vertical > .carousel-nav-inside .carousel-nav-prev {\r\n top: 0;\r\n transform: translateX(-50%);\r\n left: 50%;\r\n}\r\n.carousel-vertical > .carousel-nav-inside .carousel-nav-next {\r\n bottom: 0;\r\n transform: translateX(-50%);\r\n left: 50%;\r\n}\r\n.carousel-vertical > .carousel-nav-outside .carousel-nav-prev {\r\n bottom: 100%;\r\n transform: translateX(-50%);\r\n left: 50%;\r\n}\r\n.carousel-vertical > .carousel-nav-outside .carousel-nav-next {\r\n top: 100%;\r\n transform: translateX(-50%);\r\n left: 50%;\r\n}\r\n\r\n.carousel-horizontal.carousel-wrap-nav-outside {\r\n margin-top: 2rem;\r\n}\r\n.carousel-horizontal .carousel-nav-prev {\r\n top: 50%;\r\n transform: translateY(-50%);\r\n left: 0;\r\n}\r\n.carousel-horizontal .carousel-nav-next {\r\n top: 50%;\r\n transform: translateY(-50%);\r\n right: 0;\r\n}\r\n.carousel-horizontal .carousel-nav-inside .carousel-nav-prev {\r\n left: 0;\r\n}\r\n.carousel-horizontal .carousel-nav-inside .carousel-nav-next {\r\n right: 0;\r\n}\r\n.carousel-horizontal .carousel-nav-outside {\r\n position: absolute;\r\n bottom: 100%;\r\n right: 0.625rem;\r\n white-space: nowrap;\r\n}\r\n.carousel-horizontal .carousel-nav-outside .carousel-nav-prev,\r\n.carousel-horizontal .carousel-nav-outside .carousel-nav-next {\r\n position: relative;\r\n width: 35px;\r\n left: auto;\r\n right: auto;\r\n top: auto;\r\n transform: translateY(0);\r\n display: inline-block;\r\n vertical-align: middle;\r\n}\r\n.carousel-horizontal .carousel-nav-outside .carousel-nav-prev:disabled,\r\n.carousel-horizontal .carousel-nav-outside .carousel-nav-next:disabled {\r\n opacity: 0.3;\r\n}\r\n.carousel-horizontal .res-arrow-prev.carousel-nav-prev,\r\n.carousel-horizontal .res-arrow-next.carousel-nav-next {\r\n top: -0.1875rem;\r\n}\r\n.carousel-horizontal .res-arrow-prev.carousel-nav-prev {\r\n right: 2.1875rem;\r\n left: auto;\r\n}\r\n.carousel-horizontal .res-arrow-next.carousel-nav-next {\r\n right: 0.625rem;\r\n}\r\n\r\n.carousel-mobile {\r\n padding: 0;\r\n}\r\n\r\n.carousel-update {\r\n visibility: hidden;\r\n /* .carousel-list {\n white-space: normal;\n } */\r\n}\r\n\r\n.carousel--not-hidden-on-update.carousel-update {\r\n visibility: visible;\r\n}\r\n\r\n.carousel-nav-not-show > .carousel-nav {\r\n display: none;\r\n}\r\n\r\n.carousel-scroll-nav .carousel-inner {\r\n overflow: auto;\r\n}\r\n\r\n.carousel-placeholder {\r\n max-height: 1px;\r\n max-width: 1px;\r\n}", "\uFEFF(function (window) {\n 'use strict';\n\n var isTouchDevice = 'ontouchstart' in document.documentElement,\n autoStop = false,\n clonesForCreate = {},\n transformName = 'transform',\n transitionDurationName = 'transitionDuration',\n webkitTransitionDuration = 'webkitTransitionDuration',\n Carousel,\n storage = {},\n idIncrement = 0,\n deferList = {},\n isOverScrollX = false,\n isScrolling = false;\n\n Carousel = function (element, options) {\n var id = element.getAttribute('id') || 'carousel_' + (idIncrement += 1);\n\n this.list = element;\n this.items = Array.prototype.slice.call(element.children).filter((x) => x.classList.contains('js-carousel-clone') === false);\n this.options = options;\n this.responsive = options.responsive;\n this.responsiveOption = this.options.responsive != null ? this.checkResponsive() : null;\n this.propName = this.getPropName(this.getIsVerticalOption());\n this.cache = this.items.slice();\n this.id = id;\n this.dots = [];\n\n storage[id] = {\n state: { callAsNav: false },\n obj: this,\n };\n\n this.resolveAsNavForReady(this.id);\n\n return this;\n };\n\n Carousel.prototype.addToCache = function (item) {\n this.cache.push(item);\n };\n\n Carousel.prototype.getFromCache = function (item) {\n var index;\n\n if (typeof item === 'number') {\n index = item;\n } else {\n index = this.cache.indexOf(item);\n }\n\n return this.cache[index];\n };\n\n Carousel.prototype.removeFromCache = function (item) {\n var index;\n\n if (typeof item === 'number') {\n index = item;\n } else {\n index = this.cache.indexOf(item);\n }\n\n if (index !== -1) {\n this.cache.splice(index, 1);\n }\n\n return this.cache[index];\n };\n\n Carousel.prototype.clearCache = function () {\n this.cache.length = 0;\n };\n\n Carousel.prototype.getSize = function (totalCount, maxWidth, maxHeight, isVertical, diff) {\n var size = {};\n\n if (isVertical === false) {\n size['width'] = totalCount * maxWidth - (diff || 0);\n size['height'] = maxHeight;\n } else {\n size['width'] = maxWidth;\n size['height'] = totalCount * maxHeight - (diff || 0);\n }\n\n return size;\n };\n\n Carousel.prototype.getPropName = function (isVertical) {\n return isVertical === false ? 'width' : 'height';\n };\n\n Carousel.prototype.getItemsMaxSizes = function (items) {\n var tempWidth = 0,\n tempHeight = 0,\n maxWidth = 0,\n maxHeigth = 0;\n\n for (var i = items.length - 1; i >= 0; i--) {\n if (items[i].carouselItemData == null) {\n continue;\n }\n\n tempWidth = items[i].carouselItemData.originalWidth;\n\n if (tempWidth > maxWidth) {\n maxWidth = tempWidth;\n }\n\n tempHeight = items[i].carouselItemData.originalHeight;\n\n if (tempHeight > maxHeigth) {\n maxHeigth = tempHeight;\n }\n }\n\n return {\n width: maxWidth,\n height: maxHeigth,\n };\n };\n\n Carousel.prototype.setItemSize = function (item, value) {\n var self = this,\n valueStr = value + 'px';\n\n item.style[self.propName] = valueStr;\n //item.style['min' + self.propName.charAt(0).toUpperCase() + self.propName.slice(1)] = valueStr;\n item.style['max' + self.propName.charAt(0).toUpperCase() + self.propName.slice(1)] = valueStr;\n item.style['flexBasis'] = valueStr;\n item.style['msFlexPreferredSize'] = valueStr;\n item.style['webkitFlexBasis'] = valueStr;\n };\n\n Carousel.prototype.processItems = function (items, saveStyleAttribute) {\n var self = this;\n\n for (var i = 0, len = items.length - 1; i <= len; i++) {\n self.processItem(items[i], i, saveStyleAttribute);\n }\n };\n\n Carousel.prototype.processItem = function (item, index, saveStyleAttribute) {\n var self = this;\n var itemStylesComputed = getComputedStyle(item),\n itemBorderLeft,\n itemBorderRight,\n itemBorderTop,\n itemBorderBottom;\n\n itemBorderLeft = parseInt(itemStylesComputed['border-left-width'], 10);\n itemBorderRight = parseInt(itemStylesComputed['border-right-width'], 10);\n itemBorderTop = parseInt(itemStylesComputed['border-top-width'], 10);\n itemBorderBottom = parseInt(itemStylesComputed['border-bottom-width'], 10);\n\n itemBorderLeft = isNaN(itemBorderLeft) ? 0 : itemBorderLeft;\n itemBorderRight = isNaN(itemBorderRight) ? 0 : itemBorderRight;\n itemBorderTop = isNaN(itemBorderTop) ? 0 : itemBorderTop;\n itemBorderBottom = isNaN(itemBorderBottom) ? 0 : itemBorderBottom;\n\n /*,\n itemStylesComputed = getComputedStyle(item),\n itemStylesComputed = item.getBoundingClientRect(),\n itemPaddingLeft,\n itemPaddingRight,\n itemPaddingTop,\n itemPaddingBottom;*/\n\n /*itemPaddingLeft = parseInt(itemStylesComputed['padding-left'], 10);\n itemPaddingRight = parseInt(itemStylesComputed['padding-right'], 10);\n itemPaddingTop = parseInt(itemStylesComputed['padding-top'], 10);\n itemPaddingBottom = parseInt(itemStylesComputed['padding-bottom'], 10);\n\n itemPaddingLeft = isNaN(itemPaddingLeft) ? 0 : itemPaddingLeft;\n itemPaddingRight = isNaN(itemPaddingRight) ? 0 : itemPaddingRight;\n itemPaddingTop = isNaN(itemPaddingTop) ? 0 : itemPaddingTop;\n itemPaddingBottom = isNaN(itemPaddingBottom) ? 0 : itemPaddingBottom;*/\n\n item.carouselItemData = item.carouselItemData || {};\n item.carouselItemData.originalWidth = item.getBoundingClientRect().width;\n item.carouselItemData.originalHeight = item.getBoundingClientRect().height;\n item.carouselItemData.index = index != null ? index : self.items.length;\n item.carouselItemData.parameters =\n item.getAttribute('data-parameters') != null ? new Function('return ' + item.getAttribute('data-parameters'))() : null;\n item.carouselItemData.stylesRaw =\n saveStyleAttribute === true ? item.getAttribute('style') : item.carouselItemData != null ? item.carouselItemData.stylesRaw : null;\n\n item.classList.add('js-carousel-item');\n item.classList.add('carousel-item');\n\n return item;\n };\n\n Carousel.prototype.setSizes = function (wrapSize, innerSize, listSize, itemsSizes) {\n var self = this;\n\n //if (wrapSize != null) {\n // self.wrap.style[self.propName] = wrapSize[self.propName] + 'px';\n //}\n\n if (innerSize != null) {\n self.inner.style[self.propName] = innerSize[self.propName] + 'px';\n }\n\n if (listSize != null) {\n self.list.style[self.propName] = listSize[self.propName] + 'px';\n }\n\n if (itemsSizes != null) {\n for (var i = self.items.length - 1; i >= 0; i--) {\n self.setItemSize(self.items[i], itemsSizes[self.propName]);\n }\n }\n };\n\n Carousel.prototype.calc = function (items, options, responsiveOptions) {\n var self = this;\n\n var result = responsiveOptions != null ? self.calcResponsive(items, options, responsiveOptions) : self.calcAuto(items, options);\n\n self.countVisible = result.countVisible;\n self.wrapSize = result.wrapSize;\n self.listSize = result.listSize;\n self.innerSize = result.innerSize;\n self.itemsSize = result.itemsSize;\n self.slidesSize = result.slidesSize;\n\n return result;\n };\n\n Carousel.prototype.getCarouselSize = function () {\n var self = this,\n carouselStylesComputed,\n carouselPaddingLeft,\n carouselPaddingRight,\n carouselPaddingTop,\n carouselPaddingBottom;\n\n carouselStylesComputed = getComputedStyle(self.wrap);\n\n carouselPaddingLeft = parseInt(carouselStylesComputed['padding-left'], 10);\n carouselPaddingRight = parseInt(carouselStylesComputed['padding-right'], 10);\n carouselPaddingTop = parseInt(carouselStylesComputed['padding-top'], 10);\n carouselPaddingBottom = parseInt(carouselStylesComputed['padding-bottom'], 10);\n\n carouselPaddingLeft = isNaN(carouselPaddingLeft) ? 0 : carouselPaddingLeft;\n carouselPaddingRight = isNaN(carouselPaddingRight) ? 0 : carouselPaddingRight;\n carouselPaddingTop = isNaN(carouselPaddingTop) ? 0 : carouselPaddingTop;\n carouselPaddingBottom = isNaN(carouselPaddingBottom) ? 0 : carouselPaddingBottom;\n\n return {\n width: Math.floor(self.wrap.clientWidth - carouselPaddingLeft - carouselPaddingRight),\n height: Math.floor(self.wrap.clientHeight - carouselPaddingTop - carouselPaddingBottom),\n };\n };\n\n Carousel.prototype.calcAuto = function (items, options) {\n var self = this,\n result = {},\n slidesMaxSize,\n countVisibleDirty,\n carouselSizes,\n countVisible,\n dimension,\n propName,\n slidesSize;\n\n propName = self.propName;\n\n carouselSizes = self.getCarouselSize();\n\n slidesMaxSize = self.getItemsMaxSizes(items);\n countVisibleDirty = carouselSizes[propName] / (slidesMaxSize[propName] || 1);\n\n countVisible = Math.floor(countVisibleDirty); //Math.round\n\n //dimension \u0447\u0438\u0441\u043B\u043E \u0441 \u043F\u043B\u0430\u0432\u0430\u044E\u0449\u0435\u0439 \u0442\u043E\u0447\u043A\u043E\u0439\n if (options.visibleMin != null && options.visibleMin > items.length) {\n countVisible = items.length;\n dimension = countVisibleDirty - countVisible;\n } else if (countVisible > items.length) {\n countVisible = items.length;\n dimension = 0;\n } else if (countVisible < 1) {\n countVisible = 1;\n dimension = countVisibleDirty - countVisible;\n } else {\n dimension = countVisibleDirty - countVisible;\n }\n\n if ((options.visibleMax != null && options.visibleMax < countVisible) || (options.visibleMin != null && options.visibleMin > countVisible)) {\n if (options.visibleMax != null && options.visibleMax < countVisible) {\n countVisible = options.visibleMax;\n } else if (options.visibleMin != null && options.visibleMin > countVisible) {\n countVisible = options.visibleMin;\n slidesMaxSize[propName] = carouselSizes.width / countVisible;\n }\n\n if (options.stretch) {\n slidesMaxSize[propName] = carouselSizes[propName] / countVisible;\n } else {\n //carouselSizes[propName] = carouselSizes[propName] - (slidesMaxSize[propName] * countVisible);\n var sizeSlides = slidesMaxSize[propName] * countVisible;\n carouselSizes[propName] =\n sizeSlides >= carouselSizes[propName]\n ? carouselSizes[propName]\n : carouselSizes[propName] - (carouselSizes[propName] - sizeSlides);\n }\n } else {\n if (isNaN(dimension) == false && dimension !== 0) {\n if (options.stretch) {\n slidesMaxSize[propName] += (slidesMaxSize[propName] * dimension) / countVisible;\n } else {\n if (dimension > 0) {\n carouselSizes[propName] = carouselSizes[propName] - slidesMaxSize[propName] * dimension;\n } else {\n slidesMaxSize[propName] += (slidesMaxSize[propName] * dimension) / countVisible;\n\n if (slidesMaxSize[propName] <= 0) {\n slidesMaxSize[propName] = carouselSizes[propName];\n }\n }\n }\n }\n }\n\n if (countVisible <= 1) {\n countVisible = 1;\n result = slidesMaxSize[propName];\n } else {\n result = slidesMaxSize[propName];\n }\n\n var diff = countVisible < items.length ? self.getScrollDiff(result, countVisible) : 0;\n\n if (options.isVertical === false) {\n slidesSize = {\n width: result - diff,\n height: slidesMaxSize.height,\n };\n } else {\n slidesSize = {\n width: slidesMaxSize.width,\n height: result - diff,\n };\n }\n\n return {\n countVisible: countVisible,\n wrapSize: carouselSizes,\n listSize: self.getSize(self.items.length, slidesMaxSize.width, slidesMaxSize.height, options.isVertical, diff * self.items.length),\n innerSize: self.getSize(countVisible, slidesMaxSize.width, slidesMaxSize.height, options.isVertical),\n itemsSize: slidesSize,\n slidesSize: slidesSize,\n };\n };\n\n Carousel.prototype.calcResponsive = function (items, options, responsiveOptions) {\n var self = this,\n propName = self.propName,\n carouselSizes,\n slidesSize,\n slidesMaxSize,\n countVisible;\n\n if (responsiveOptions.slidesToShow != undefined) {\n countVisible = responsiveOptions.slidesToShow;\n } else {\n throw new Error('Count sliders to show is not set');\n }\n\n carouselSizes = self.getCarouselSize();\n slidesMaxSize = self.getItemsMaxSizes(items);\n\n if (options.visibleMin != null && options.visibleMin > items.length) {\n countVisible = items.length;\n } else if (countVisible > items.length) {\n countVisible = items.length;\n }\n\n if (options.stretch) {\n slidesMaxSize[propName] = carouselSizes[propName] / countVisible;\n } else {\n //carouselSizes[propName] = carouselSizes[propName] - (slidesMaxSize[propName] * countVisible);\n var sizeSlides = slidesMaxSize[propName] * countVisible;\n carouselSizes[propName] =\n sizeSlides >= carouselSizes[propName] ? carouselSizes[propName] : carouselSizes[propName] - (carouselSizes[propName] - sizeSlides);\n }\n\n slidesMaxSize = {\n width: carouselSizes.width / countVisible,\n height: carouselSizes.height / countVisible,\n };\n\n var isVertical = self.getIsVerticalOption();\n var diff = self.getScrollDiff(slidesMaxSize[self.getPropName(isVertical)], countVisible);\n\n if (isVertical === false) {\n slidesSize = {\n width: slidesMaxSize.width - diff,\n //height: slidesMaxSize.height\n };\n } else {\n slidesSize = {\n //width: slidesMaxSize.width,\n height: slidesMaxSize.height - diff,\n };\n }\n\n return {\n countVisible: countVisible,\n wrapSize: carouselSizes,\n listSize: self.getSize(self.items.length, slidesMaxSize.width, slidesMaxSize.height, isVertical, diff * self.items.length),\n innerSize: self.getSize(countVisible, slidesMaxSize.width, slidesMaxSize.height, isVertical),\n itemsSize: slidesSize,\n slidesSize: slidesSize,\n };\n };\n\n Carousel.prototype.checkDots = function () {\n var self = this;\n var need;\n if (self.options.dots === true) {\n need = self.items.length !== 1 && self.countVisible !== self.items.length;\n\n if (need === false) {\n if (self.dotsContainer != null && self.dotsContainer.parentNode != null) {\n self.dotsContainer.parentNode.removeChild(self.dotsContainer);\n }\n\n self.dotsContainer = null;\n self.dots.length = 0;\n } else {\n self.renderDots();\n self.selectDots(self.options.indexActive);\n }\n }\n };\n\n Carousel.prototype.renderDots = function () {\n var self = this,\n newCount,\n dot,\n isRenderContaner = false,\n dim,\n dimAbs,\n itemTemp;\n\n if (self.dotsContainer == null) {\n self.dotsContainer = self.wrap.querySelector('.carousel-dots');\n\n if (self.dotsContainer != null) {\n Array.prototype.forEach.call(self.dotsContainer.children, function (el) {\n self.dots.push(el);\n });\n } else {\n self.dotsContainer = createComponent('ul');\n self.dotsContainer.className = 'carousel-dots ' + (self.options.dotsClass || '');\n isRenderContaner = true;\n }\n }\n\n newCount = self.items.length / self.options.scrollCount;\n\n dim = self.dots.length - newCount;\n dimAbs = Math.abs(dim);\n\n if (dim < 0) {\n for (var d = 0, len = dimAbs; d < len; d++) {\n dot = createComponent('li');\n dot.classList.add('carousel-dots-item');\n dot.innerHTML = '';\n self.dotsContainer.appendChild(dot);\n self.dots.push(dot);\n }\n\n self.dots.forEach(function (el, index) {\n el.setAttribute('data-index', index);\n });\n\n if (isRenderContaner === true) {\n self.wrap.appendChild(self.dotsContainer);\n }\n } else {\n for (var r = dimAbs - 1; r >= 0; r--) {\n itemTemp = self.dots.pop();\n itemTemp.parentNode.removeChild(itemTemp);\n }\n }\n };\n\n Carousel.prototype.renderNav = function () {\n var self = this,\n nav = self.wrap.querySelector('.carousel-nav'),\n navPrev,\n navNext,\n needRenderNav,\n needRenderPrev,\n needRenderNext;\n\n //#region nav find or create\n if (nav == null || nav.parentNode !== self.wrap) {\n nav = createComponent('div');\n needRenderNav = true;\n }\n\n nav.className = 'carousel-nav ' + ('carousel-nav-' + self.options.navPosition);\n\n self.nav = nav;\n //#endregion\n\n //#region prev find or create\n navPrev = nav.querySelector('.carousel-nav-prev');\n\n if (navPrev == null) {\n navPrev = createComponent('button', {\n type: 'button',\n role: 'button',\n 'aria-label': '\u041F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0439 \u0441\u043B\u0430\u0439\u0434',\n });\n needRenderPrev = true;\n }\n\n self.navPrev = navPrev;\n\n //var isVertical = self.getIsVerticalOption();\n\n //navPrev.className = 'carousel-nav-prev ' + (isVertical ? self.options.prevIconVertical : self.options.prevIcon);\n\n //if (self.options.prevClass) {\n // self.options.prevClass.split(' ').forEach(function (item) {\n // navPrev.classList.add(item);\n // });\n //}\n\n self.navPrev = navPrev;\n //#endregion\n\n //#region next find or create\n navNext = nav.querySelector('.carousel-nav-next');\n\n if (navNext == null) {\n navNext = createComponent('button', {\n type: 'button',\n role: 'button',\n 'aria-label': '\u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u0441\u043B\u0430\u0439\u0434',\n });\n needRenderNext = true;\n }\n self.navNext = navNext;\n\n self.addDirectionClassFromNav();\n\n //navNext.className = 'carousel-nav-next ' + (isVertical ? self.options.nextIconVertical : self.options.nextIcon);\n //if (self.options.nextClass) {\n // self.options.nextClass.split(' ').forEach(function (item) {\n // navNext.classList.add(item);\n // });\n //}\n\n //#endregion\n\n if (needRenderPrev === true) {\n nav.appendChild(navPrev);\n }\n\n if (needRenderNext === true) {\n nav.appendChild(navNext);\n }\n\n if (needRenderNav === true) {\n self.wrap.appendChild(nav);\n }\n };\n\n Carousel.prototype.removeDirectionClassFromNav = function () {\n var isVertical = this.getIsVerticalOption();\n var self = this;\n\n self.navNext.className = isVertical ? self.options.nextIconVertical : self.options.nextIcon;\n\n if (self.options.nextClass) {\n self.options.nextClass.split(' ').forEach(function (item) {\n self.navNext.classList.remove(item);\n });\n }\n\n self.navPrev.className = isVertical ? self.options.prevIconVertical : self.options.prevIcon;\n\n if (self.options.prevClass) {\n self.options.prevClass.split(' ').forEach(function (item) {\n self.navPrev.classList.remove(item);\n });\n }\n };\n\n Carousel.prototype.addDirectionClassFromNav = function () {\n var isVertical = this.getIsVerticalOption();\n var self = this;\n\n self.navNext.className = 'carousel-nav-next ' + (isVertical ? self.options.nextIconVertical : self.options.nextIcon);\n\n if (self.options.nextClass) {\n self.options.nextClass.split(' ').forEach(function (item) {\n self.navNext.classList.add(item);\n });\n }\n\n self.navPrev.className = 'carousel-nav-prev ' + (isVertical ? self.options.prevIconVertical : self.options.prevIcon);\n\n if (self.options.prevClass) {\n self.options.prevClass.split(' ').forEach(function (item) {\n self.navPrev.classList.add(item);\n });\n }\n };\n\n Carousel.prototype.generate = function (element) {\n var self = this,\n wrap,\n inner,\n needRenderInner,\n needRenderWrap;\n\n element.classList.add('carousel-list');\n\n if (self.options.itemActiveClass != null && self.options.itemActiveClass.length > 0) {\n self.options.itemActiveClass.split(' ').forEach(function (classNameValue) {\n self.items[self.options.indexActive].classList.add(classNameValue);\n });\n }\n\n if (self.options.itemSelectClass != null && self.options.itemSelectClass.length > 0) {\n self.options.itemSelectClass.split(' ').forEach(function (classNameValue) {\n self.items[self.options.indexActive].classList.add(classNameValue);\n });\n }\n\n //#region inner find or create\n if (self.list.parentNode != null && self.list.parentNode.classList.contains('carousel-inner') === true) {\n inner = self.list.parentNode;\n } else {\n inner = createComponent('div');\n needRenderInner = true;\n }\n\n inner.classList.add('carousel-inner');\n\n self.inner = inner;\n //#endregion\n\n //#region wrap find or create\n if (self.inner.parentNode != null && self.inner.parentNode.classList.contains('carousel') === true) {\n wrap = self.inner.parentNode;\n } else {\n wrap = createComponent('div');\n needRenderWrap = true;\n }\n\n var isVertical = self.getIsVerticalOption();\n\n wrap.classList.add('carousel');\n wrap.classList.add('carousel-' + (isVertical ? 'vertical' : 'horizontal'));\n wrap.classList.add('carousel-wrap-nav-' + self.options.navPosition);\n\n if (self.options.carouselClass != null && self.options.carouselClass.length > 0) {\n self.options.carouselClass\n .split(' ')\n .filter((item) => item.length > 0)\n .forEach(function (item) {\n wrap.classList.add(item);\n });\n }\n\n if (self.options.scrollNav === true) {\n wrap.classList.add('carousel-scroll-nav');\n }\n\n self.wrap = wrap;\n //#endregion\n\n //TODO \u043F\u043E\u0434\u0443\u043C\u0430\u0442\u044C, \u043C\u043E\u0436\u043D\u043E \u043B\u0438 \u043E\u043F\u0442\u0438\u043C\u0438\u0437\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0440\u0435\u043D\u0434\u0435\u0440\u0438\u043D\u0433\n if (needRenderInner) {\n wrap.appendChild(inner);\n }\n\n if (needRenderWrap) {\n //element.parentNode.appendChild(wrap);\n element.insertAdjacentElement('beforebegin', wrap);\n }\n\n if (needRenderInner) {\n inner.appendChild(element);\n }\n };\n\n Carousel.prototype.selectDots = function (index) {\n var self = this;\n\n if (self.dots == null || self.dotActive === self.dots[index]) {\n return;\n }\n\n if (self.dotActive != null) {\n self.dotActive.classList.remove('carousel-dots-selected');\n\n if (self.options.dotsItemSelectedClass != null && self.options.dotsItemSelectedClass.length > 0) {\n self.options.dotsItemSelectedClass.split(' ').forEach(function (classNameValue) {\n self.dotActive.classList.remove(classNameValue);\n });\n }\n\n if (self.options.dotsItemInnerSelectedClass != null && self.options.dotsItemInnerSelectedClass.length > 0) {\n self.options.dotsItemInnerSelectedClass.split(' ').forEach(function (classNameValue) {\n self.dotActive.children[0].classList.remove(classNameValue);\n });\n }\n }\n\n var dotSelectedIndex = self.dots.find((x) => parseFloat(x.dataset.index) + self.options.scrollCount - 1 >= index);\n\n if (dotSelectedIndex != null) {\n self.dotActive = dotSelectedIndex;\n dotSelectedIndex.classList.add('carousel-dots-selected');\n\n if (self.options.dotsItemSelectedClass != null && self.options.dotsItemSelectedClass.length > 0) {\n self.options.dotsItemSelectedClass.split(' ').forEach(function (classNameValue) {\n dotSelectedIndex.classList.add(classNameValue);\n });\n }\n\n if (self.options.dotsItemInnerSelectedClass != null && self.options.dotsItemInnerSelectedClass.length > 0) {\n self.options.dotsItemInnerSelectedClass.split(' ').forEach(function (classNameValue) {\n dotSelectedIndex.children[0].classList.add(classNameValue);\n });\n }\n }\n };\n\n Carousel.prototype.doClone = function () {\n var self = this,\n oldClones,\n itemsDuplicate,\n itemsClonePrev,\n itemsCloneNext,\n fragmentPrev,\n fragmentNext,\n clonePrev,\n cloneNext,\n marginLeftValue;\n\n var clonesNext = [];\n var clonesPrev = [];\n\n //#region find and delete old clones\n\n oldClones = self.list.querySelectorAll('.js-carousel-clone');\n for (var c = oldClones.length - 1; c >= 0; c--) {\n oldClones[c].parentNode.removeChild(oldClones[c]);\n }\n\n for (var i = self.items.length - 1; i >= 0; i--) {\n delete self.items[i].carouselItemData.clone;\n }\n\n self.list.style.marginLeft = '0px';\n\n //#endregion\n\n if (self.countVisible >= self.items.length) {\n return null;\n }\n\n itemsDuplicate = self.items.slice();\n\n itemsClonePrev = Array.prototype.slice.call(itemsDuplicate.reverse(), 0, self.countVisible).reverse();\n itemsCloneNext = Array.prototype.slice.call(itemsDuplicate.reverse(), 0, self.countVisible);\n\n fragmentPrev = document.createDocumentFragment();\n fragmentNext = document.createDocumentFragment();\n\n for (var p = 0, len = itemsClonePrev.length; p < len; p++) {\n clonePrev = (itemsClonePrev[p].carouselItemData.originalClone || itemsClonePrev[p]).cloneNode(true);\n clonePrev.classList.add('js-carousel-clone');\n\n self.setItemSize(clonePrev, self.slidesSize[self.propName]);\n\n fragmentPrev.appendChild(clonePrev);\n clonesPrev.push(clonePrev);\n\n itemsClonePrev[p].carouselItemData.clone = clonePrev;\n }\n\n for (var n = 0, l = itemsCloneNext.length; n < l; n++) {\n cloneNext = (itemsCloneNext[n].carouselItemData.originalClone || itemsCloneNext[n]).cloneNode(true);\n cloneNext.classList.add('js-carousel-clone');\n\n self.setItemSize(cloneNext, self.slidesSize[self.propName]);\n\n fragmentNext.appendChild(cloneNext);\n clonesNext.push(cloneNext);\n\n itemsCloneNext[n].carouselItemData.clone = cloneNext;\n }\n\n //insert for prev\n self.list.insertBefore(fragmentPrev, self.items[0]);\n\n //insert for next\n self.list.appendChild(fragmentNext);\n\n marginLeftValue = -itemsClonePrev.length * self.slidesSize[self.propName];\n\n self.list.style.marginLeft = marginLeftValue + 'px';\n\n self.hasClones = true;\n\n self.countClone = itemsClonePrev.length + itemsCloneNext.length;\n\n self.clonesInOneDirection = (itemsClonePrev.length + itemsCloneNext.length) / 2;\n\n var result = {\n clonesNext: clonesNext,\n clonesPrev: clonesPrev,\n clonesNextCount: itemsCloneNext.length,\n clonesPrevCount: itemsClonePrev.length,\n marginLeftValue: marginLeftValue,\n };\n\n if (self.options.onDoClone != null) {\n self.options.onDoClone(result);\n }\n\n return result;\n };\n\n Carousel.prototype.getMoveData = function (index) {\n var self = this,\n result;\n\n if (self.items.length > self.countVisible) {\n result = Math.abs(index) * self.slidesSize[self.propName] * (index < 0 ? 1 : -1);\n } else {\n result = 0;\n }\n\n return result;\n };\n\n Carousel.prototype.move = function (transformValue, useAnimate) {\n useAnimate = useAnimate != null ? useAnimate : true;\n\n var self = this,\n transformObj = {},\n transformStyle;\n\n var isVertical = self.getIsVerticalOption();\n\n transformObj[isVertical ? 'top' : 'left'] = transformValue;\n\n if (self.options.scrollNav === false) {\n //elStyle.webkitTransitionDuration = duration;\n //elStyle.transitionDuration = duration;\n\n self.list.style[transitionDurationName] = useAnimate === false ? '0ms' : self.options.speed / 1000 + 's';\n self.list.style[webkitTransitionDuration] = useAnimate === false ? '0ms' : self.options.speed / 1000 + 's';\n transformStyle = ['translate3d(', transformObj.left || 0, 'px,', ' ', transformObj.top || 0, 'px, 0px)'].join('');\n self.list.style[transformName] = transformStyle;\n } else {\n var scrollValue = Math.floor(isVertical ? self.inner.scrollTop : self.inner.scrollLeft);\n var scrollValueEnd = Math.floor(Math.abs((isVertical ? transformObj.top : transformObj.left) || 0));\n\n smoothScroll(self.inner, scrollValue, scrollValueEnd, isVertical);\n }\n\n self.transformValue = transformValue;\n };\n\n Carousel.prototype.moveAuto = function () {\n var self = this;\n\n if (autoStop === true) {\n return;\n }\n\n clearTimeout(self.timerAuto);\n\n self.timerAuto = setTimeout(function () {\n if (autoStop === true) {\n return;\n }\n\n self.next();\n\n self.moveAuto();\n }, self.options.autoPause);\n };\n\n Carousel.prototype.stopAuto = function () {\n autoStop = true;\n\n if (self.timerAuto != null) {\n clearTimeout(self.timerAuto);\n }\n };\n\n Carousel.prototype.startAuto = function () {\n var self = this;\n\n autoStop = false;\n\n self.moveAuto();\n };\n\n Carousel.prototype.checkNav = function () {\n var self = this,\n itemsCount = self.items.length;\n\n self.isPrevDisabled = (self.options.auto === false && 0 === self.options.indexActive) || self.countVisible >= itemsCount;\n self.isNextDisabled =\n (self.options.auto === false && self.options.indexActive + self.countVisible === self.items.length) || self.countVisible >= itemsCount;\n self.isNavNotShow = itemsCount <= self.countVisible;\n\n self.isPrevDisabled ? self.navPrev.setAttribute('disabled', 'disabled') : self.navPrev.removeAttribute('disabled');\n self.isNextDisabled ? self.navNext.setAttribute('disabled', 'disabled') : self.navNext.removeAttribute('disabled');\n\n self.wrap.classList[self.isNavNotShow === true ? 'add' : 'remove']('carousel-nav-not-show');\n };\n\n Carousel.prototype.prev = function () {\n var self = this,\n newIndex;\n var carouselAsNavFor = self.getCarouselAsNav();\n\n if (self.isPrevDisabled === true || self.animationLoop === true) {\n return;\n }\n\n newIndex = self.options.indexActive - self.options.scrollCount;\n\n //go to last item\n if (self.options.auto === true && newIndex < 0) {\n self.animationLoop = true;\n\n var returnFn = function () {\n self.list.removeEventListener('transitionend', returnFn);\n\n setTimeout(function () {\n self.animationLoop = false;\n self.goto(self.items.length - 1, false);\n\n if (carouselAsNavFor != null) {\n carouselAsNavFor.goto(self.items.length - 1, false);\n }\n }, 0);\n };\n\n self.list.addEventListener('transitionend', returnFn);\n }\n\n self.goto(newIndex, true, 'backwards');\n\n if (carouselAsNavFor != null) {\n carouselAsNavFor.goto(newIndex, true, 'backwards');\n }\n };\n\n Carousel.prototype.next = function () {\n var self = this,\n newIndex;\n var carouselAsNavFor = self.getCarouselAsNav();\n\n if (self.isNextDisabled === true || self.animationLoop === true) {\n return;\n }\n\n newIndex = self.options.indexActive + self.options.scrollCount;\n //go to first item\n\n if (self.options.auto === true && newIndex > self.items.length) {\n self.goto(0, false);\n newIndex = self.options.scrollCount;\n setTimeout(function () {\n self.goto(newIndex, true, 'forward');\n }, 0);\n return;\n }\n\n if (self.options.auto === true && newIndex === self.items.length) {\n // newIndex > self.items.length - self.countVisible\n\n self.animationLoop = true;\n\n var returnFn = function () {\n self.list.removeEventListener('transitionend', returnFn);\n setTimeout(function () {\n self.animationLoop = false;\n self.goto(0, false);\n\n if (carouselAsNavFor != null) {\n carouselAsNavFor.goto(0, false);\n }\n }, 0);\n };\n\n self.list.addEventListener('transitionend', returnFn);\n }\n\n self.goto(newIndex, true, 'forward');\n\n if (carouselAsNavFor != null) {\n carouselAsNavFor.goto(newIndex, true, 'forward');\n }\n };\n\n Carousel.prototype.loadImg = function (objForLoad, preload) {\n var self = this;\n var list, img;\n\n if (objForLoad != null) {\n list = Array.prototype.slice.call(objForLoad instanceof NodeList ? objForLoad : [objForLoad]);\n let dataSetKey;\n for (let i = 0, len = list.length; i < len; i++) {\n img = list[i];\n dataSetKey = img.dataset.src != null ? 'src' : img.dataset.srcset ? 'srcset' : null;\n if (img.dataset.carouselImg != null) {\n if (self.options.onLazyLoad != null) {\n img.addEventListener('load', function () {\n this.classList.remove('carousel-placeholder');\n });\n self.options.onLazyLoad(img, img);\n }\n } else if (dataSetKey != null && img.classList.contains('loaded') === false && img.dataset[dataSetKey].indexOf('{{') === -1) {\n // {{ - \u0432\u044B\u0440\u0430\u0436\u0435\u043D\u0438\u0435 \u0430\u043D\u0433\u0443\u043B\u044F\u0440\u0430\n\n img.addEventListener('load', function () {\n this.classList.remove('carousel-placeholder');\n });\n\n img[dataSetKey] = img.dataset[dataSetKey];\n img.classList.add('loaded');\n\n if (preload === true) {\n let fakeImg = new Image();\n fakeImg[dataSetKey] = img.dataset[dataSetKey];\n }\n }\n }\n }\n };\n\n Carousel.prototype.loadImgInsideItems = function (start, end) {\n var self = this;\n var list = [];\n\n if (self.options.auto === true) {\n start = start < 0 ? 0 : start;\n list = list.concat(self.cloneResult.clonesPrev.slice());\n list = list.concat(self.items, self.cloneResult != null ? self.cloneResult.clonesNext : []);\n } else {\n list = list.concat(self.items);\n }\n\n for (var i = start; i < end; i++) {\n self.loadImg(list[i].querySelectorAll('img'));\n }\n };\n\n Carousel.prototype.goto = function (index, isAnimate, direction) {\n var self = this;\n var carouselAsNavFor = self.getCarouselAsNav();\n\n if (self.options.itemActiveClass != null && self.options.itemActiveClass.length > 0) {\n self.options.itemActiveClass.split(' ').forEach(function (classNameValue) {\n self.items[self.options.indexActive].classList.remove(classNameValue);\n self.items[index].classList.add(classNameValue);\n });\n }\n\n if (self.countVisible === 1) {\n if (self.options.itemSelectClass != null && self.options.itemSelectClass.length > 0) {\n self.options.itemSelectClass.split(' ').forEach(function (classNameValue) {\n self.items[self.options.indexActive].classList.remove(classNameValue);\n self.items[index].classList.add(classNameValue);\n });\n }\n\n if (carouselAsNavFor != null) {\n self.callFnCarouselAsNavFor(self.setItemSelect, [index]);\n }\n }\n\n self.options.indexActive = index;\n var maxIndex;\n if (self.items.length < self.countVisible) {\n maxIndex = 0;\n } else {\n maxIndex = self.items.length - self.countVisible + (self.options.auto === true ? self.countVisible : 0);\n }\n\n var minIndex = 0 - (self.options.auto === true ? self.countVisible : 0);\n\n if (self.options.auto === false) {\n if (index < minIndex) {\n index = minIndex;\n self.options.indexActive = minIndex;\n } else if (index > maxIndex) {\n index = maxIndex;\n self.options.indexActive = maxIndex;\n }\n }\n\n isAnimate = isAnimate != null ? isAnimate : true;\n\n var transform = self.getMoveData(self.options.indexActive);\n\n self.move(transform, isAnimate);\n\n if (self.options.nav === true) {\n self.checkNav();\n }\n\n if (self.options.dots) {\n var dotsIndex = self.options.indexActive;\n if (self.options.auto === true && self.options.indexActive === self.items.length) {\n dotsIndex = 0;\n } else if (self.options.auto === true && self.options.indexActive < 0) {\n dotsIndex = self.items.length - -self.options.indexActive;\n }\n self.selectDots(dotsIndex);\n }\n };\n\n Carousel.prototype.removeItem = function (child, keepInCache) {\n var self = this,\n index,\n clone;\n\n index = self.items.indexOf(child);\n\n if (index < 0) {\n return;\n }\n\n keepInCache = keepInCache != null ? keepInCache : true;\n\n if (child != null && child.parentNode != null) {\n if (self.options.auto === true && child.carouselItemData.clone != null) {\n clone = child.carouselItemData.clone;\n clone.parentNode.removeChild(clone);\n }\n\n child.parentNode.removeChild(child);\n self.items.splice(index, 1);\n }\n\n if (keepInCache === false) {\n self.removeFromCache(child);\n }\n\n //else {\n // self.addToCache(child);\n //}\n\n self.checkDots();\n\n return child;\n };\n\n Carousel.prototype.addItem = function (item, positonIndex) {\n var self = this,\n index = self.cache.indexOf(item),\n indexSibling = index - 1;\n\n if (index == -1 || self.items.length === 0 || self.items[indexSibling] == null || self.items[indexSibling].carouselItemData == null) {\n indexSibling = null;\n }\n\n if (indexSibling == null && positonIndex == null) {\n self.items.push(item);\n self.list.insertAdjacentElement('beforeend', item);\n } else {\n self.items.splice(positonIndex != null ? positonIndex : indexSibling + 1, 0, item);\n self.items[positonIndex != null ? positonIndex - 1 : indexSibling].insertAdjacentElement('afterend', item);\n }\n\n if (item.carouselItemData == null) {\n self.processItem(item);\n }\n\n return item;\n };\n\n Carousel.prototype.updateItems = function (newItems, keepInCache) {\n var self = this;\n var insertContent = document.createDocumentFragment();\n\n self.items.length = 0;\n keepInCache = keepInCache != null ? keepInCache : true;\n\n if (keepInCache === false) {\n self.clearCache();\n }\n\n for (var i = 0, len = newItems.length; i < len; i++) {\n insertContent.appendChild(newItems[i]);\n\n if (i < self.countVisible) {\n self.loadImg(newItems[i].querySelectorAll('img'), true);\n }\n }\n\n self.list.innerHTML = '';\n self.list.appendChild(insertContent);\n\n self.processItems(newItems, true);\n\n return newItems;\n };\n\n Carousel.prototype.getItems = function () {\n return this.items;\n };\n\n Carousel.prototype.filterItems = function (filterFunction) {\n var self = this,\n arrayAll = self.cache,\n itemsForVisible;\n\n var carouselAsNavFor = self.getCarouselAsNav();\n\n if (self.options.filterFn) {\n filterFunction = self.options.filterFn;\n }\n\n itemsForVisible = arrayAll.filter(filterFunction);\n\n for (var i = 0, len = arrayAll.length - 1; i <= len; i++) {\n if (self.observer != null) {\n if (arrayAll[i] != null) {\n var img = arrayAll[i].querySelector('img');\n if (img != null) {\n img.classList.remove('loaded');\n self.observer.unobserve(img);\n }\n }\n }\n }\n\n self.items = self.updateItems(itemsForVisible, true);\n\n for (var j = 0; itemsForVisible.length > j; j++) {\n if (self.observer != null) {\n if (itemsForVisible[j] != null) {\n const img = itemsForVisible[j].querySelector('img');\n if (img != null) {\n self.observer.observe(img);\n }\n }\n }\n }\n\n self.options.indexActive = 0;\n\n self.update();\n\n if (carouselAsNavFor != null) {\n self.callFnCarouselAsNavFor(self.filterItems, [filterFunction]);\n }\n\n return self.items;\n };\n\n Carousel.prototype.clearFilterItems = function () {\n var self = this;\n\n self.filterItems(function () {\n return true;\n });\n };\n\n Carousel.prototype.getActiveItem = function () {\n return this.items[this.options.indexActive];\n };\n\n Carousel.prototype.getSelectedItem = function () {\n return this.itemSelected;\n };\n\n Carousel.prototype.setItemSelect = function (item) {\n var self = this;\n var itemIndex;\n var carouselAsNavFor = self.getCarouselAsNav();\n\n if (item == null) {\n return;\n }\n\n self.itemSelected = null;\n\n if (typeof item === 'number') {\n itemIndex = item;\n item = self.items[item];\n\n if (item == null) {\n return;\n }\n } else {\n itemIndex = self.items.indexOf(item);\n }\n\n for (var j = self.items.length - 1; j >= 0; j--) {\n if (self.options.itemSelectClass != null) {\n self.options.itemSelectClass.split(' ').forEach(function (classNameValue) {\n self.items[j].classList.remove(classNameValue);\n });\n }\n\n if (self.items[j].carouselItemData != null) {\n self.items[j].carouselItemData.isSelect = false;\n }\n }\n\n if (self.options.itemSelectClass != null) {\n self.options.itemSelectClass.split(' ').forEach(function (cssClass) {\n item.classList.add(cssClass);\n\n if (self.options.auto === true && item.carouselItemData != null && item.carouselItemData.clone != null) {\n item.carouselItemData.clone.classList.add(cssClass);\n }\n });\n }\n\n if (item.carouselItemData != null) {\n item.carouselItemData.isSelect = true;\n self.itemSelected = item;\n }\n\n if (carouselAsNavFor != null) {\n self.callFnCarouselAsNavFor(self.setItemSelect, [itemIndex]);\n }\n };\n\n Carousel.prototype.dotClick = function (event) {\n var self = this,\n currentDot,\n index;\n\n if (event.target.tagName.toLowerCase() === 'i') {\n currentDot = event.target.parentNode;\n } else if (event.target.tagName.toLowerCase() === 'li') {\n currentDot = event.target;\n } else {\n return;\n }\n\n index = parseInt(currentDot.getAttribute('data-index'));\n\n self.goto(index === 0 ? 0 : index + self.options.scrollCount - 1);\n };\n\n Carousel.prototype.itemClick = function (item) {\n var self = this;\n var itemIndex;\n var itemObj;\n var carouselAsNavFor = self.getCarouselAsNav();\n\n if (typeof item === 'number') {\n itemIndex = item;\n itemObj = self.items[itemIndex];\n } else {\n itemIndex = self.items.indexOf(item);\n itemObj = item;\n }\n\n self.setItemSelect(itemObj);\n\n if (self.options.itemSelect != null) {\n self.options.itemSelect(self, itemObj, itemIndex);\n }\n\n if (carouselAsNavFor != null) {\n if (carouselAsNavFor.isVisibleItem(itemIndex) === false) {\n carouselAsNavFor.goto(itemIndex, true);\n }\n\n self.callFnCarouselAsNavFor(self.itemClick, [itemIndex]);\n }\n };\n\n Carousel.prototype.touch = function () {\n var self = this;\n var startCoords, movedCoords;\n function touchStart(event) {\n event.stopPropagation();\n startCoords = self.getCoordinates(event);\n movedCoords = startCoords;\n\n if (self.options.auto === true) {\n self.stopAuto();\n }\n\n self.list.addEventListener('touchmove', touchMove, { passive: true });\n\n self.list.addEventListener('touchend', touchEnd, { passive: true });\n }\n\n function touchStartScroll() {\n var scrollEvent = debounce(function () {\n self.inner.removeEventListener('scroll', scrollEvent);\n self.inner.removeEventListener('touchend', scrollEvent);\n var isVertical = self.getIsVerticalOption();\n var newIndex = Math.ceil(self.inner.scrollLeft / self.itemsSize[self.getPropName(isVertical)]);\n self.goto(newIndex, true);\n }, 700);\n\n self.inner.addEventListener('scroll', scrollEvent, { passive: true });\n self.inner.addEventListener('touchend', scrollEvent, { passive: true });\n }\n\n function touchMove(event) {\n var validSwipe;\n var coords = self.getCoordinates(event);\n var dim = coords.main - movedCoords.main;\n var dimAllTime = movedCoords.main - startCoords.main;\n\n isOverScrollX = self.listSize.width + Math.abs(dimAllTime) - self.slidesSize.width > self.listSize.width;\n\n if (self.options.auto === true) {\n self.goToFirstInMobile();\n }\n\n if (!isScrolling) {\n validSwipe = self.validSwipe(startCoords, coords, dim >= 0 ? 1 : -1);\n if (validSwipe === true) {\n isScrolling = true;\n } else {\n isScrolling = false;\n }\n }\n if (isScrolling) {\n event.stopPropagation();\n self.move((self.transformValue || 0) + dim, false);\n movedCoords = coords;\n } else {\n if (self.options.scrollNav === false) {\n self.list.removeEventListener('touchmove', touchMove);\n }\n\n self.list.removeEventListener('touchend', touchEnd);\n\n if (self.options.auto === true) {\n self.startAuto();\n }\n }\n }\n\n function touchEnd(event) {\n self.list.removeEventListener('touchmove', touchMove);\n self.list.removeEventListener('touchend', touchEnd);\n var dim = movedCoords.main - startCoords.main;\n\n if (isScrolling) {\n gotoByTouhMove(dim);\n }\n\n if (self.options.auto === true) {\n self.startAuto();\n }\n\n isScrolling = false;\n }\n\n function gotoByTouhMove(dim) {\n var dimAllTime = movedCoords.main - startCoords.main;\n var maxIndex = self.items.length - self.countVisible + (self.options.auto === true ? self.countVisible - 1 : 0);\n var minIndex = 0 - (self.options.auto === true ? self.countVisible - 1 : 0);\n var isVertical = self.getIsVerticalOption();\n var touchMoveItemsCount = Math.abs(Math.round(dimAllTime / self.slidesSize[self.getPropName(isVertical)])) || 1;\n var index = dimAllTime < 0 ? self.options.indexActive + touchMoveItemsCount : self.options.indexActive - touchMoveItemsCount;\n var carouselAsNavFor = self.getCarouselAsNav();\n var direction = dim >= 0 ? 'forward' : 'backward';\n\n if (self.options.auto === false && index > maxIndex) {\n index = maxIndex;\n } else if (self.options.auto === false && index < minIndex) {\n index = minIndex;\n }\n\n if (self.options.auto === true && isOverScrollX && direction === 'backward') {\n index = self.items.length - self.countVisible + self.clonesInOneDirection;\n } else if (self.options.auto === true && isOverScrollX && direction === 'forward') {\n index = 0 - self.countVisible;\n }\n\n if (carouselAsNavFor != null && carouselAsNavFor.isVisibleItem(index) === false) {\n carouselAsNavFor.goto(index, true);\n }\n\n self.goto(index, true);\n\n isOverScrollX = false;\n }\n\n self.list.addEventListener('touchstart', self.options.scrollNav === false ? touchStart : touchStartScroll, {\n passive: true,\n });\n };\n\n Carousel.prototype.getCoordinates = function (event) {\n var self = this;\n var originalEvent = event.originalEvent || event;\n var touches = originalEvent.touches && originalEvent.touches.length ? originalEvent.touches : [originalEvent];\n var e = (originalEvent.changedTouches && originalEvent.changedTouches[0]) || touches[0];\n var result;\n var isVertical = self.getIsVerticalOption();\n if (isVertical) {\n result = {\n main: e.clientY,\n alt: e.clientX,\n };\n } else {\n result = {\n main: e.clientX,\n alt: e.clientY,\n };\n }\n\n return result;\n };\n\n Carousel.prototype.validSwipe = function (startCoords, coords) {\n var deltaAlt = Math.abs(coords.alt - startCoords.alt);\n var deltaMain = Math.abs(coords.main - startCoords.main);\n var self = this;\n var touchAngle = (Math.atan2(Math.abs(deltaAlt), Math.abs(deltaMain)) * 180) / Math.PI;\n var isVertical = self.getIsVerticalOption();\n if (isVertical === false && touchAngle > 45) {\n return false;\n }\n if (isVertical === false && touchAngle <= 45) {\n return true;\n }\n if (isVertical === true && 90 - touchAngle > 45) {\n return true;\n } else {\n return false;\n }\n };\n\n Carousel.prototype.bindIt = function () {\n var self = this,\n options = self.options;\n\n if (isTouchDevice === true) {\n self.touch();\n\n window.addEventListener('orientationchange', self.update.bind(self));\n } else {\n window.addEventListener('resize', function () {\n self.update();\n });\n }\n\n if (options.auto === true && isTouchDevice === false) {\n //self.wrap.removeEventListener('mouseenter', self.stopAuto);\n self.wrap.addEventListener('mouseenter', function () {\n self.stopAuto();\n });\n\n //self.wrap.removeEventListener('mouseleave', self.startAuto);\n self.wrap.addEventListener('mouseleave', function () {\n self.startAuto();\n });\n }\n\n self.wrap.addEventListener('click', function (event) {\n var itemClicked;\n\n if (options.nav === true) {\n if (event.target === self.navNext) {\n self.next();\n return;\n } else if (event.target === self.navPrev) {\n self.prev();\n return;\n }\n }\n\n if (options.dots === true && closest(event.target, self.dotsContainer) !== null) {\n self.dotClick(event);\n return;\n }\n\n itemClicked = closest(event.target, '.js-carousel-item');\n\n if (itemClicked !== null) {\n self.itemClick(itemClicked);\n }\n });\n\n if (self.options.responsive != null) {\n Object.keys(self.options.responsive).forEach(function (mqRule) {\n var mq = getMediaQuery(mqRule);\n\n mq.addListener(function (event) {\n if (event.matches === true) {\n self.update();\n }\n });\n });\n }\n if (self.options.auto) {\n document.addEventListener('visibilitychange', function () {\n if (document.visibilityState === 'visible') {\n self.startAuto();\n } else {\n self.stopAuto();\n }\n });\n }\n };\n\n Carousel.prototype.init = function () {\n var self = this,\n sizes;\n\n //self.cache.length = 0;\n\n self.processItems(self.items, true);\n\n self.generate(self.list);\n\n self.sizes = self.calc(self.items, self.options, self.options.responsive != null ? self.responsiveOption : null); //self.wrap, self.inner, self.list,\n\n self.setSizes(self.sizes.wrapSize, self.sizes.innerSize, self.sizes.listSize, self.sizes.itemsSize);\n\n self.checkDots();\n\n if (self.options.nav === true) {\n self.renderNav();\n }\n\n if (self.options.auto === true && self.countVisible < self.items.length) {\n self.cloneResult = self.doClone();\n\n self.sizes.listSize[self.propName] += Math.abs(self.cloneResult.marginLeftValue) * 2; //2 - \u0441 \u043E\u0431\u0435\u0438\u0445 \u0441\u0442\u043E\u0440\u043E\u043D \u0448\u0438\u0440\u0438\u043D\u0430 \u043A\u043B\u043E\u043D\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0445 \u0441\u043B\u0430\u0439\u0434\u043E\u0432\n\n self.setSizes(self.sizes.wrapSize, self.sizes.innerSize, self.sizes.listSize, self.sizes.itemsSize);\n\n self.goto(self.options.indexActive, false);\n }\n\n if (self.options.nav === true) {\n self.checkNav();\n }\n\n if (self.options.auto === true) {\n self.startAuto();\n }\n\n if (self.dots != null) {\n self.selectDots(self.options.indexActive);\n }\n\n if (self.options.initFn != null) {\n self.options.initFn(self);\n }\n\n self.bindIt();\n\n self.setIntersectionObserver();\n\n self.initilized = true;\n\n self.wrap.classList.add('carousel-initilized');\n self.addDirectionCarouselClass();\n\n return self;\n };\n\n Carousel.prototype.resetSizes = function (callback) {\n var self = this;\n var isVertical = self.getIsVerticalOption();\n\n self.wrap.style[self.propName] = isVertical ? '100%' : 'auto';\n self.inner.style[self.propName] = isVertical ? '100%' : 'auto';\n self.list.style[self.propName] = isVertical ? '100%' : 'auto';\n\n self.list.style.marginLeft = '0';\n\n self.removeDirectionCarouselClass();\n if (self.navPref != null && self.navNext != null) {\n self.removeDirectionClassFromNav();\n }\n\n var oldClones = self.list.querySelectorAll('.js-carousel-clone');\n for (var c = oldClones.length - 1; c >= 0; c--) {\n clearStyleSlide(oldClones[c], self);\n }\n\n for (var i = self.items.length - 1; i >= 0; i--) {\n clearStyleSlide(self.items[i], self);\n self.items[i].setAttribute('style', self.items[i].carouselItemData.stylesRaw || '');\n }\n\n setTimeout(function () {\n callback();\n }, 500);\n };\n\n function clearStyleSlide(slide, carousel) {\n slide.style[carousel.propName] = 'auto';\n slide.style['flex-basis'] = 'auto';\n slide.style['msFlexPreferredSize'] = 'auto';\n slide.style['webkitFlexBasis'] = 'auto';\n\n if (self.propName === 'width') {\n slide.style.maxWidth = 'none';\n } else {\n slide.style.maxHeight = 'none';\n }\n }\n\n Carousel.prototype.update = function () {\n var self = this,\n sizes;\n\n self.wrap.classList.remove('carousel-nav-not-show');\n self.wrap.classList.add('carousel-update');\n\n self.resetSizes(function () {\n if (self.list.children != null && self.list.children.length > 0) {\n var childrenWithoutClone = Array.prototype.filter.call(self.list.children, function (child) {\n return child.classList.contains('js-carousel-clone') === false;\n });\n } else {\n return;\n }\n self.responsiveOption = self.options.responsive != null ? self.checkResponsive() : null;\n var isVertical = self.getIsVerticalOption();\n self.addDirectionCarouselClass();\n if (self.navPref != null && self.navNext != null) {\n self.addDirectionClassFromNav();\n }\n self.propName = self.getPropName(isVertical);\n\n self.items = Array.prototype.slice.call(childrenWithoutClone);\n self.processItems(self.items);\n sizes = self.calc(self.items, self.options, self.responsiveOption);\n\n self.setSizes(sizes.wrapSize, sizes.innerSize, sizes.listSize, sizes.itemsSize);\n\n if (self.options.auto === true) {\n self.cloneResult = self.doClone();\n\n if (self.cloneResult != null) {\n sizes.listSize[self.propName] += Math.abs(self.cloneResult.marginLeftValue) * 2; //2 - \u0441 \u043E\u0431\u0435\u0438\u0445 \u0441\u0442\u043E\u0440\u043E\u043D \u0448\u0438\u0440\u0438\u043D\u0430 \u043A\u043B\u043E\u043D\u0438\u0440\u043E\u0432\u0430\u043D\u043D\u044B\u0445 \u0441\u043B\u0430\u0439\u0434\u043E\u0432\n }\n\n self.setSizes(sizes.wrapSize, sizes.innerSize, sizes.listSize, sizes.itemsSize);\n\n //self.options.indexActive = 0;\n } else {\n if (self.options.nav === true) {\n self.checkNav();\n }\n }\n\n self.goto(self.options.indexActive, false);\n\n if (self.options.dots === true) {\n self.checkDots();\n self.selectDots(self.options.indexActive);\n }\n\n self.wrap.classList.remove('carousel-update');\n\n if (self.options.onUpdate != null) {\n self.options.onUpdate();\n }\n });\n };\n\n Carousel.prototype.checkResponsive = function () {\n var self = this;\n var mq;\n var mqOptions;\n var mqRules = Object.keys(this.options.responsive);\n\n for (var i = mqRules.length - 1; i >= 0; i--) {\n mq = getMediaQuery(mqRules[i]);\n mqOptions = self.options.responsive[mqRules[i]];\n\n if (mq.matches === true) {\n break;\n }\n }\n\n return mqOptions;\n };\n\n Carousel.prototype.getCarouselAsNav = function () {\n return storage[this.options.asNavFor] && storage[this.options.asNavFor].obj;\n };\n\n Carousel.prototype.callFnCarouselAsNavFor = function (fn, params) {\n var self = this;\n if (\n self.options.asNavFor != null &&\n self.options.asNavFor.length > 0 &&\n storage[self.options.asNavFor] &&\n storage[self.options.asNavFor].state.callAsNav !== true\n ) {\n storage[self.options.asNavFor].state.callAsNav = true;\n fn.apply(storage[self.options.asNavFor].obj, params);\n storage[self.options.asNavFor].state.callAsNav = false;\n }\n };\n\n Carousel.prototype.whenAsNavForReady = function (idAsNavFor, callback) {\n if (storage[idAsNavFor] != null) {\n callback(storage[idAsNavFor]);\n } else {\n deferList[idAsNavFor] = callback;\n }\n };\n\n Carousel.prototype.resolveAsNavForReady = function (idAsNavFor) {\n if (deferList[idAsNavFor] != null) {\n deferList[idAsNavFor](storage[idAsNavFor]);\n }\n };\n\n Carousel.prototype.isVisibleItem = function (item) {\n var self = this;\n var itemObj = typeof item === 'number' ? self.items[item] : item;\n var itemIndex = itemObj.carouselItemData.index;\n var isVertical = self.getIsVerticalOption();\n var minIndex =\n (self.options.scrollNav === true ? self.inner.scrollLeft : Math.abs(self.transformValue)) / self.slidesSize[self.getPropName(isVertical)];\n var maxIndex = minIndex + self.countVisible;\n return minIndex < itemIndex && maxIndex > itemIndex;\n };\n\n Carousel.prototype.getScrollDiff = function (itemSize, countVisible) {\n return this.options.scrollNav === true ? Math.ceil(itemSize / 2 / countVisible) : 0;\n };\n\n Carousel.prototype.goToFirstInMobile = function () {\n var self = this;\n if (self.options.indexActive >= self.items.length + self.clonesInOneDirection - self.countVisible) {\n self.goto(0, false);\n } else if (self.options.indexActive <= 0 - self.clonesInOneDirection) {\n self.goto(self.items.length - self.countVisible, false);\n }\n };\n\n Carousel.prototype.setIntersectionObserver = function (objOptions, funcCallback, classElement) {\n var self = this;\n var targetArr = self.inner.querySelectorAll(classElement || 'img');\n\n if (targetArr != null && targetArr.length > 0) {\n var isVertical = self.getIsVerticalOption();\n var options = objOptions || {\n root: self.inner,\n rootMargin: (isVertical ? self.innerSize.height : self.innerSize.width) + 'px',\n threshold: 0,\n };\n var callback =\n funcCallback ||\n function (entries, observer) {\n entries.forEach(function (entry) {\n if (entry.isIntersecting) {\n var img = entry.target;\n\n self.loadImg(img);\n\n self.observer.unobserve(img);\n }\n });\n };\n\n if (window.IntersectionObserver) {\n self.observer = new IntersectionObserver(callback, options);\n\n for (let i = 0; i < targetArr.length; i++) {\n self.observer.observe(targetArr[i]);\n }\n } else {\n for (let i = 0; i < targetArr.length; i++) {\n var img = targetArr[i];\n\n self.loadImg(img);\n }\n }\n }\n };\n\n Carousel.prototype.getIsVerticalOption = function () {\n var self = this;\n return self.responsiveOption != null && self.responsiveOption.isVertical != null ? self.responsiveOption.isVertical : self.options.isVertical;\n };\n\n Carousel.prototype.removeDirectionCarouselClass = function () {\n this.wrap.classList.remove('carousel-vertical');\n this.wrap.classList.remove('carousel-horizontal');\n };\n\n Carousel.prototype.addDirectionCarouselClass = function () {\n var isVertical = this.getIsVerticalOption();\n this.wrap.classList.add(isVertical ? 'carousel-vertical' : 'carousel-horizontal');\n };\n\n window.Carousel = Carousel;\n\n function createComponent(tagName, attrs = {}) {\n if (clonesForCreate[tagName] == null) {\n clonesForCreate[tagName] = document.createElement(tagName);\n for (const [attr, value] of Object.entries(attrs)) {\n clonesForCreate[tagName].setAttribute(attr, value);\n }\n }\n\n return clonesForCreate[tagName].cloneNode();\n }\n\n function closest(element, selector) {\n var parent = element,\n matchesSelector;\n\n if (parent == null) {\n return null;\n }\n\n matchesSelector = parent.matches || parent.webkitMatchesSelector || parent.mozMatchesSelector || parent.msMatchesSelector;\n\n while (parent != document.body && parent != document && parent != null) {\n if (typeof selector === 'string') {\n if (matchesSelector.bind(parent)(selector) === true) {\n return parent;\n }\n } else {\n if (parent == selector) {\n return parent;\n }\n }\n\n parent = parent.parentNode;\n }\n\n return null;\n }\n\n function getMediaQuery(value) {\n return window.matchMedia('(min-width:' + value + 'px)');\n }\n\n function smoothScroll(element, scrollValue, scrollEnd, isVertical) {\n var timeLapsed = 0,\n start,\n speed = 700,\n percentage,\n position;\n var distance = scrollEnd - scrollValue;\n\n function go(timestamp) {\n var finish = true;\n\n if (!start) {\n start = timestamp;\n }\n\n timeLapsed += timestamp - start;\n percentage = speed === 0 ? 0 : timeLapsed / speed;\n percentage = percentage > 1 ? 1 : percentage;\n position = Math.floor(scrollValue + distance * animateValue(percentage));\n\n if (position != scrollEnd) {\n finish = false;\n start = timestamp;\n }\n\n element.scrollTo(!isVertical && position, isVertical && position);\n\n if (finish === false) {\n window.requestAnimationFrame(go, element);\n }\n }\n\n window.requestAnimationFrame(go, element);\n }\n\n function debounce(func, ms) {\n var timer;\n\n return function () {\n if (timer != null) {\n clearTimeout(timer);\n }\n\n var vm = this;\n var args = arguments;\n\n timer = setTimeout(function () {\n func.apply(vm, args);\n }, ms);\n };\n }\n\n //easeInOutCubic\n function animateValue(time) {\n return time < 0.5 ? 4 * time * time * time : (time - 1) * (2 * time - 2) * (2 * time - 2) + 1;\n }\n})(window);\n", "\uFEFFvar carouselService = function ($q) {\n var service = this;\n\n var imageLoad = function (imageSrc) {\n var deferItem = $q.defer(),\n imageFake = new Image();\n\n if (imageSrc == null) return deferItem.promise;\n\n imageFake.addEventListener('load', function () {\n deferItem.resolve(true);\n });\n\n imageFake.addEventListener('error', function () {\n deferItem.resolve();\n });\n\n imageFake.src = imageSrc;\n\n return deferItem.promise;\n };\n\n var checkNeedLoad = function (image) {\n return !image.complete || typeof image.naturalWidth === 'undefined' || image.naturalWidth === 0;\n };\n\n service.waitLoadImages = function (images, carouselOptions) {\n var deferMain = $q.defer(),\n promises = [];\n\n var countLoadImageInit = carouselOptions.visibleMax;\n var countLoadImage;\n\n if (countLoadImageInit != null) {\n countLoadImage = images.length - 1 <= countLoadImageInit ? images.length - 1 : countLoadImageInit;\n } else {\n countLoadImage = images.length - 1;\n }\n\n for (var i = 0; i <= countLoadImage; i++) {\n if (checkNeedLoad(images[i]) === true) {\n promises.push(imageLoad(images[i].src || images[i].dataset.src));\n }\n\n if ((images[i].src == null || images[i].src.length === 0) && images[i].dataset.src != null && images[i].dataset.src.length > 0) {\n images[i].src = images[i].dataset.src;\n }\n }\n\n if (carouselOptions.auto === true && countLoadImageInit != null) {\n for (var k = images.length - 1; k >= images.length - countLoadImageInit; k--) {\n if (checkNeedLoad(images[k]) === true) {\n promises.push(imageLoad(images[k].src || images[k].dataset.src));\n }\n\n if ((images[k].src == null || images[k].src.length === 0) && images[k].dataset.src != null && images[k].dataset.src.length > 0) {\n images[k].src = images[k].dataset.src;\n }\n }\n }\n\n if (promises.length === 0) {\n promises.push(deferMain.promise);\n deferMain.resolve();\n }\n\n return $q.all(promises);\n };\n};\n\ncarouselService.$inject = ['$q'];\n\nexport default carouselService;\n", "function carouselDirective($compile, $document, $window, carouselDefault) {\n return {\n restrict: 'A',\n scope: {\n isVertical: '&',\n scrollCount: '&',\n nav: '&',\n dots: '&',\n speed: '&',\n auto: '&',\n autoPause: '&',\n indexActive: '=?',\n prevIcon: '@',\n nextIcon: '@',\n filterFn: '&',\n prevIconVertical: '@',\n nextIconVertical: '@',\n prevClass: '@',\n nextClass: '@',\n dotsClass: '@',\n dotsItemClass: '@',\n dotsItemSelectedClass: '@',\n dotsItemInnerSelectedClass: '@',\n visibleMax: '&',\n visibleMin: '&',\n itemSelectClass: '@',\n itemActiveClass: '@',\n carouselClass: '@',\n stretch: '&',\n navPosition: '@',\n initOnLoad: ' 0) {\n if (children.length === 1 && children[0].classList.contains('carousel-inner')) {\n children = children[0].children;\n }\n if (children != null) {\n for (var i = 0, len = children.length; i < len; i++) {\n children[i].carouselItemData = children[i].carouselItemData || {};\n children[i].carouselItemData.originalClone = children[i].cloneNode(true);\n }\n }\n }\n }\n memoryItemsAsClone();\n if ($document[0].readyState !== 'complete') {\n $window.addEventListener('load', function () {\n _initWrap();\n });\n } else {\n _initWrap();\n }\n }\n };\n}\ncarouselDirective.$inject = [\"$compile\", \"$document\", \"$window\", \"carouselDefault\"];\nfunction carouselImgDirective($parse) {\n return {\n require: '^?carousel',\n link: function (scope, element, attrs, carouselCtrl) {\n if (carouselCtrl != null) {\n var callbackParsed = $parse(attrs.carouselImg);\n var callback = function (img, carouselItem) {\n return callbackParsed(scope, {\n img: img,\n carouselItem: carouselItem\n });\n };\n var carouselImgId = carouselCtrl.addCarouselImg({\n callback: callback\n });\n attrs.$set('dataCarouselImgId', carouselImgId);\n }\n }\n };\n}\ncarouselImgDirective.$inject = [\"$parse\"];\nexport { carouselDirective, carouselImgDirective };", "\uFEFFvar CarouselCtrl = function ($element, $scope, $q, carouselService, $timeout) {\n var ctrl = this;\n var carouselImgList = {};\n var deferList = [];\n\n ctrl.init = function () {\n var element = $element[0];\n return carouselService.waitLoadImages(element.querySelectorAll('img'), ctrl.carouselOptions).then(function () {\n setTimeout(function () {\n var carouselEl = element;\n\n if (ctrl.initilazeTo != null) {\n carouselEl = carouselEl.querySelector(ctrl.initilazeTo);\n }\n /* eslint-disable no-undef */\n ctrl.carouselNative = new Carousel(carouselEl, ctrl.carouselOptions).init();\n\n if (deferList.length > 0) {\n deferList.forEach(function (item) {\n item.resolve(ctrl);\n });\n }\n\n $scope.$digest();\n }, 0);\n });\n };\n\n ctrl.addCarouselImg = function (carouselImg) {\n var id = ctrl.generateCarouselImgId();\n carouselImgList[id] = carouselImg;\n return id;\n };\n\n ctrl.callFnFromCarouselImg = function (img, carouselItem) {\n var id = img.dataset.carouselImgId;\n if (carouselImgList[id] != null) {\n carouselImgList[id].callback();\n }\n };\n\n ctrl.generateCarouselImgId = function () {\n return 'carouselImgId_' + Math.random();\n };\n\n ctrl.whenCarouselInit = function () {\n var defer = $q.defer();\n if (ctrl.carouselNative == null) {\n deferList.push(defer);\n } else {\n defer.resolve(ctrl);\n }\n\n return defer.promise;\n };\n};\n\nCarouselCtrl.$inject = ['$element', '$scope', '$q', 'carouselService', '$timeout'];\n\nexport default CarouselCtrl;\n", "\uFEFFimport './styles/carousel.scss';\n\nimport './carouselNative.js';\n\nimport carouselService from './services/carouselService.js';\nimport { carouselDirective, carouselImgDirective } from './directives/carouselDirectives.js';\nimport CarouselCtrl from './controllers/carouselController.js';\n\nconst moduleName = 'carousel';\n\nangular\n .module(moduleName, [])\n .directive('carousel', carouselDirective)\n .directive('carouselImg', carouselImgDirective)\n .service('carouselService', carouselService)\n .controller('CarouselCtrl', CarouselCtrl)\n .constant('carouselDefault', {\n isVertical: false,\n scrollCount: 1,\n nav: true,\n dots: false,\n speed: 600,\n auto: false,\n autoPause: 5000,\n indexActive: 0,\n prevIcon: 'icon-left-open-after',\n nextIcon: 'icon-right-open-after',\n prevIconVertical: 'icon-up-open-after',\n nextIconVertical: 'icon-down-open-after',\n prevClass: 'cs-l-1-interactive',\n nextClass: 'cs-l-1-interactive',\n dotsClass: undefined,\n dotsItemClass: 'cs-bg-i-1',\n dotsItemSelectedClass: null,\n dotsItemInnerSelectedClass: null,\n visibleMax: null,\n visibleMin: null,\n itemSelectClass: null,\n carouselClass: null,\n stretch: true,\n navPosition: 'inside', //inside or outside\n responsive: null,\n });\n\nexport default moduleName;\n", ".rating {\r\n display: inline-block;\r\n padding: 0;\r\n margin: 0;\r\n list-style: none;\r\n font-size: 1.125rem;\r\n line-height: 1;\r\n direction: rtl;\r\n}\r\n\r\n.rating-item {\r\n display: inline-block;\r\n vertical-align: middle;\r\n padding: 0;\r\n margin: 0;\r\n cursor: pointer;\r\n color: #d1d1d1;\r\n line-height: 1;\r\n}\r\n\r\n.rating-readonly .rating-item {\r\n cursor: default;\r\n}\r\n\r\n.rating-item-selected {\r\n color: #fec419;\r\n}\r\n\r\n/* .rating-item-hover {\n color: #db2929;\n} */\r\n.rating:not(.rating-readonly) > li:hover::before,\r\n.rating:not(.rating-readonly) > li:hover ~ li::before {\r\n color: #db2929;\r\n}", "\uFEFFfunction ratingDirective() {\n return {\n require: ['rating', '?ngModel'],\n restrict: 'A',\n scope: true,\n controller: 'RatingCtrl',\n controllerAs: 'rating',\n bindToController: true,\n link: function (scope, element, attrs, ctrls) {\n const rating = ctrls[0];\n const ngModel = ctrls[1];\n const childs = element[0].children;\n\n rating.max = parseInt(attrs.max) || 5;\n rating.readonly = attrs.readonly != null ? attrs.readonly === 'true' : false;\n\n if (rating.readonly) {\n element[0].classList.add(`rating-readonly`);\n }\n\n rating.current = parseInt(attrs.current);\n rating.url = attrs.url;\n rating.objId = attrs.objId;\n rating.rateBinding = attrs.rateBinding;\n\n for (var i = 0; i <= childs.length - 1; i++) {\n childs[i].setAttribute(`data-index`, childs.length - i);\n rating.items[i] = {\n isSelected: rating.current - 1 < i,\n };\n }\n\n if (ngModel != null) {\n if (isNaN(ngModel.$modelValue) && isNaN(rating.current) === false && rating.current > 0) {\n ngModel.$setViewValue(rating.current);\n }\n ngModel.$render = () => {\n if (isNaN(ngModel.$modelValue) === false) {\n rating.current = ngModel.$modelValue;\n }\n };\n }\n\n if (rating.readonly === false) {\n element[0].addEventListener('click', function (event) {\n const item = event.target.closest('.rating-item');\n if (item != null) {\n if (ngModel != null) {\n ngModel.$setViewValue(parseInt(item.getAttribute('data-index')));\n }\n const promise = rating.select(parseInt(item.getAttribute('data-index')));\n if (promise) {\n promise.then(() => {\n element[0].classList.add(`rating-readonly`);\n });\n } else {\n scope.$apply();\n }\n }\n });\n }\n },\n };\n}\n\nexport { ratingDirective };\n", "function RatingCtrl($http, $q) {\n var ctrl = this;\n ctrl.items = [];\n ctrl.select = function (val) {\n if (ctrl.readonly === false) {\n ctrl.current = val;\n for (var i = 0; i < val; i++) {\n ctrl.items[i].isSelected = true;\n }\n if (ctrl.url) {\n return $http.post(ctrl.url, {\n objId: ctrl.objId,\n rating: ctrl.current\n }).then(function (response) {\n return ctrl.current = response.data;\n });\n } else {\n return $q.resolve(ctrl.current);\n }\n }\n };\n}\nRatingCtrl.$inject = [\"$http\", \"$q\"];\nexport default RatingCtrl;", "\uFEFFimport './styles/rating.scss';\n\nimport { ratingDirective } from './directives/ratingDirectives.js';\nimport RatingCtrl from './controllers/ratingController.js';\n\nconst moduleName = 'rating';\n\nangular.module(moduleName, []).controller('RatingCtrl', RatingCtrl).directive('rating', ratingDirective);\n\nexport default moduleName;\n", "/*!\n * screenfull\n * v3.3.2 - 2017-10-27\n * (c) Sindre Sorhus; MIT License\n */\n(function () {\n 'use strict';\n\n var document = typeof window !== 'undefined' && typeof window.document !== 'undefined' ? window.document : {};\n var isCommonjs = typeof module !== 'undefined' && module.exports;\n var keyboardAllowed = typeof Element !== 'undefined' && 'ALLOW_KEYBOARD_INPUT' in Element;\n\n var fn = (function () {\n var val;\n\n var fnMap = [\n ['requestFullscreen', 'exitFullscreen', 'fullscreenElement', 'fullscreenEnabled', 'fullscreenchange', 'fullscreenerror'],\n // New WebKit\n [\n 'webkitRequestFullscreen',\n 'webkitExitFullscreen',\n 'webkitFullscreenElement',\n 'webkitFullscreenEnabled',\n 'webkitfullscreenchange',\n 'webkitfullscreenerror',\n ],\n // Old WebKit (Safari 5.1)\n [\n 'webkitRequestFullScreen',\n 'webkitCancelFullScreen',\n 'webkitCurrentFullScreenElement',\n 'webkitCancelFullScreen',\n 'webkitfullscreenchange',\n 'webkitfullscreenerror',\n ],\n [\n 'mozRequestFullScreen',\n 'mozCancelFullScreen',\n 'mozFullScreenElement',\n 'mozFullScreenEnabled',\n 'mozfullscreenchange',\n 'mozfullscreenerror',\n ],\n ['msRequestFullscreen', 'msExitFullscreen', 'msFullscreenElement', 'msFullscreenEnabled', 'MSFullscreenChange', 'MSFullscreenError'],\n ];\n\n var i = 0;\n var l = fnMap.length;\n var ret = {};\n\n for (; i < l; i++) {\n val = fnMap[i];\n if (val && val[1] in document) {\n for (i = 0; i < val.length; i++) {\n ret[fnMap[0][i]] = val[i];\n }\n return ret;\n }\n }\n\n return false;\n })();\n\n var eventNameMap = {\n change: fn.fullscreenchange,\n error: fn.fullscreenerror,\n };\n\n var screenfull = {\n request: function (elem) {\n var request = fn.requestFullscreen;\n\n elem = elem || document.documentElement;\n\n // Work around Safari 5.1 bug: reports support for\n // keyboard in fullscreen even though it doesn't.\n // Browser sniffing, since the alternative with\n // setTimeout is even worse.\n if (/ Version\\/5\\.1(?:\\.\\d+)? Safari\\//.test(navigator.userAgent)) {\n elem[request]();\n } else {\n elem[request](keyboardAllowed && Element.ALLOW_KEYBOARD_INPUT);\n }\n },\n exit: function () {\n document[fn.exitFullscreen]();\n },\n toggle: function (elem) {\n if (this.isFullscreen) {\n this.exit();\n } else {\n this.request(elem);\n }\n },\n onchange: function (callback) {\n this.on('change', callback);\n },\n onerror: function (callback) {\n this.on('error', callback);\n },\n on: function (event, callback) {\n var eventName = eventNameMap[event];\n if (eventName) {\n document.addEventListener(eventName, callback, false);\n }\n },\n off: function (event, callback) {\n var eventName = eventNameMap[event];\n if (eventName) {\n document.removeEventListener(eventName, callback, false);\n }\n },\n raw: fn,\n };\n\n if (!fn) {\n if (isCommonjs) {\n module.exports = false;\n } else {\n window.screenfull = false;\n }\n\n return;\n }\n\n Object.defineProperties(screenfull, {\n isFullscreen: {\n get: function () {\n return Boolean(document[fn.fullscreenElement]);\n },\n },\n element: {\n enumerable: true,\n get: function () {\n return document[fn.fullscreenElement];\n },\n },\n enabled: {\n enumerable: true,\n get: function () {\n // Coerce to boolean in case of old WebKit\n return Boolean(document[fn.fullscreenEnabled]);\n },\n },\n });\n\n if (isCommonjs) {\n module.exports = screenfull;\n } else {\n window.screenfull = screenfull;\n }\n})();\n", "/*! threesixty-slider version 2.5.2 */\n/* http://github.com/etetlow/threesixty-slider.git */\n\n/*!\n * 360 degree Image Slider v2.5.2\n * http://gaurav.jassal.me\n * http://etetlow.co.uk\n * Copyright 2015, gaurav@jassal.me\n * Dual licensed under the MIT or GPL Version 3 licenses.\n *\n */\n(function ($) {\n 'use strict';\n /**\n * @class ThreeSixty\n * **The ThreeSixty slider class**.\n *\n * This as jQuery plugin to create 360 degree product image slider.\n * The plugin is full customizable with number of options provided. The plugin\n * have the power to display images in any angle 360 degrees. This feature can be\n * used successfully in many use cases e.g. on an e-commerce site to help customers\n * look products in detail, from any angle they desire.\n *\n * **Features**\n *\n * - Smooth Animation\n * - Plenty of option parameters for customization\n * - Api interaction\n * - Simple mouse interaction\n * - Custom behavior tweaking\n * - Support for touch devices\n * - Easy to integrate\n * - No flash\n *\n * Example code:\n * var product1 = $('.product1').ThreeSixty({\n * totalFrames: 72,\n * endFrame: 72,\n * currentFrame: 1,\n * imgList: '.threesixty_images',\n * progress: '.spinner',\n * imagePath:'/assets/product1/',\n * filePrefix: 'ipod-',\n * ext: '.jpg',\n * height: 265,\n * width: 400,\n * navigation: true\n * });\n * **Note:** There are loads other options that you can override to customize\n * this plugin.\n\n * @extends jQuery\n * @singleton\n * @param {String} [el] jQuery selector string for the parent container\n * @param {Object} [options] An optional config object\n *\n * @return this\n */\n $.ThreeSixty = function (el, options) {\n // To avoid scope issues, use 'base' instead of 'this'\n // to reference this class from internal events and functions.\n var base = this,\n AppConfig,\n frames = [],\n VERSION = '2.5.2';\n // Access to jQuery and DOM versions of element\n /**\n * @property {$el}\n * jQuery Dom node attached to the slider inherits all jQuery public functions.\n */\n base.$el = $(el);\n base.el = el;\n // Add a reverse reference to the DOM object\n base.$el.data('ThreeSixty', base);\n /**\n * @method init\n * The function extends the user options with default settings for the\n * slider and initilize the slider.\n * **Style Override example**\n *\n * var product1 = $('.product1').ThreeSixty({\n * totalFrames: 72,\n * endFrame: 72,\n * currentFrame: 1,\n * imgList: '.threesixty_images',\n * progress: '.spinner',\n * imagePath:'/assets/product1/',\n * filePrefix: 'ipod-',\n * ext: '.jpg',\n * height: 265,\n * width: 400,\n * navigation: true,\n * styles: {\n * border: 2px solide #b4b4b4,\n * background: url(http://example.com/images/loader.gif) no-repeat\n * }\n * });\n */\n base.init = function () {\n AppConfig = $.extend({}, $.ThreeSixty.defaultOptions, options);\n if (AppConfig.disableSpin) {\n AppConfig.currentFrame = 1;\n AppConfig.endFrame = 1;\n }\n base.initProgress();\n base.loadImages();\n };\n\n /*\n * @method maxHeight\n * Function calculates the maximum possible height of the parent element\n *\n */\n\n base.maxHeight = function (container) {\n var offset = base.el.offset(),\n top = offset.top,\n yOffset = window.pageYOffset,\n total = $(window).height(),\n distance = top - yOffset,\n maxHeight = total - distance;\n\n if (yOffset === 0 || top === 'undefined') {\n maxHeight = 'undefined';\n }\n return maxHeight;\n };\n\n /* @method resize\n * Function to make sure the slider fits.\n */\n base.resize = function () {\n var aw = AppConfig.width,\n ah = AppConfig.height,\n lr = ah / aw,\n pr = aw / ah,\n pw = base.el.parent().width(),\n ph = base.el.parent().height(),\n maxHeight = base.maxHeight(),\n altWidth = $(window).width(),\n altHeight = $(window).height(),\n sum = pw * lr;\n\n if (pw > altWidth) {\n pw = altWidth;\n }\n if (ph > altHeight) {\n ph = altHeight;\n }\n if (maxHeight === 0 || maxHeight === 'undefined') {\n maxHeight = altHeight;\n }\n if (pw * lr > maxHeight) {\n base.$el.css({\n height: maxHeight + 'px',\n width: maxHeight * pr + 'px',\n });\n } else {\n base.$el.css({\n width: pw + 'px',\n height: sum + 'px',\n });\n }\n };\n\n /*\n * @method responsive\n * Function calculates and set responsive height and width\n *\n */\n\n base.responsive = function () {\n if (AppConfig.responsive) {\n var aw = AppConfig.width,\n ah = AppConfig.height,\n lr = ah / aw,\n pr = aw / ah,\n pw = base.el.parent().width(),\n ph = base.el.parent().height(),\n maxHeight = base.maxHeight(),\n altWidth = $(window).width(),\n altHeight = $(window).height();\n\n if (pw > altWidth) {\n pw = altWidth;\n }\n if (ph > altHeight) {\n ph = altHeight;\n }\n if (maxHeight === 0 || maxHeight === 'undefined') {\n maxHeight = altHeight;\n }\n if (pw * lr > maxHeight) {\n base.$el.css({\n height: maxHeight + 'px',\n width: maxHeight * pr + 'px',\n });\n } else {\n base.$el.css({\n width: '100%',\n height: pw * lr + 'px',\n });\n }\n }\n };\n\n /**\n * @method fSBackgroundColor\n * Sets background color when fullscreen\n */\n base.fSBackgroundColor = function () {\n var bgColor = AppConfig.fSBackgroundColor;\n return bgColor;\n };\n\n /**\n * @method fullscreen\n * Creates a fullscreen capability if set to true in settings\n */\n base.fullscreen = function () {\n var aw = AppConfig.width,\n ah = AppConfig.height,\n lr = ah / aw,\n pr = aw / ah,\n wsh = screen.height,\n wsw = screen.width,\n bgColor = base.fSBackgroundColor;\n\n if (AppConfig.fullscreen) {\n var target = base.$el[0];\n if (screenfull.enabled) {\n screenfull.toggle(target);\n screenfull.onchange(function () {\n if (screenfull.isFullscreen) {\n $('.btnFull span').removeClass('icon-fullscreen').addClass('icon-resize');\n if (wsw * lr > wsh) {\n base.$el.css({\n height: wsh + 'px',\n width: wsh * pr + 'px',\n backgroundColor: bgColor,\n });\n } else {\n base.$el.css({\n width: wsw + 'px',\n height: wsw * lr + 'px',\n backgroundColor: bgColor,\n });\n }\n } else {\n $('.btnFull span').removeClass('icon-resize').addClass('icon-fullscreen');\n base.$el.css({\n width: aw + 'px',\n height: ah + 'px',\n backgroundColor: '',\n });\n base.resize();\n }\n });\n }\n }\n };\n\n /**\n * @method initProgress\n * The function sets initial styles and start the progress indicator\n * to show loading of images.\n *\n * @private\n */\n base.initProgress = function () {\n base.$el.css({\n width: AppConfig.width + 'px',\n height: AppConfig.height + 'px',\n 'background-image': 'none !important',\n });\n if (AppConfig.styles) {\n base.$el.css(AppConfig.styles);\n }\n\n base.resize();\n\n base.$el.find(AppConfig.progress).css({\n marginTop: AppConfig.height / 2 - 15 + 'px',\n });\n base.$el.find(AppConfig.progress).fadeIn('slow');\n base.$el.find(AppConfig.imgList).hide();\n };\n\n /**\n * @method loadImages\n * @private\n * The function asynchronously loads images and inject into the slider.\n */\n base.loadImages = function () {\n var li, imageName, image, host, baseIndex;\n li = document.createElement('li');\n baseIndex = AppConfig.zeroBased ? 0 : 1;\n imageName = !AppConfig.imgArray\n ? AppConfig.domain +\n AppConfig.imagePath +\n AppConfig.filePrefix +\n base.zeroPad(AppConfig.loadedImages + baseIndex) +\n AppConfig.ext +\n ('?' + new Date().getTime())\n : AppConfig.imgArray[AppConfig.loadedImages];\n image = $('').attr('src', imageName).attr('alt', '360 Slider Images').addClass('previous-image normal').appendTo(li);\n\n frames.push(image);\n\n base.$el.find(AppConfig.imgList).append(li);\n\n base.imageLoadNext();\n };\n\n /**\n * @method imageLoadNext\n * @private\n * The function load next image or call imagesLoaded()\n */\n base.imageLoadNext = function () {\n AppConfig.loadedImages += 1;\n if (AppConfig.loadedImages >= AppConfig.totalFrames) {\n base.imagesLoaded();\n } else {\n base.loadImages();\n }\n };\n\n /**\n * @method imagesLoaded\n * @private\n * The function gets triggers once the image is loaded. We also update\n * the progress percentage in this function.\n */\n base.imagesLoaded = function () {\n var loaded = 0;\n $.each(frames, function (i, image) {\n $(image).on('load', function () {\n loaded += 1;\n $(AppConfig.progress + ' span').text(Math.floor((loaded / AppConfig.totalFrames) * 100) + '%');\n if (loaded >= AppConfig.totalFrames) {\n if (AppConfig.disableSpin) {\n frames[0].removeClass('previous-image').addClass('current-image');\n }\n $(AppConfig.progress).fadeOut('slow', function () {\n $(this).hide();\n base.showImages();\n base.showNavigation();\n });\n }\n });\n });\n };\n\n /**\n * @method showImages\n * @private\n * This function is called when all the images are loaded.\n * **The function does following operations**\n * - Removes background image placeholder\n * - Displays the 360 images\n * - Initilizes mouse intraction events\n */\n base.showImages = function () {\n base.$el.find('.txtC').fadeIn();\n base.$el.find(AppConfig.imgList).fadeIn();\n base.ready = true;\n AppConfig.ready = true;\n\n if (AppConfig.drag) {\n base.initEvents();\n }\n base.refresh();\n base.initPlugins();\n AppConfig.onReady();\n\n setTimeout(function () {\n base.resize();\n }, 50);\n };\n\n /** @method initPlugins\n * The function to initilize external plugins\n */\n base.initPlugins = function () {\n $.each(AppConfig.plugins, function (i, plugin) {\n if (typeof $[plugin] === 'function') {\n $[plugin].call(base, base.$el, AppConfig);\n } else {\n throw new Error(plugin + ' not available.');\n }\n });\n };\n\n /**\n * @method showNavigation\n * Creates a navigation panel if navigation is set to true in the\n * settings.\n */\n base.showNavigation = function () {\n if (AppConfig.navigation && !AppConfig.navigation_init) {\n var nav_bar, next_btn, next, previous_btn, previous, play_stop_btn, play_stop, full_btn, full, position;\n\n if (AppConfig.position) {\n position = AppConfig.position;\n nav_bar = $('
').attr('class', 'nav_bar ' + position);\n } else {\n nav_bar = $('
').attr('class', 'btnPrev butn');\n previous = $('').attr('class', 'icon-back');\n play_stop_btn = $('
').attr('class', 'btnPlay butn');\n play_stop = $('').attr('class', 'icon-play');\n next_btn = $('
').attr('class', 'btnNext butn');\n next = $('').attr('class', 'icon-forward');\n\n previous_btn.append(previous);\n play_stop_btn.append(play_stop);\n next_btn.append(next);\n nav_bar.append(previous_btn);\n nav_bar.append(play_stop_btn);\n nav_bar.append(next_btn);\n\n if (AppConfig.fullscreen) {\n full_btn = $('
').attr('class', 'btnFull butn');\n full = $('').attr('class', 'icon-fullscreen');\n full_btn.append(full);\n nav_bar.append(full_btn);\n }\n\n base.$el.prepend(nav_bar);\n\n next_btn.bind('mousedown touchstart', base.next);\n previous_btn.bind('mousedown touchstart', base.previous);\n play_stop_btn.bind('mousedown touchstart', base.play_stop);\n\n if (AppConfig.fullscreen) {\n full_btn.bind('mousedown touchstart', base.fullscreen);\n }\n AppConfig.navigation_init = true;\n }\n };\n\n /**\n * @method play_stop\n * @private\n * Function toggles the autoplay rotation of 360 slider\n * @param {Object} [event] jQuery events object.\n *\n */\n\n base.play_stop = function (event) {\n event.preventDefault();\n\n if (!AppConfig.autoplay) {\n AppConfig.autoplay = true;\n AppConfig.play = setInterval(base.moveToNextFrame, AppConfig.playSpeed);\n $('.btnPlay span').removeClass('icon-play').addClass('icon-pause');\n } else {\n AppConfig.autoplay = false;\n $('.btnPlay span').removeClass('icon-pause').addClass('icon-play');\n clearInterval(AppConfig.play);\n AppConfig.play = null;\n }\n };\n\n /**\n * @method next\n * Using this function you can rotate 360 to next 5 frames.\n * @param {Object} [event] jQuery events object.\n *\n */\n\n base.next = function (event) {\n if (event) {\n event.preventDefault();\n }\n if (AppConfig.autoplayDirection === 1) {\n AppConfig.endFrame -= 5;\n } else {\n AppConfig.endFrame += 5;\n }\n base.refresh();\n };\n\n /**\n * @method previous\n * Using this function you can rotate 360 to previous 5 frames.\n * @param {Object} [event] jQuery events object.\n *\n */\n base.previous = function (event) {\n if (event) {\n event.preventDefault();\n }\n if (AppConfig.autoplayDirection === 1) {\n AppConfig.endFrame += 5;\n } else {\n AppConfig.endFrame -= 5;\n }\n base.refresh();\n };\n\n /**\n * @method play\n * You are start the auto rotaion for the slider with this function.\n *\n */\n base.play = function (speed, direction) {\n var _speed = speed || AppConfig.playSpeed;\n var _direction = direction || AppConfig.autoplayDirection;\n AppConfig.autoplayDirection = _direction;\n\n if (!AppConfig.autoplay) {\n AppConfig.autoplay = true;\n AppConfig.play = setInterval(base.moveToNextFrame, _speed);\n }\n };\n\n /**\n * @method stop\n * You can stop the auto rotation of the 360 slider with this function.\n *\n */\n\n base.stop = function () {\n if (AppConfig.autoplay) {\n AppConfig.autoplay = false;\n clearInterval(AppConfig.play);\n AppConfig.play = null;\n }\n };\n\n /**\n * @method endFrame\n * @private\n * Function animates to previous frame\n *\n */\n base.moveToNextFrame = function () {\n if (AppConfig.autoplayDirection === 1) {\n AppConfig.endFrame -= 1;\n } else {\n AppConfig.endFrame += 1;\n }\n base.refresh();\n };\n\n /**\n * @method gotoAndPlay\n * @public\n * Function animates to previous frame\n *\n */\n base.gotoAndPlay = function (n) {\n if (AppConfig.disableWrap) {\n AppConfig.endFrame = n;\n base.refresh();\n } else {\n // Since we could be looped around grab the multiplier\n var multiplier = Math.ceil(AppConfig.endFrame / AppConfig.totalFrames);\n if (multiplier === 0) {\n multiplier = 1;\n }\n\n // Figure out the quickest path to the requested frame\n var realEndFrame = multiplier > 1 ? AppConfig.endFrame - (multiplier - 1) * AppConfig.totalFrames : AppConfig.endFrame;\n\n var currentFromEnd = AppConfig.totalFrames - realEndFrame;\n\n // Jump past end if it's faster\n var newEndFrame = 0;\n if (n - realEndFrame > 0) {\n // Faster to move the difference ahead?\n if (n - realEndFrame < realEndFrame + (AppConfig.totalFrames - n)) {\n newEndFrame = AppConfig.endFrame + (n - realEndFrame);\n } else {\n newEndFrame = AppConfig.endFrame - (realEndFrame + (AppConfig.totalFrames - n));\n }\n } else {\n // Faster to move the distance back?\n if (realEndFrame - n < currentFromEnd + n) {\n newEndFrame = AppConfig.endFrame - (realEndFrame - n);\n } else {\n newEndFrame = AppConfig.endFrame + (currentFromEnd + n);\n }\n }\n\n // Now set the end frame\n if (realEndFrame !== n) {\n AppConfig.endFrame = newEndFrame;\n base.refresh();\n }\n }\n };\n\n /**\n * @method initEvents\n * @private\n * Function initilizes all the mouse and touch events for 360 slider movement.\n *\n */\n base.initEvents = function () {\n base.$el.bind('mousedown mousemove click', function (event) {\n event.preventDefault();\n if (event.type === 'mousedown' && event.which === 1) {\n AppConfig.pointerStartPosX = base.getPointerEvent(event).pageX;\n AppConfig.dragging = true;\n AppConfig.onDragStart(AppConfig.currentFrame);\n }\n });\n\n base.$el.bind('touchstart touchmove touchend', function (event) {\n if (event.type === 'touchstart') {\n AppConfig.pointerStartPosX = base.getPointerEvent(event).pageX;\n AppConfig.dragging = true;\n AppConfig.onDragStart(AppConfig.currentFrame);\n } else if (event.type === 'touchmove') {\n base.trackPointer(event);\n } else if (event.type === 'touchend') {\n AppConfig.dragging = false;\n AppConfig.onDragStop(AppConfig.endFrame);\n }\n });\n\n $(document).bind('mouseup', function (event) {\n AppConfig.dragging = false;\n AppConfig.onDragStop(AppConfig.endFrame);\n $(this).css('cursor', 'none');\n });\n\n $(window).bind('resize', function (event) {\n base.responsive();\n });\n\n $(document).bind('mousemove', function (event) {\n if (AppConfig.dragging) {\n event.preventDefault();\n if (base.browser.isIE && AppConfig.showCursor) {\n base.$el.css('cursor', 'url(assets/images/hand_closed.png), auto');\n }\n } else {\n if (!base.browser.isIE && AppConfig.showCursor) {\n base.$el.css('cursor', 'url(assets/images/hand_open.png), auto');\n }\n }\n base.trackPointer(event);\n });\n\n $(window).resize(function () {\n base.responsive();\n });\n };\n\n /**\n * @method getPointerEvent\n * @private\n * Function returns touch pointer events\n *\n * @params {Object} [event]\n */\n base.getPointerEvent = function (event) {\n return event.originalEvent.targetTouches ? event.originalEvent.targetTouches[0] : event;\n };\n\n /**\n * @method trackPointer\n * @private\n * Function calculates the distance between the start pointer and end pointer/\n *\n * @params {Object} [event]\n */\n base.trackPointer = function (event) {\n if (AppConfig.ready && AppConfig.dragging) {\n AppConfig.pointerEndPosX = base.getPointerEvent(event).pageX;\n if (AppConfig.monitorStartTime < new Date().getTime() - AppConfig.monitorInt) {\n AppConfig.pointerDistance = AppConfig.pointerEndPosX - AppConfig.pointerStartPosX;\n if (AppConfig.pointerDistance > 0) {\n AppConfig.endFrame =\n AppConfig.currentFrame +\n Math.ceil((AppConfig.totalFrames - 1) * AppConfig.speedMultiplier * (AppConfig.pointerDistance / base.$el.width()));\n } else {\n AppConfig.endFrame =\n AppConfig.currentFrame +\n Math.floor((AppConfig.totalFrames - 1) * AppConfig.speedMultiplier * (AppConfig.pointerDistance / base.$el.width()));\n }\n\n if (AppConfig.disableWrap) {\n AppConfig.endFrame = Math.min(AppConfig.totalFrames - (AppConfig.zeroBased ? 1 : 0), AppConfig.endFrame);\n AppConfig.endFrame = Math.max(AppConfig.zeroBased ? 0 : 1, AppConfig.endFrame);\n }\n base.refresh();\n AppConfig.monitorStartTime = new Date().getTime();\n AppConfig.pointerStartPosX = base.getPointerEvent(event).pageX;\n }\n }\n };\n\n /**\n * @method refresh\n * @public\n * Function refeshes the timer and set interval for render cycle.\n *\n */\n\n base.refresh = function () {\n if (AppConfig.ticker === 0) {\n AppConfig.ticker = setInterval(base.render, Math.round(1000 / AppConfig.framerate));\n }\n };\n\n /**\n * @method refresh\n * @private\n * Function render the animation frames on the screen with easing effect.\n */\n\n base.render = function () {\n var frameEasing;\n if (AppConfig.currentFrame !== AppConfig.endFrame) {\n frameEasing =\n AppConfig.endFrame < AppConfig.currentFrame\n ? Math.floor((AppConfig.endFrame - AppConfig.currentFrame) * 0.1)\n : Math.ceil((AppConfig.endFrame - AppConfig.currentFrame) * 0.1);\n base.hidePreviousFrame();\n AppConfig.currentFrame += frameEasing;\n base.showCurrentFrame();\n base.$el.trigger('frameIndexChanged', [base.getNormalizedCurrentFrame(), AppConfig.totalFrames]);\n } else {\n window.clearInterval(AppConfig.ticker);\n AppConfig.ticker = 0;\n }\n };\n\n /**\n * @method hidePreviousFrame\n * @private\n * Function hide the previous frame in the animation loop.\n */\n\n base.hidePreviousFrame = function () {\n frames[base.getNormalizedCurrentFrame()].removeClass('current-image').addClass('previous-image');\n };\n\n /**\n * @method showCurrentFrame\n * @private\n * Function shows the current frame in the animation loop.\n */\n base.showCurrentFrame = function () {\n frames[base.getNormalizedCurrentFrame()].removeClass('previous-image').addClass('current-image');\n };\n\n /**\n * @method getNormalizedCurrentFrame\n * @private\n * Function normalize and calculate the current frame once the user release the mouse and release touch event.\n */\n\n base.getNormalizedCurrentFrame = function () {\n var c, e;\n\n if (!AppConfig.disableWrap) {\n c = Math.ceil(AppConfig.currentFrame % AppConfig.totalFrames);\n if (c < 0) {\n c += AppConfig.totalFrames - (AppConfig.zeroBased ? 1 : 0);\n }\n } else {\n c = Math.min(AppConfig.currentFrame, AppConfig.totalFrames - (AppConfig.zeroBased ? 1 : 0));\n e = Math.min(AppConfig.endFrame, AppConfig.totalFrames - (AppConfig.zeroBased ? 1 : 0));\n c = Math.max(c, AppConfig.zeroBased ? 0 : 1);\n e = Math.max(e, AppConfig.zeroBased ? 0 : 1);\n AppConfig.currentFrame = c;\n AppConfig.endFrame = e;\n }\n\n return c;\n };\n\n /*\n * @method getCurrentFrame\n * Function returns the current active frame.\n *\n * @return Number\n */\n\n base.getCurrentFrame = function () {\n return AppConfig.currentFrame;\n };\n\n /**\n * Function to return with zero padding.\n */\n base.zeroPad = function (num) {\n function pad(number, length) {\n var str = number.toString();\n if (AppConfig.zeroPadding) {\n while (str.length < length) {\n str = '0' + str;\n }\n }\n return str;\n }\n\n var approximateLog = Math.log(AppConfig.totalFrames) / Math.LN10;\n var roundTo = 1e3;\n var roundedLog = Math.round(approximateLog * roundTo) / roundTo;\n var numChars = Math.floor(roundedLog) + 1;\n return pad(num, numChars);\n };\n\n base.browser = {};\n\n /**\n * Function to detect if the brower is IE\n * @return {boolean}\n *\n * http://msdn.microsoft.com/en-gb/library/ms537509(v=vs.85).aspx\n */\n base.browser.isIE = function () {\n var rv = -1;\n if (navigator.appName === 'Microsoft Internet Explorer') {\n var ua = navigator.userAgent;\n var re = new RegExp('MSIE ([0-9]{1,}[\\\\.0-9]{0,})');\n if (re.exec(ua) !== null) {\n rv = parseFloat(RegExp.$1);\n }\n }\n\n return rv !== -1;\n };\n\n /**\n * @method getConfig\n * The function returns the extended version of config object the plugin is going to\n * user.\n *\n * @public\n *\n * @return Object\n */\n base.getConfig = function () {\n return AppConfig;\n };\n\n $.ThreeSixty.defaultOptions = {\n /**\n * @cfg {Boolean} dragging [dragging=false]\n * @private\n * Private propery contains a flags if users is in dragging mode.\n */\n dragging: false,\n /**\n * @cfg {Boolean} ready [ready=false]\n * @private\n * Private propery is set to true is all assets are loading and application is\n * ready to render 360 slider.\n */\n ready: false,\n /**\n * @cfg {Number} pointerStartPosX\n * @private\n * private property mouse pointer start x position when user starts dragging slider.\n */\n pointerStartPosX: 0,\n /**\n * @cfg {Number} pointerEndPosX\n * @private\n * private property mouse pointer start x position when user end dragging slider.\n */\n pointerEndPosX: 0,\n /**\n * @cfg {Number} pointerDistance\n * @private\n * private property contains the distance between the pointerStartPosX and pointerEndPosX\n */\n pointerDistance: 0,\n /**\n * @cfg {Number} monitorStartTime\n * @private\n * private property contains time user took in dragging mouse from pointerStartPosX and pointerEndPosX\n */\n monitorStartTime: 0,\n monitorInt: 10,\n /**\n * @cfg {Number} ticker\n * @private\n * Timer event that renders the 360\n */\n ticker: 0,\n /**\n * @cfg {Number} speedMultiplier\n * This property controls the sensitivity for the 360 slider\n */\n speedMultiplier: 7,\n /**\n * @cfg {Number} totalFrames\n * Set total number for frames used in the 360 rotation\n */\n totalFrames: 180,\n /**\n * @cfg {Number} currentFrame\n * Current frame of the slider.\n */\n currentFrame: 0,\n /**\n * @cfg {Array} endFrame\n * Private perperty contains information about the end frame when user slides the slider.\n */\n endFrame: 0,\n /**\n * @cfg {Number} loadedImages\n * Private property contains count of loaded images.\n */\n loadedImages: 0,\n /**\n * @cfg {Array} framerate\n * Set framerate for the slider animation\n */\n framerate: 60,\n /**\n * @cfg {String} domains\n * Set comma seprated list of all parallel domain from where 360 assets needs to be loaded.\n */\n domains: null,\n /**\n * @cfg {String} domain\n * Domain from where assets needs to be loaded. Use this propery is you want to load all assets from\n * single domain.\n */\n domain: '',\n /**\n * @cfg {Boolean} parallel\n * Set to true if you want to load assets from parallel domain. Default false\n */\n parallel: false,\n /**\n * @cfg {Number} queueAmount\n * Set number of calls to be made on parallel domains.\n */\n queueAmount: 8,\n /**\n * @cfg {Number} idle\n * Mouse Inactivite idle time in seconds. If set more than 0 will auto spine the slider\n */\n idle: 0,\n /**\n * @cfg {String} filePrefix\n * Prefix for the image file name before the numeric value.\n */\n filePrefix: '',\n /**\n * @cfg {String} ext [ext=.png]\n * Slider image extension.\n */\n ext: 'png',\n /**\n * @cfg {Object} height [300]\n * Height of the slider\n */\n height: 300,\n /**\n * @cfg {Number} width [300]\n * Width of the slider\n */\n width: 300,\n /**\n * @cfg {Object} styles\n * CSS Styles for the 360 slider\n */\n styles: {},\n /**\n * @cfg {Boolean} navigation[false]\n * State if navigation controls are visible or not.\n */\n navigation: false,\n /**\n * @cfg {string} position[top-right]\n * Positioning of navigation.\n * Options are top-left, top-center, top-right, bottom-right, bottom-center, bottom-left.\n */\n position: 'top-right',\n /**\n * @cfg {Boolean} fullscreen [false]\n * FullScreen now an option instead of plugin\n */\n fullscreen: false,\n /**\n * @cfg {string} fSBackgroundColor [white]\n * Set color of background in FullScreen (css style)\n */\n fSBackgroundColor: '#fff',\n /**\n * @cfg {Boolean} autoplay[false]\n * Autoplay the 360 animation\n */\n autoplay: false,\n /**\n * @cfg {number} autoplayDirection [1]\n * Direction for autoplay the 360 animation. 1 for right spin, and -1 for left spin.\n */\n autoplayDirection: 1,\n /**\n * Property to disable auto spin\n * @type {Boolean}\n */\n disableSpin: false,\n /**\n * Property to disable infinite wrap\n * @type {Boolean}\n */\n disableWrap: false,\n /**\n * Responsive width\n * @type {Boolean}\n */\n responsive: false,\n /**\n * Zero Padding for filenames\n * @type {Boolean}\n */\n zeroPadding: false,\n /**\n * Zero based for image filenames starting at 0\n * @type {Boolean}\n */\n zeroBased: false,\n /**\n * @type {Array}\n * List of plugins\n */\n plugins: [],\n /**\n * @type {Boolean}\n * Show hand cursor on drag\n */\n showCursor: false,\n /**\n * @cfg {Boolean} drag\n * Set it to false if you want to disable mousedrag or touch events\n */\n drag: true,\n /**\n * @cfg {Function} onReady\n * Callback triggers once all images are loaded and ready to render on the screen\n */\n onReady: function () {},\n /**\n * @cfg {Function} onDragStart\n * Callback triggers when a user initiates dragging\n */\n onDragStart: function () {},\n /**\n * @cfg {Function} onDragStop\n * Callback triggers when a user releases after dragging\n */\n onDragStop: function () {},\n /**\n * @cfg {String} imgList\n * Set ul element where image will be loaded\n */\n imgList: '.threesixty_images',\n /**\n * @cfg {Array} imgArray\n * Use set of images in array to load images\n */\n imgArray: null,\n /**\n * @cfg {Number} playSpeed\n * Value to control the speed of play button rotation\n */\n playSpeed: 100,\n };\n base.init();\n };\n\n $.fn.ThreeSixty = function (options) {\n return Object.create(new $.ThreeSixty(this, options));\n };\n})(jQuery);\n/**\n *\n * Object.create method for perform as a fallback if method not available.\n * The syntax just takes away the illusion that JavaScript uses Classical Inheritance.\n */\nif (typeof Object.create !== 'function') {\n Object.create = function (o) {\n 'use strict';\n\n function F() {}\n F.prototype = o;\n return new F();\n };\n}\n", ".threesixty {\r\n margin: 0 auto;\r\n overflow: hidden;\r\n max-height: 100%;\r\n text-rendering: auto;\r\n -webkit-font-smoothing: antialiased;\r\n -moz-osx-font-smoothing: grayscale;\r\n width: auto;\r\n}\r\n\r\n.threesixty .threesixty_images {\r\n display: none;\r\n list-style: none;\r\n margin: 0;\r\n padding: 0;\r\n}\r\n\r\n.threesixty .threesixty_images img {\r\n top: 0;\r\n width: 100%;\r\n height: auto;\r\n}\r\n\r\n.threesixty .threesixty_images img.previous-image {\r\n display: none;\r\n /* stylelint-disable */\r\n /*\r\n Do not put here any other styles.\n It causes massive recalc / repaints and image flickering,\n especially on Firefox.\r\n */\r\n /* stylelint-enable */\r\n}\r\n\r\n.threesixty .threesixty_images img.current-image {\r\n display: block;\r\n /* stylelint-disable */\r\n /*\r\n Do not put here any other styles.\n It causes massive recalc / repaints and image flickering,\n especially on Firefox.\r\n */\r\n /* stylelint-enable */\r\n}\r\n\r\n.threesixty .spinner {\r\n width: 60px;\r\n display: block;\r\n margin: 0 auto;\r\n height: 30px;\r\n background: #333;\r\n background: rgba(0, 0, 0, 0.7);\r\n border-radius: 5px;\r\n}\r\n\r\n.threesixty .spinner span {\r\n font-family: Arial, \"MS Trebuchet\", sans-serif;\r\n font-size: 12px;\r\n font-weight: bolder;\r\n color: #fff;\r\n text-align: center;\r\n line-height: 30px;\r\n display: block;\r\n}\r\n\r\n.threesixty .nav_bar {\r\n position: absolute;\r\n color: #fff;\r\n z-index: 1;\r\n height: 32px;\r\n background: rgba(0, 0, 0, 0.6);\r\n border: 1px solid rgba(0, 0, 0, 0.7);\r\n border-radius: 5px;\r\n box-shadow: inset 0 0 5px rgba(255, 255, 255, 0.5);\r\n}\r\n\r\n.threesixty .nav_bar.bottom-right {\r\n bottom: 10px;\r\n right: 20px;\r\n}\r\n\r\n.threesixty .nav_bar.bottom-left {\r\n bottom: 10px;\r\n left: 20px;\r\n}\r\n\r\n.threesixty .nav_bar.top-left {\r\n top: 10px;\r\n left: 20px;\r\n}\r\n\r\n.threesixty .nav_bar.top-right {\r\n top: 10px;\r\n right: 20px;\r\n}\r\n\r\n.threesixty .nav_bar.top-center {\r\n top: 10px;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n}\r\n\r\n.threesixty .nav_bar.bottom-center {\r\n bottom: 10px;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n}\r\n\r\n.threesixty .nav_bar .butn {\r\n z-index: 2;\r\n float: left;\r\n width: 30px;\r\n height: 30px;\r\n padding: 7.5px;\r\n border-right: 1px solid rgba(0, 0, 0, 0.6);\r\n border-left: 1px solid rgba(255, 255, 255, 0.2);\r\n border-radius: 0;\r\n cursor: pointer;\r\n}\r\n\r\n.threesixty .nav_bar .butn:first-child {\r\n border-left: none;\r\n}\r\n\r\n.threesixty .nav_bar .butn:last-child {\r\n border-right: none;\r\n}\r\n\r\n.threesixty .nav_bar .butn span {\r\n z-index: 13;\r\n display: block;\r\n width: 15px;\r\n height: 15px;\r\n margin: auto;\r\n}\r\n\r\n.threesixty .nav_bar .butn span.icon-play {\r\n background: url(\"../images/sprite.png\") no-repeat 0 0;\r\n}\r\n\r\n.threesixty .nav_bar .butn span.icon-pause {\r\n background: url(\"../images/sprite.png\") no-repeat -15px 0;\r\n}\r\n\r\n.threesixty .nav_bar .butn span.icon-forward {\r\n background: url(\"../images/sprite.png\") no-repeat -30px 0;\r\n}\r\n\r\n.threesixty .nav_bar .butn span.icon-back {\r\n background: url(\"../images/sprite.png\") no-repeat -45px 0;\r\n}\r\n\r\n.threesixty .nav_bar .butn span.icon-fullscreen {\r\n background: url(\"../images/sprite.png\") no-repeat -60px 0;\r\n}\r\n\r\n.threesixty .nav_bar .butn span.icon-resize {\r\n background: url(\"../images/sprite.png\") no-repeat -75px 0;\r\n}\r\n\r\n.threesixty .nav_bar .butn span.icon-download {\r\n background: url(\"../images/sprite.png\") no-repeat -90px 0;\r\n}\r\n\r\n/* stylelint-disable */\r\n_:-webkit-full-screen,\r\n.threesixty {\r\n background-color: transparent;\r\n}\r\n\r\n/* stylelint-enable */\r\n.threesixty_images {\r\n cursor: e-resize;\r\n}", "\uFEFFfunction RotateCtrl() {\n var ctrl = this;\n\n ctrl.$onInit = function () {\n ctrl.rotateOptions = {\n totalFrames: parseInt(ctrl.totalFrames), // Total no. of image you have for 360 slider\n endFrame: parseInt(ctrl.endFrame), // end frame for the auto spin animation\n currentFrame: parseInt(ctrl.currentFrame) || 1, // This the start frame for auto spin\n imgList: ctrl.imgList, // selector for image list\n progress: ctrl.progress, // selector to show the loading progress\n imagePath: ctrl.imagePath, // path of the image assets\n ext: ctrl.ext || '.png', // extention for the assets\n height: parseInt(ctrl.height) || 300,\n width: parseInt(ctrl.width) || 300,\n navigation: ctrl.navigation() || false,\n responsive: ctrl.responsive() || false,\n autoplayDirection: parseInt(ctrl.autoplayDirection) || 1,\n framerate: parseInt(ctrl.framerate) || 60,\n disableSpin: false,\n };\n };\n}\n\nexport default RotateCtrl;\n", "function rotateDirective($window) {\n return {\n restrict: 'A',\n scope: {\n imagePath: '@',\n totalFrames: '@',\n endFrame: '@',\n height: '@',\n width: '@',\n imgList: '@',\n progress: '@',\n navigation: '&',\n responsive: '&',\n autoplayDirection: '@',\n // -1 or 1\n autoplay: '&',\n ext: '@',\n framerate: '@'\n },\n controller: 'RotateCtrl',\n controllerAs: 'rotate',\n bindToController: true,\n replace: true,\n template: '
0%
    ',\n link: function (scope, element, attrs, ctrl) {\n var img = new Image();\n img.addEventListener('load', function () {\n var wInnerWidthCut = $window.innerWidth * 0.75;\n var wInnerHeightCut = $window.innerHeight * 0.75;\n var resultWidth = Math.min(wInnerWidthCut, img.naturalWidth);\n var diffWidth = img.naturalWidth > wInnerWidthCut ? img.naturalWidth - wInnerWidthCut : 0;\n var resultHeight;\n if (wInnerWidthCut < img.naturalWidth) {\n resultHeight = (img.naturalWidth - diffWidth) * img.naturalHeight / img.naturalWidth;\n } else {\n resultHeight = img.naturalHeight;\n }\n ctrl.rotateOptions.width = resultWidth;\n ctrl.rotateOptions.height = resultHeight;\n element.ThreeSixty(ctrl.rotateOptions);\n });\n img.src = ctrl.rotateOptions.imagePath + '1' + ctrl.rotateOptions.ext;\n }\n };\n}\nrotateDirective.$inject = [\"$window\"];\nexport { rotateDirective };", "\uFEFFimport './screenfull.cjs';\nimport './threesixty.js';\nimport './styles/rotate.scss';\n\nimport RotateCtrl from './controllers/rotateController.js';\nimport { rotateDirective } from './directives/rotateDirectives.js';\n\nconst moduleName = 'rotate';\n\nangular.module(moduleName, []).controller('RotateCtrl', RotateCtrl).directive('rotate', rotateDirective);\n\nexport default moduleName;\n", "\uFEFFimport {LozadAdvObserverMode, LozadAdvOptions} from \"./types\";\n\n\nexport const LOZAD_OBSERVER_MODE: Record = {\n default: 'default',\n observerAlways: 'observerAlways',\n};\n\n\n\nconst lozadAdvConstants: LozadAdvOptions = {\n rootMargin: '0px',\n threshold: 0,\n afterWindowLoaded: true,\n load: function load(element) {\n const el = element\n\n if (el.dataset.src) {\n el.src = el.dataset.src;\n }\n if (el.dataset.srcset) {\n el.srcset = el.dataset.srcset;\n }\n if (el.dataset.backgroundImage) {\n el.style.backgroundImage = 'url(' + el.dataset.backgroundImage + ')';\n }\n },\n};\n\nexport default lozadAdvConstants;\n", "import { ILozadAdvService } from \"./lozadAdv.service\";\nimport { IAttributes, IController, IDocumentService, IParseService, IScope, IWindowService } from \"angular\";\nimport { LozadAdvOptions, LozadAdvParams } from \"./types\";\nimport { LOZAD_OBSERVER_MODE } from \"./lozadAdv.constants\";\nexport type ILozadAdvCtrlFn = (this: ILozadAdvCtrl, $window: IWindowService, $scope: IScope, $element: JQLite, $parse: IParseService, $attrs: IAttributes, $document: IDocumentService, lozadAdvDefault: LozadAdvOptions, lozadAdvService: ILozadAdvService) => void;\nexport interface ILozadAdvCtrl extends IController {\n scroll: (entry: IntersectionObserverEntry, observer: IntersectionObserver) => void;\n lozad: (element: Element) => void;\n loadFn: () => void;\n}\n\n/*@ngInject*/\nconst LozadAdvCtrl: ILozadAdvCtrlFn = function ($window, $scope, $element, $parse, $attrs, $document, lozadAdvDefault, lozadAdvService) {\n const ctrl = this;\n let elementNative;\n const ctrlParams: LozadAdvParams = {} as LozadAdvParams;\n ctrl.$postLink = function () {\n elementNative = $element[0];\n ctrlParams.options = angular.extend({}, lozadAdvDefault, $parse($attrs.lozadAdvOptions)($scope));\n ctrlParams.lozadAdv = $parse($attrs.lozadAdv);\n ctrlParams.lozadObserverMode = $attrs.lozadObserverMode != null ? $parse($attrs.lozadObserverMode)($scope) : LOZAD_OBSERVER_MODE.default;\n ctrlParams.lozadAdvDebounce = $attrs.lozadAdvDebounce != null ? $parse($attrs.lozadAdvDebounce)($scope) : 500;\n ctrlParams.lozadAdvKey = $parse($attrs.lozadAdvKey)($scope);\n lozadAdvService.guardOptions(ctrlParams);\n if (ctrlParams.options.afterWindowLoaded &&\n // @ts-ignore: TODO: fix conflict type IDocumentService for angularjs\n $document[0].readyState !== 'complete') {\n $window.addEventListener('load', ctrl.loadFn);\n } else {\n ctrl.lozad(elementNative);\n }\n };\n ctrl.scroll = function (entry, observer) {\n if (lozadAdvService.isElementInViewport(entry.target, entry)) {\n if (ctrlParams.lozadObserverMode !== LOZAD_OBSERVER_MODE.observerAlways) {\n observer.unobserve(entry.target);\n }\n ctrlParams.options.load(entry.target);\n }\n ctrlParams.lozadAdv($scope, {\n entry,\n isVisible: lozadAdvService.isElementInViewport(entry.target, entry)\n });\n // timeout \u043D\u0443\u0436\u0435\u043D, \u0447\u0442\u043E\u0431\u044B \u043F\u043E\u043F\u0440\u0430\u0432\u0438\u0442\u044C \"$digest already in progress\" \u0432 \u0442\u0435\u0441\u0442\u0430\u0445.\n setTimeout(() => {\n $scope.$digest();\n }, 0);\n };\n ctrl.lozad = function lozad(element) {\n const wrapper = lozadAdvService.initObserver({\n lozadObserverMode: ctrlParams.lozadObserverMode,\n lozadAdvKey: ctrlParams.lozadAdvKey,\n options: ctrlParams.options\n });\n const callback = ctrlParams.lozadObserverMode !== \"observerAlways\" ? lozadAdvService.onIntersection((entry, observer) => {\n ctrl.scroll.bind(ctrl, entry, observer)();\n }, ctrlParams.lozadAdvDebounce) : ctrl.scroll;\n wrapper.observeWrapper(element, callback);\n };\n ctrl.loadFn = function loadFn() {\n $window.removeEventListener('load', ctrl.loadFn);\n ctrl.lozad(elementNative);\n };\n};\nLozadAdvCtrl.$inject = [\"$window\", \"$scope\", \"$element\", \"$parse\", \"$attrs\", \"$document\", \"lozadAdvDefault\", \"lozadAdvService\"];\nexport default LozadAdvCtrl;", "\uFEFFimport {IAttributes, IDirective, IDirectiveFactory, IScope} from \"angular\";\nimport {ILozadAdvCtrl} from \"./lozadAdv.ctrl\";\n\ninterface LozadAdvDirective extends IDirectiveFactory {\n\n}\n\nconst lozadAdv: LozadAdvDirective = function () {\n return {\n controller: 'LozadAdvCtrl',\n bindToController: true,\n controllerAs: 'lozadAdv',\n scope: true,\n };\n}\n\nexport default lozadAdv\n", "const copyProperty = (to, from, property, ignoreNonConfigurable) => {\n\t// `Function#length` should reflect the parameters of `to` not `from` since we keep its body.\n\t// `Function#prototype` is non-writable and non-configurable so can never be modified.\n\tif (property === 'length' || property === 'prototype') {\n\t\treturn;\n\t}\n\n\t// `Function#arguments` and `Function#caller` should not be copied. They were reported to be present in `Reflect.ownKeys` for some devices in React Native (#41), so we explicitly ignore them here.\n\tif (property === 'arguments' || property === 'caller') {\n\t\treturn;\n\t}\n\n\tconst toDescriptor = Object.getOwnPropertyDescriptor(to, property);\n\tconst fromDescriptor = Object.getOwnPropertyDescriptor(from, property);\n\n\tif (!canCopyProperty(toDescriptor, fromDescriptor) && ignoreNonConfigurable) {\n\t\treturn;\n\t}\n\n\tObject.defineProperty(to, property, fromDescriptor);\n};\n\n// `Object.defineProperty()` throws if the property exists, is not configurable and either:\n// - one its descriptors is changed\n// - it is non-writable and its value is changed\nconst canCopyProperty = function (toDescriptor, fromDescriptor) {\n\treturn toDescriptor === undefined || toDescriptor.configurable || (\n\t\ttoDescriptor.writable === fromDescriptor.writable\n\t\t&& toDescriptor.enumerable === fromDescriptor.enumerable\n\t\t&& toDescriptor.configurable === fromDescriptor.configurable\n\t\t&& (toDescriptor.writable || toDescriptor.value === fromDescriptor.value)\n\t);\n};\n\nconst changePrototype = (to, from) => {\n\tconst fromPrototype = Object.getPrototypeOf(from);\n\tif (fromPrototype === Object.getPrototypeOf(to)) {\n\t\treturn;\n\t}\n\n\tObject.setPrototypeOf(to, fromPrototype);\n};\n\nconst wrappedToString = (withName, fromBody) => `/* Wrapped ${withName}*/\\n${fromBody}`;\n\nconst toStringDescriptor = Object.getOwnPropertyDescriptor(Function.prototype, 'toString');\nconst toStringName = Object.getOwnPropertyDescriptor(Function.prototype.toString, 'name');\n\n// We call `from.toString()` early (not lazily) to ensure `from` can be garbage collected.\n// We use `bind()` instead of a closure for the same reason.\n// Calling `from.toString()` early also allows caching it in case `to.toString()` is called several times.\nconst changeToString = (to, from, name) => {\n\tconst withName = name === '' ? '' : `with ${name.trim()}() `;\n\tconst newToString = wrappedToString.bind(null, withName, from.toString());\n\t// Ensure `to.toString.toString` is non-enumerable and has the same `same`\n\tObject.defineProperty(newToString, 'name', toStringName);\n\tconst {writable, enumerable, configurable} = toStringDescriptor; // We destructue to avoid a potential `get` descriptor.\n\tObject.defineProperty(to, 'toString', {value: newToString, writable, enumerable, configurable});\n};\n\nexport default function mimicFunction(to, from, {ignoreNonConfigurable = false} = {}) {\n\tconst {name} = to;\n\n\tfor (const property of Reflect.ownKeys(from)) {\n\t\tcopyProperty(to, from, property, ignoreNonConfigurable);\n\t}\n\n\tchangePrototype(to, from);\n\tchangeToString(to, from, name);\n\n\treturn to;\n}\n", "import mimicFunction from 'mimic-function';\n\nconst debounceFunction = (inputFunction, options = {}) => {\n\tif (typeof inputFunction !== 'function') {\n\t\tthrow new TypeError(`Expected the first argument to be a function, got \\`${typeof inputFunction}\\``);\n\t}\n\n\tconst {\n\t\twait = 0,\n\t\tmaxWait = Number.POSITIVE_INFINITY,\n\t\tbefore = false,\n\t\tafter = true,\n\t} = options;\n\n\tif (wait < 0 || maxWait < 0) {\n\t\tthrow new RangeError('`wait` and `maxWait` must not be negative.');\n\t}\n\n\tif (!before && !after) {\n\t\tthrow new Error('Both `before` and `after` are false, function wouldn\\'t be called.');\n\t}\n\n\tlet timeout;\n\tlet maxTimeout;\n\tlet result;\n\n\tconst debouncedFunction = function (...arguments_) {\n\t\tconst context = this; // eslint-disable-line unicorn/no-this-assignment\n\n\t\tconst later = () => {\n\t\t\ttimeout = undefined;\n\n\t\t\tif (maxTimeout) {\n\t\t\t\tclearTimeout(maxTimeout);\n\t\t\t\tmaxTimeout = undefined;\n\t\t\t}\n\n\t\t\tif (after) {\n\t\t\t\tresult = inputFunction.apply(context, arguments_);\n\t\t\t}\n\t\t};\n\n\t\tconst maxLater = () => {\n\t\t\tmaxTimeout = undefined;\n\n\t\t\tif (timeout) {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t\ttimeout = undefined;\n\t\t\t}\n\n\t\t\tif (after) {\n\t\t\t\tresult = inputFunction.apply(context, arguments_);\n\t\t\t}\n\t\t};\n\n\t\tconst shouldCallNow = before && !timeout;\n\t\tclearTimeout(timeout);\n\t\ttimeout = setTimeout(later, wait);\n\n\t\tif (maxWait > 0 && maxWait !== Number.POSITIVE_INFINITY && !maxTimeout) {\n\t\t\tmaxTimeout = setTimeout(maxLater, maxWait);\n\t\t}\n\n\t\tif (shouldCallNow) {\n\t\t\tresult = inputFunction.apply(context, arguments_);\n\t\t}\n\n\t\treturn result;\n\t};\n\n\tmimicFunction(debouncedFunction, inputFunction);\n\n\tdebouncedFunction.cancel = () => {\n\t\tif (timeout) {\n\t\t\tclearTimeout(timeout);\n\t\t\ttimeout = undefined;\n\t\t}\n\n\t\tif (maxTimeout) {\n\t\t\tclearTimeout(maxTimeout);\n\t\t\tmaxTimeout = undefined;\n\t\t}\n\t};\n\n\treturn debouncedFunction;\n};\n\nexport default debounceFunction;\n", "import debounceFn from 'debounce-fn';\nimport { LozadAdvParams, LozadAdvObserverParams, LozadAdvObserverWrap, LozadAdvObservers } from \"./types\";\nimport { LOZAD_OBSERVER_MODE } from \"./lozadAdv.constants\";\nexport interface ILozadAdvService {\n guardOptions: (params: LozadAdvParams) => void;\n onIntersection: (callback: (entry: IntersectionObserverEntry, observer: IntersectionObserver) => void, debounceTime: LozadAdvParams[\"lozadAdvDebounce\"]) => (entry: IntersectionObserverEntry, observer: IntersectionObserver) => void;\n isElementInViewport: (element: Element, entry: IntersectionObserverEntry) => boolean;\n getHash: (options: Record) => string;\n initObserver: (params: LozadAdvObserverParams) => LozadAdvObserverWrap;\n reObserve: (key: string, element: HTMLElement) => boolean;\n lozadIntersectionCallback: (key: string) => (entry: IntersectionObserverEntry[], observer: IntersectionObserver) => void;\n}\nexport type ILozadAdvServiceFn = (this: ILozadAdvService) => void;\n\n//TODO: \u0435\u0441\u043B\u0438 \u0443\u043A\u0430\u0437\u0430\u043D \u0442\u043E\u043B\u044C\u043A\u043E this, \u0442\u043E \u0432 \u0442\u0435\u0441\u0442\u0430\u0445 \u043E\u043D \u043F\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044F \u0432 params. \u0443\u043A\u0430\u0437\u0430\u043B ngInject \u0443 \u0441\u0430\u043C\u043E\u0439 \u0444\u0443\u043D\u043A\u0446\u0438\u0438\nconst LozadAdvService: ILozadAdvServiceFn = /*@ngInject*/function () {\n const service = this;\n let observers: LozadAdvObservers = new Map();\n service.guardOptions = function (params: LozadAdvParams) {\n if (!['number', 'boolean'].includes(typeof params.lozadAdvDebounce)) {\n throw new Error(`[LozadAdv]: lozadAdvDebounce is number or boolean`);\n }\n if (!Object.keys(LOZAD_OBSERVER_MODE).includes(params.lozadObserverMode)) {\n throw new Error(`[LozadAdv]: mode \"${params.lozadObserverMode}\" not found`);\n }\n };\n service.onIntersection = function onIntersection(callback, debounceTime = 500) {\n return function (entry, observer) {\n if (entry.isIntersecting || service.isElementInViewport(entry.target, entry)) {\n if (debounceTime === false) {\n callback(entry, observer);\n return;\n } else if (debounceTime === true) {\n debounceTime = 500;\n }\n debounceFn(() => callback(entry, observer), {\n wait: debounceTime\n })();\n }\n };\n };\n\n //https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript\n service.getHash = function (options) {\n const optionsAsString = JSON.stringify(options);\n let hash = 0;\n for (let i = 0; i < optionsAsString.length; i++) {\n hash = (hash << 5) - hash + optionsAsString.charCodeAt(i);\n hash |= 0;\n }\n const hashString = Math.abs(hash).toString(36);\n const needFill = hashString.length < 10;\n const diffLength = 10 - hashString.length;\n return needFill ? new Array(diffLength).fill('0').join('') + hashString : hashString.slice(0, 10);\n };\n service.isElementInViewport = function isElementInViewport(el, entry) {\n var rect = entry.boundingClientRect;\n var windowHeight = window.innerHeight || document.documentElement.clientHeight;\n // http://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlap\n var vertInView = rect.top <= windowHeight && rect.top + rect.height >= 0;\n return vertInView;\n };\n service.lozadIntersectionCallback = key => function (entries, observer) {\n const observerWrap = observers.get(key);\n if (observerWrap == null) {\n console.warn(`Observer with key \"${key} not found\"`);\n return;\n }\n entries.forEach(entry => {\n const handler = observerWrap.params.handlers.find(({\n element\n }) => element === entry.target);\n if (handler) {\n handler.callback(entry, observer);\n }\n });\n };\n service.initObserver = params => {\n const {\n lozadAdvKey,\n options\n } = params;\n const _key = lozadAdvKey ?? service.getHash(options);\n let observerWrap = observers.get(_key);\n if (!observerWrap) {\n const observer = new IntersectionObserver(service.lozadIntersectionCallback(_key), options);\n observerWrap = {\n observerId: _key,\n observer,\n params: {\n ...params,\n handlers: []\n },\n observeWrapper: function (element, callback) {\n this.params.handlers.push({\n callback,\n element\n });\n this.observer.observe(element);\n }\n };\n observers.set(_key, observerWrap);\n }\n return observerWrap;\n };\n service.reObserve = (key, element) => {\n let observerWrap = observers.get(key);\n if (observerWrap) {\n observerWrap.observer.unobserve(element);\n observerWrap.observer.observe(element);\n return true;\n }\n return false;\n };\n};\nexport default LozadAdvService;", "\uFEFFimport LozadAdvCtrl from './lozadAdv.ctrl.ts';\nimport lozadAdvConstants from './lozadAdv.constants.ts';\nimport LozadAdv from './lozadAdv.directive.ts';\nimport LozadAdvService from './lozadAdv.service.ts';\n\nconst moduleName = `lozadAdv`;\n\nangular\n .module(moduleName, [])\n .constant(`lozadAdvDefault`, lozadAdvConstants)\n .controller(`LozadAdvCtrl`, LozadAdvCtrl)\n .service('lozadAdvService', LozadAdvService)\n .directive(`lozadAdv`, LozadAdv);\n\nexport default moduleName;\n", "@charset \"UTF-8\";\r\n/* https://www.smashingmagazine.com/2014/02/making-embedded-content-work-in-responsive-design/ */\r\niframe-responsive {\r\n display: block;\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n.mobile-version .video-embed {\r\n padding-bottom: 0;\r\n}\r\n\r\n.mobile-version .iframe-responsive--vk-clip iframe,\r\n.mobile-version .iframe-responsive--vk-clip .iframe-responsive__custom-play-wrap {\r\n max-width: 300px;\r\n max-height: 603px;\r\n}\r\n.mobile-version .iframe-responsive--vk-clip .video-embed {\r\n padding-bottom: 0;\r\n}\r\n\r\n.iframe-responsive--vk-clip .iframe-responsive__custom-play-wrap {\r\n max-width: 300px;\r\n}\r\n.iframe-responsive--vk-clip .embed-container {\r\n aspect-ratio: 9/16;\r\n max-width: 300px;\r\n}\r\n.iframe-responsive--vk-clip .iframe-responsive__container .iframe-responsive__custom-play {\r\n top: calc(50% - 30px);\r\n}\r\n.iframe-responsive--vk-clip iframe {\r\n max-width: 300px !important;\r\n}\r\n\r\n.iframe-responsive__container-wrap {\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n.iframe-responsive__container {\r\n position: relative;\r\n aspect-ratio: 16/9;\r\n width: 100%;\r\n height: 100%;\r\n}\r\n.iframe-responsive__container iframe {\r\n width: 100%;\r\n height: 100%;\r\n border: 0;\r\n}\r\n\r\n.embed-container {\r\n position: relative;\r\n aspect-ratio: 16/9;\r\n width: 100%;\r\n height: 100%;\r\n overflow: hidden;\r\n max-width: 100%;\r\n}\r\n\r\n.embed-container iframe,\r\n.embed-container object,\r\n.embed-container embed,\r\n.embed-container video {\r\n width: 100%;\r\n height: 100%;\r\n}\r\n\r\n/* .iframe-responsive__container iframe {\n display: block;\n width: 100%;\n position: relative;\n} */\r\n.iframe-responsive__container .iframe-responsive__custom-play {\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate3d(-50%, -50%, 0);\r\n z-index: 1;\r\n border-radius: 50%;\r\n /* border: 11px solid #fff; */\r\n background-color: #fff;\r\n width: 75px;\r\n height: 75px;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n}\r\n\r\n.iframe-responsive__custom-play-wrap {\r\n pointer-events: none; /* \u0427\u0442\u043E\u0431\u044B \u043A\u043B\u0438\u043A \u043F\u0440\u043E\u0438\u0441\u0445\u043E\u0434\u0438\u043B \u043F\u043E \u0432\u0438\u0434\u0435\u043E */\r\n cursor: pointer;\r\n position: absolute;\r\n top: 0;\r\n right: 0;\r\n bottom: 0;\r\n left: 0;\r\n text-align: center;\r\n z-index: 1;\r\n background-clip: border-box;\r\n background-color: rgba(0, 0, 0, 0);\r\n background-origin: padding-box;\r\n background-position-x: 50%;\r\n background-position-y: 50%;\r\n background-size: 100%;\r\n background-repeat: no-repeat;\r\n}\r\n\r\n.iframe-responsive__custom-play-icon {\r\n width: 52px;\r\n height: 52px;\r\n}\r\n\r\n.modal-video-icon {\r\n margin-right: 24px;\r\n}\r\n\r\n@media (max-width: 30em) {\r\n .iframe-responsive__container .iframe-responsive__custom-play {\r\n border: 2px solid #fff;\r\n }\r\n .iframe-responsive__custom-play-icon {\r\n width: 72px;\r\n height: 72px;\r\n }\r\n}\r\n.opacity {\r\n opacity: 0;\r\n}\r\n\r\n.iframe-responsive__container-upload video {\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n -o-object-fit: cover;\r\n object-fit: cover;\r\n}\r\n\r\n.embed-container.iframe-responsive__container-upload {\r\n /* padding: 0; */\r\n}\r\n\r\n.iframe-responsive__container--image {\r\n display: block !important;\r\n width: 100%;\r\n height: 100%;\r\n -o-object-fit: cover;\r\n object-fit: cover;\r\n background-repeat: no-repeat;\r\n background-size: cover;\r\n}\r\n\r\n/* .iframe-responsive__container + iframe-responsive__container--image {\n display: none !important;\n}\n\n@media(min-width: 48em) {\n .iframe-responsive__container + iframe-responsive__container--image {\n display: block !important;\n }\n} */", "function iframeResponsiveCtrl($sce, iframeResponsiveService, $scope, $timeout) {\n var ctrl = this,\n stateChangeFlag = true;\n ctrl.showContent = function () {\n ctrl.isShowContent = true;\n if (ctrl.deviceMobile && ctrl.asBackground) {\n if (ctrl.useVimeo) {\n var vimeoVideoId = iframeResponsiveService.getVideoIdFromVimeo(ctrl.src);\n iframeResponsiveService.getVimeoCover(vimeoVideoId).then(function (response) {\n if (response.data != null) {\n ctrl.coverVideoPath = response.data.thumbnail_url;\n }\n });\n } else if (ctrl.useYouTube) {\n var YTVideoId = iframeResponsiveService.getVideoIdFromYouTube(ctrl.src);\n ctrl.coverVideoPath = iframeResponsiveService.getYTCover(YTVideoId);\n }\n } else {\n if (ctrl.isPlayerCode) {\n ctrl.playerCode = ctrl.src;\n } else {\n ctrl.src = iframeResponsiveService.getSrc(ctrl.src);\n }\n ctrl.pasteVideo(ctrl.src, ctrl.autoplay, ctrl.loop);\n $scope.$digest();\n }\n };\n ctrl.pasteVideoForModal = function (src) {\n // ctrl.stopOthersVideo();\n ctrl.showVideo();\n ctrl.hideCover();\n if (ctrl.useYouTube) {\n src = iframeResponsiveService.getYouTubeCode(src, true);\n }\n if (ctrl.useVimeo) {\n src = iframeResponsiveService.getVimeoCode(src, true);\n }\n if (ctrl.useRutube) {\n src = iframeResponsiveService.getRutubeCode(src, true);\n }\n ctrl.iframeSrc = $sce.trustAsResourceUrl(src);\n };\n ctrl.onPlayerReady = function (event) {\n if (ctrl.autoplay) {\n ctrl.player.mute();\n ctrl.player.playVideo();\n }\n if (stateChangeFlag) {\n stateChangeFlag = false;\n }\n };\n ctrl.onPlayerStateChange = function (event) {\n ctrl.videoLoaded = true;\n if (event.data === -1) {\n ctrl.muteOn = true; // autoplay\n\n $timeout(function () {\n ctrl.hideCover();\n }, 100);\n } else if (event.data === 1) {\n if (!ctrl.disabledStop) {\n iframeResponsiveService.run(ctrl, 'youtube');\n }\n }\n };\n ctrl.showVideo = function () {\n ctrl.visibleVideo = true;\n };\n ctrl.hideVideo = function () {\n ctrl.visibleVideo = false;\n };\n ctrl.showCover = function () {\n ctrl.visibleCover = true;\n };\n ctrl.hideCover = function () {\n ctrl.visibleCover = false;\n };\n ctrl.stopOthersVideo = function () {\n if (!ctrl.disabledStop) {\n iframeResponsiveService.run(ctrl, 'vimeo');\n iframeResponsiveService.run(ctrl, 'youtube');\n }\n };\n ctrl.pasteYTIframeSrc = function (src, playerId, autoplay, loop) {\n var YTVideoId = iframeResponsiveService.getVideoIdFromYouTube(src);\n ctrl.coverVideoPath = iframeResponsiveService.getYTCover(YTVideoId);\n $timeout(function () {\n if (!iframeResponsiveService.checkInitYouTubeIframeAPI()) {\n iframeResponsiveService.addOnYouTubeIframeAPIReady().then(function () {\n ctrl.player = iframeResponsiveService.getYTPlayerAPI(playerId, YTVideoId, {\n onReady: ctrl.onPlayerReady,\n onStateChange: ctrl.onPlayerStateChange\n }, autoplay, loop);\n }).catch(function (error) {\n console.error(error);\n });\n } else {\n ctrl.player = iframeResponsiveService.getYTPlayerAPI(ctrl.playerId, YTVideoId, {\n onReady: ctrl.onPlayerReady,\n onStateChange: ctrl.onPlayerStateChange\n }, autoplay, loop);\n }\n });\n var YTCode = iframeResponsiveService.getYouTubeCode(src, autoplay, YTVideoId, loop);\n ctrl.iframeSrc = $sce.trustAsResourceUrl(YTCode);\n };\n ctrl.pasteVimeoIframeSrc = function (src, playerId, autoplay, loop) {\n var vimeoVideoId = iframeResponsiveService.getVideoIdFromVimeo(src);\n iframeResponsiveService.getVimeoCover(vimeoVideoId).then(function (response) {\n if (response.data != null) {\n ctrl.coverVideoPath = response.data.thumbnail_url;\n }\n });\n $timeout(function () {\n if (!iframeResponsiveService.checkInitVimeoIframeAPI()) {\n iframeResponsiveService.addVimeoIframeAPI().then(function () {\n ctrl.player = iframeResponsiveService.getVimeoPlayerAPI(playerId, vimeoVideoId, autoplay, loop);\n ctrl.player.on('play', function () {\n // ctrl.stopOthersVideo();\n iframeResponsiveService.run(ctrl, 'vimeo');\n ctrl.hideCover();\n $scope.$digest();\n });\n }).catch(function (error) {\n console.error(error);\n });\n } else {\n ctrl.player = iframeResponsiveService.getVimeoPlayerAPI(playerId, vimeoVideoId, autoplay, loop);\n }\n });\n };\n ctrl.pasteRutubeIframeSrc = function (link, playerId, autoplay, loop) {\n let videoId = iframeResponsiveService.getVideoIdFromRutube(link);\n $timeout(function () {\n let player = document.getElementById(playerId);\n if (player != null && (ctrl.player == null || ctrl.player.getId() !== playerId)) {\n ctrl.player = iframeResponsiveService.getRutubePlayer(playerId, {\n events: {\n onReady: ctrl.onPlayerReadyRutube,\n onStateChange: ctrl.onPlayerStateChangeRutube,\n onComplete: ctrl.onCompleteRutube\n }\n });\n }\n\n // if (ctrl.player != null) {\n // ctrl.stopOthersVideo();\n // }\n });\n let code = iframeResponsiveService.getRutubeCode(link, autoplay, videoId, loop);\n ctrl.iframeSrc = $sce.trustAsResourceUrl(code);\n };\n ctrl.pasteVkIframeSrc = function (link, playerId, autoplay, loop) {\n const [oid, id] = iframeResponsiveService.getVideoIdsFromVk(link);\n if (oid && id) {\n iframeResponsiveService.addVkAPI().then(() => {\n const src = `https://vk.com/video_ext.php?oid=${oid}&id=${id}&hd=2&autoplay=${autoplay ? '1' : '0'}&repeat=${loop ? '1' : '0'}&js_api=1`;\n ctrl.iframeSrc = $sce.trustAsResourceUrl(src);\n let iframe = document.getElementById(playerId);\n iframe.src = src;\n if (iframe) {\n ctrl.player = iframeResponsiveService.getVkPlayer(iframe);\n ctrl.player?.on('started', ctrl.onPlayerStateChangeVk);\n }\n }).catch(e => {\n throw new Error(e);\n });\n }\n };\n ctrl.pasteDzenIframeSrc = function (link, playerId, autoplay, loop) {\n ctrl.iframeSrc = $sce.trustAsResourceUrl(link + `?autoplay=${autoplay ? '1' : '0'}&loop=${loop ? '1' : '0'}`);\n };\n ctrl.onPlayerReadyRutube = function () {\n if (ctrl.autoplay) {\n try {\n ctrl.player.mute();\n ctrl.player.play();\n $timeout(function () {\n ctrl.hideCover();\n }, 100);\n } catch {\n /* tslint:disable:no-empty */\n }\n }\n };\n ctrl.onPlayerStateChangeVk = function (event) {\n if (event.state === 'playing') {\n ctrl.hideCover();\n $scope.$digest();\n }\n };\n ctrl.onPlayerStateChangeRutube = function (event) {\n if (event.playerState.PLAYING || event.playerState.PREROLL) {\n $timeout(function () {\n ctrl.hideCover();\n }, 100);\n }\n };\n ctrl.onCompleteRutube = function () {\n if (ctrl.loop) {\n try {\n ctrl.player.seekTo({\n time: 0\n });\n ctrl.player.play();\n } catch {\n /* tslint:disable:no-empty */\n }\n }\n };\n ctrl.pasteVideo = function (src, autoplay, loop) {\n ctrl.playerId = iframeResponsiveService.getPlayerId();\n if (ctrl.useYouTube) {\n ctrl.pasteYTIframeSrc(src, ctrl.playerId, autoplay, loop);\n }\n if (ctrl.useVimeo) {\n ctrl.pasteVimeoIframeSrc(src, ctrl.playerId, autoplay, loop);\n }\n if (ctrl.useRutube) {\n ctrl.pasteRutubeIframeSrc(src, ctrl.playerId, autoplay, loop);\n }\n if (ctrl.useVk) {\n ctrl.pasteVkIframeSrc(src, ctrl.playerId, autoplay, loop);\n }\n if (ctrl.useDzen) {\n ctrl.hideCover();\n ctrl.pasteDzenIframeSrc(src, ctrl.playerId, autoplay, loop);\n }\n };\n}\niframeResponsiveCtrl.$inject = [\"$sce\", \"iframeResponsiveService\", \"$scope\", \"$timeout\"];\nexport default iframeResponsiveCtrl;", "\uFEFFimport iframeResponsivePlayerCodeTemplate from './iframeResponsivePlayerCode.html';\nimport iframeResponsiveUploadTemplate from './iframeResponsiveUpload.html';\nimport iframeResponsiveUploadModalTemplate from './iframeResponsiveUploadModal.html';\nimport iframeResponsiveVideoTemplate from './iframeResponsiveVideo.html';\nimport iframeResponsiveVideoBackgroundTemplate from './iframeResponsiveVideoBackground.html';\n\nexport {\n iframeResponsivePlayerCodeTemplate,\n iframeResponsiveUploadTemplate,\n iframeResponsiveUploadModalTemplate,\n iframeResponsiveVideoTemplate,\n iframeResponsiveVideoBackgroundTemplate,\n};\n", "import * as tpls from '../templates/iframeResponsiveTemplates.js';\n\n/*@ngInject*/\nexport default function iframeResponsiveDirective(iframeResponsiveService, $templateRequest, $compile, urlHelper) {\n return {\n controller: 'IframeResponsiveCtrl',\n controllerAs: '$ctrl',\n bindToController: true,\n priority: 100,\n scope: {\n src: '@',\n videoWidth: '@',\n videoHeight: '@',\n autoplay: '
    '\n };\n}\niframeResponsiveDirective.$inject = [\"iframeResponsiveService\", \"$templateRequest\", \"$compile\", \"urlHelper\"];", "\uFEFFexport default function iframeResponsiveService($q, $window, $http) {\n var service = this,\n initializedYTList = [],\n initializedVimeoList = [],\n playerId = 0,\n regExpIsVkClip = /clip-\\d+_\\d+/,\n regExpVkId = /(?:video|clip)(-?\\d+)_(\\d+)/,\n regExpIdVideo = /(youtu.*be.*)\\/(watch\\?v=|embed\\/|v|shorts|)(.*?((?=[&#?])|$))/,\n regExpIdRutubeVideo = /(?:video|shorts|embed)\\/([a-zA-Z0-9]+)/,\n regExpIframe = new RegExp('(?:])'),\n regExpGetUrlFromSrc = new RegExp('(?:src=\").*?(?=[?\"])'),\n urlRegex = /(http[s]?:)?(\\/\\/)?(www\\.)?[a-zA-Z0-9]+\\.[^\\s]{2,}/,\n loadedYouTubeIframeAPI = false,\n loadedVimeoIframeAPI = false,\n activeItem;\n\n service.checkInitYouTubeIframeAPI = function () {\n return loadedYouTubeIframeAPI;\n };\n\n service.checkInitVimeoIframeAPI = function () {\n return loadedVimeoIframeAPI;\n };\n\n service.checkInitVkAPI = function () {\n return loadedVimeoIframeAPI;\n };\n\n service.addYouTubeIframeAPI = function () {\n var tag = document.createElement('script');\n tag.src = 'https://www.youtube.com/iframe_api';\n var firstScriptTag = document.getElementsByTagName('script')[0];\n firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n };\n\n service.addVimeoIframeAPI = function () {\n var defer = $q.defer();\n initializedVimeoList.push(defer);\n var tag = document.createElement('script');\n tag.src = 'https://www.youtube.com/iframe_api';\n tag.onload = function () {\n initializedVimeoList.forEach(function (defer) {\n defer.resolve();\n });\n loadedVimeoIframeAPI = true;\n };\n var firstScriptTag = document.getElementsByTagName('script')[0];\n firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n return defer.promise;\n };\n\n service.addOnYouTubeIframeAPIReady = function () {\n window.onYouTubeIframeAPIReady = function () {\n initializedYTList.forEach(function (defer) {\n defer.resolve();\n });\n loadedYouTubeIframeAPI = true;\n };\n var defer = $q.defer();\n initializedYTList.push(defer);\n if (!service.checkInitYouTubeIframeAPI()) {\n service.addYouTubeIframeAPI();\n }\n return defer.promise;\n };\n\n service.getPlayerId = function () {\n return 'player' + (playerId += 1);\n };\n\n service.getVideoIdFromYouTube = function (url) {\n return url.match(regExpIdVideo)[3];\n };\n\n service.getVideoIdFromVimeo = function (url) {\n var regexp =\n /(?:www\\.|player\\.)?vimeo.com\\/(?:channels\\/(?:\\w+\\/)?|groups\\/(?:[^\\/]*)\\/videos\\/|album\\/(?:\\d+)\\/video\\/|video\\/|)(\\d+)(?:[a-zA-Z0-9_\\-]+)?/i;\n return url.match(regexp)[1];\n };\n\n service.getYTPlayerAPI = function (elId, videoId, callbacks, autoplay, loop) {\n /* eslint-disable no-undef */\n return new YT.Player(elId, {\n videoId: videoId,\n playerVars: {\n enablejsapi: 1,\n html5: 1,\n fmt: 1,\n showinfo: 0,\n },\n events: callbacks,\n });\n };\n\n service.getVimeoPlayerAPI = function (elId, videoId, autoplay, loop) {\n /* eslint-disable no-undef */\n return new Vimeo.Player(elId, {\n id: videoId,\n autoplay: autoplay != null ? autoplay : false,\n muted: autoplay != null ? autoplay : false,\n loop: loop === true,\n });\n };\n\n service.run = function (obj, type) {\n if (activeItem != null && activeItem.obj !== obj && activeItem.obj.player != null) {\n if (activeItem.type === 'youtube') {\n activeItem.obj.player.pauseVideo();\n } else if (activeItem.type === 'vimeo') {\n activeItem.obj.player.pause();\n }\n if (activeItem.type === 'rutube') {\n activeItem.obj.player.pause();\n }\n }\n\n activeItem = {\n obj: obj,\n type: type,\n };\n };\n\n service.checkUrlFromIframe = function (url) {\n return url.match(regExpIframe);\n };\n\n service.getSrc = function (url) {\n if (service.checkUrlFromIframe(url)) {\n return url.match(regExpGetUrlFromSrc)[0].match(urlRegex)[0];\n }\n return url;\n };\n\n service.isPlayerCode = function (url) {\n return url.match(urlRegex) == null;\n };\n\n service.getYouTubeCode = function (link, autoplay, videoId, loop) {\n link = link.indexOf('https://') === -1 ? 'https://' + link : link;\n link = link.indexOf('www') === -1 ? 'https://www.' + link.split('https://')[1] : link;\n return (\n link.replace('youtu.be', 'youtube.com/embed/').replace('watch?v=', 'embed/').replace('shorts', 'embed').split('&')[0] +\n '?rel=0&enablejsapi=1&showinfo=0' +\n (autoplay || loop ? '&autoplay=1&mute=1&' : '') +\n (loop ? 'loop=1&controls=0&wmode=transparent&playlist=' + videoId + '' : '')\n );\n };\n\n service.getVimeoCode = function (link, autoplay, loop) {\n return (\n 'https://player.vimeo.com/video' +\n link.split('vimeo.com')[link.split('vimeo.com').length - 1] +\n '?title=0&byline=0&portrait=0' +\n (autoplay ? '&autoplay=1&muted=1' : '') +\n (loop ? '&loop=1' : '')\n );\n };\n\n service.getYTCover = function (YTVideoId) {\n return 'https://i.ytimg.com/vi/' + YTVideoId + '/maxresdefault.jpg';\n };\n\n service.getVimeoCover = function (vimeoId) {\n return $http\n .get('https://vimeo.com/api/oembed.json?url=https%3A//vimeo.com/' + vimeoId, {\n format: 'json',\n width: '1280',\n })\n .then(function (response) {\n return response;\n })\n .catch(function (error) {\n console.error(error);\n });\n };\n\n /// #region Rutube\n // https://github.com/rutube/RutubePlayerJSAPI\n // https://github.com/evikza/rutube-player/blob/main/rt.js\n\n service.getVideoIdFromRutube = function (url) {\n const match = url.match(regExpIdRutubeVideo);\n return match && match[1];\n };\n\n service.getRutubeCode = function (link, autoplay, loop) {\n const videoId = service.getVideoIdFromRutube(link);\n return `https://rutube.ru/play/embed/${videoId}?autoplay=${autoplay ? '1' : '0'}`;\n };\n\n const Rutube = function () {\n this.Player = function (id, config) {\n this.selector = id;\n this.config = config;\n };\n\n this.getId = function () {\n return this.selector;\n };\n\n this.triggerEventObserver = function (env, args = null) {\n if (!this.config.events || !this.config.events[env]) return;\n\n return this.config.events[env](args);\n };\n\n this.setPlayerState = function (status) {\n const playerState = {\n playerState: { PLAYING: 0, PAUSED: 0, STOPPED: 0, PREROLL: 0 },\n };\n\n for (let state in playerState.playerState) {\n if (state.toLowerCase() === status.toLowerCase()) {\n playerState.playerState[state] = 1;\n\n break;\n }\n }\n\n return playerState;\n };\n\n for (let [iterator, type] of Object.entries({\n play: 'play',\n pause: 'pause',\n stop: 'stop',\n seekTo: 'setCurrentTime',\n changeVideo: 'changeVideo',\n mute: 'mute',\n unMute: 'unMute',\n setVolume: 'setVolume',\n })) {\n this[iterator] = function (data = {}) {\n document.getElementById(this.selector).contentWindow.postMessage(\n JSON.stringify({\n type: 'player:' + type,\n data: data,\n }),\n '*',\n );\n };\n }\n\n this.playerEvent = function (receivedMessage) {\n switch (receivedMessage.type) {\n case 'player:ready':\n this.triggerEventObserver('onReady');\n break;\n\n case 'player:changeState':\n this.triggerEventObserver('onStateChange', this.setPlayerState(receivedMessage.data.state));\n break;\n\n case 'player:rollState': // \u0440\u0435\u043A\u043B\u0430\u043C\u0430\n this.triggerEventObserver('onStateChange', this.setPlayerState('preroll'));\n break;\n\n case 'player:playComplete':\n this.triggerEventObserver('onComplete');\n break;\n }\n };\n\n window.addEventListener(\n 'message',\n function (event) {\n const receivedMessage = JSON.parse(event.data);\n this.playerEvent(receivedMessage);\n }.bind(this),\n 0,\n );\n };\n\n service.getRutubePlayer = function (playerId, events) {\n let rt = new Rutube();\n rt.Player(playerId, events);\n return rt;\n };\n\n // #endregion\n\n service.getVideoIdsFromVk = function (url) {\n const ids = url.match(regExpVkId);\n if (ids.length) {\n return ids.slice(1);\n }\n };\n service.checkIsVkClip = function (url) {\n return regExpIsVkClip.test(url);\n };\n\n service.addVkAPI = function () {\n return new Promise((resolve) => {\n if (!service.checkInitVkAPI()) {\n const tag = document.createElement('script');\n tag.src = 'https://vk.com/js/api/videoplayer.js';\n const firstScriptTag = document.getElementsByTagName('script')[0];\n firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\n tag.onload = () => {\n resolve();\n };\n } else {\n resolve();\n }\n });\n };\n\n service.getVkPlayer = function (iframe) {\n return VK?.VideoPlayer(iframe);\n };\n}\n\niframeResponsiveService.$inject = ['$q', '$window', '$http'];\n", "\uFEFFimport lozadAdvModule from '../lozad-adv/lozadAdv.module.js';\n\nimport './styles/iframe-responsive.scss';\n\nimport iframeResponsiveCtrl from './controllers/iframeResponsiveController.js';\nimport iframeResponsiveDirective from './directives/iframeResponsiveDirective.js';\nimport iframeResponsiveService from './services/iframeResponsiveService.js';\n\nconst moduleName = 'iframeResponsive';\n\nangular\n .module(moduleName, [lozadAdvModule])\n .directive('iframeResponsive', iframeResponsiveDirective)\n .service('iframeResponsiveService', iframeResponsiveService)\n .controller('IframeResponsiveCtrl', iframeResponsiveCtrl);\n\nexport default moduleName;\n", "function VideosCtrl($http, $sce, $timeout) {\n var ctrl = this;\n ctrl.$onInit = function () {\n ctrl.getVideos();\n };\n ctrl.getVideos = function () {\n return $http.get('productExt/getvideos', {\n params: {\n productId: ctrl.productId\n }\n }).then(function (response) {\n ctrl.videos = response.data;\n for (var i = 0; i < ctrl.videos.length; i++) {\n ctrl.videos[i].PlayerCode = $sce.trustAsHtml(ctrl.videos[i].PlayerCode);\n }\n if (ctrl.onReceive != null) {\n $timeout(function () {\n ctrl.onReceive({});\n });\n }\n return response.data;\n });\n };\n}\nVideosCtrl.$inject = [\"$http\", \"$sce\", \"$timeout\"];\nexport default VideosCtrl;", "import videosTemplateTemplate from '../templates/videosTemplate.html';\nfunction videosDirective() {\n return {\n restrict: 'A',\n controller: 'VideosCtrl',\n controllerAs: 'videos',\n scope: {\n productId: '@',\n onReceive: '&',\n },\n bindToController: true,\n replace: true,\n templateUrl: videosTemplateTemplate,\n };\n}\n\nexport { videosDirective };\n", "\uFEFFimport iframeResponsive from '../../_common/iframe-responsive/iframeResponsive.module.js';\n\nimport VideosCtrl from './controllers/videosController.js';\nimport { videosDirective } from './directives/videosDirective.js';\n\nconst moduleName = 'videos';\n\nconst deps = [iframeResponsive];\n\nangular.module(moduleName, deps).controller('VideosCtrl', VideosCtrl).directive('videos', videosDirective);\n\nexport default moduleName;\n", ".zoomer {\r\n position: relative;\r\n display: inline-block;\r\n vertical-align: middle;\r\n}\r\n\r\n.zoomer-window {\r\n position: absolute;\r\n background-repeat: no-repeat;\r\n background-color: #fff;\r\n z-index: 5;\r\n}\r\n\r\n.zoomer-lens {\r\n position: absolute;\r\n background: rgba(0, 0, 0, 0.5);\r\n z-index: 15;\r\n}\r\n\r\n.zoomer-processing::after {\r\n content: \"\";\r\n position: absolute;\r\n top: 0;\r\n right: 0;\r\n bottom: 0;\r\n left: 0;\r\n background: rgba(255, 255, 255, 0.5);\r\n}\r\n\r\n.zoomer-inner + .zoomer-window {\r\n cursor: crosshair;\r\n}\r\n\r\n.zoomer-right + .zoomer-window {\r\n margin-left: 0.3125rem;\r\n}\r\n\r\n.zoomer-window-title {\r\n position: absolute;\r\n color: #fff;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n background: rgba(0, 0, 0, 0.5);\r\n text-align: center;\r\n white-space: normal;\r\n padding: 0.3125rem;\r\n}", "function ZoomerCtrl($element, $q, $window) {\n const ctrl = this,\n previewImageSize = {};\n ctrl.$onInit = function () {\n ctrl.isShowZoom = false;\n ctrl.isProcessing = false;\n ctrl.zoomPos = {\n left: 0,\n top: 0\n };\n ctrl.zoomSizes = {\n top: 0,\n left: 0,\n width: 0,\n height: 0,\n originalWidth: 0,\n originalHeight: 0\n };\n ctrl.zoomerSizes = {\n top: 0,\n left: 0,\n width: 0,\n height: 0\n };\n ctrl.lensSizes = {\n top: 0,\n left: 0,\n width: 0,\n height: 0\n };\n };\n ctrl.getSizePreview = function () {\n return {\n left: $element[0].offsetLeft,\n top: $element[0].offsetTop,\n width: $element[0].offsetWidth,\n height: $element[0].offsetHeight\n };\n };\n ctrl.getSizeOriginal = function (url) {\n return ctrl.getImage(url).then(function (image) {\n return {\n width: image.naturalWidth,\n height: image.naturalHeight\n };\n });\n };\n ctrl.getImage = function (url) {\n ctrl.isProcessing = true;\n const defered = $q.defer(),\n img = new Image();\n img.src = url;\n if (img.complete === true || typeof img.naturalWidth !== 'undefined' && img.naturalWidth > 0) {\n defered.resolve(img);\n } else {\n img.onload = function (e) {\n defered.resolve(img);\n };\n }\n return defered.promise.then(function (response) {\n ctrl.isProcessing = false;\n return response;\n });\n };\n ctrl.active = function (event) {\n event.preventDefault();\n event.stopPropagation();\n ctrl.getSizeOriginal(ctrl.originalPath).then(imageOriginalSize => ctrl.getSizeOriginal(ctrl.previewPath).then(imagePreviewSize => {\n return {\n imageOriginalSize,\n imagePreviewSize\n };\n })).then(function ({\n imageOriginalSize,\n imagePreviewSize\n }) {\n const previewSize = ctrl.getSizePreview();\n ctrl.zoomerSizes.left = previewSize.left;\n ctrl.zoomerSizes.top = previewSize.top;\n ctrl.zoomerSizes.width = previewSize.width;\n ctrl.zoomerSizes.height = previewSize.height;\n if (ctrl.type === 'inner') {\n ctrl.zoomSizes.top = previewSize.top;\n ctrl.zoomSizes.left = previewSize.left;\n ctrl.zoomSizes.height = previewSize.height;\n ctrl.zoomSizes.width = previewSize.width;\n } else {\n switch (ctrl.type) {\n case 'right':\n ctrl.zoomSizes.top = previewSize.top;\n ctrl.zoomSizes.left = previewSize.left + previewSize.width;\n break;\n case 'left':\n ctrl.zoomSizes.top = previewSize.top;\n ctrl.zoomSizes.left = previewSize.left - previewSize.width;\n break;\n default:\n ctrl.zoomSizes.top = previewSize.top;\n ctrl.zoomSizes.left = previewSize.left + previewSize.width;\n }\n const _zoomWidth = imagePreviewSize.width < ctrl.zoomWidth ? imagePreviewSize.width : ctrl.zoomWidth;\n const _zoomHeight = imagePreviewSize.height < ctrl.zoomHeight ? imagePreviewSize.width : ctrl.zoomHeight;\n ctrl.zoomSizes.width = _zoomWidth < imageOriginalSize.width ? _zoomWidth : imageOriginalSize.width;\n ctrl.zoomSizes.height = _zoomHeight < imageOriginalSize.height ? _zoomHeight : imageOriginalSize.height;\n }\n ctrl.zoomSizes.originalHeight = imageOriginalSize.height;\n ctrl.zoomSizes.originalWidth = imageOriginalSize.width;\n ctrl.isShowZoom = true;\n });\n };\n ctrl.update = function (event) {\n event.preventDefault();\n event.stopPropagation();\n let rect, pointX, pointY;\n rect = $element[0].getBoundingClientRect();\n pointX = event.pageX - (rect.left + $window.pageXOffset);\n pointY = event.pageY - (rect.top + $window.pageYOffset);\n if (ctrl.isShowZoom === true) {\n const scaleOriginal = ctrl.zoomSizes.originalWidth / ctrl.zoomerSizes.width,\n scalePreview = ctrl.zoomerSizes.width / ctrl.zoomSizes.originalWidth;\n ctrl.lensSizes.width = ctrl.zoomSizes.width * scalePreview;\n ctrl.lensSizes.height = ctrl.zoomSizes.height * scalePreview;\n const lensLeft = pointX - ctrl.lensSizes.width / 2,\n lensTop = pointY - ctrl.lensSizes.height / 2;\n const lensLimit = {\n left: 0,\n top: 0,\n right: ctrl.zoomerSizes.width - ctrl.lensSizes.width,\n bottom: ctrl.zoomerSizes.height - ctrl.lensSizes.height\n };\n if (lensTop < lensLimit.top) {\n ctrl.lensSizes.top = 0;\n } else if (lensTop > lensLimit.bottom) {\n ctrl.lensSizes.top = lensLimit.bottom;\n } else {\n ctrl.lensSizes.top = lensTop;\n }\n if (lensLeft < lensLimit.left) {\n ctrl.lensSizes.left = 0;\n } else if (lensLeft > lensLimit.right) {\n ctrl.lensSizes.left = lensLimit.right;\n } else {\n ctrl.lensSizes.left = lensLeft;\n }\n const zoomImageLeft = (ctrl.lensSizes.left + ctrl.lensSizes.width) * scaleOriginal,\n zoomImageTop = (ctrl.lensSizes.top + ctrl.lensSizes.height) * scaleOriginal;\n if (zoomImageLeft >= ctrl.zoomSizes.width) {\n ctrl.zoomPos.left = -(zoomImageLeft - ctrl.zoomSizes.width);\n }\n if (zoomImageTop >= ctrl.zoomSizes.height) {\n ctrl.zoomPos.top = -(zoomImageTop - ctrl.zoomSizes.height);\n }\n }\n };\n ctrl.deactive = function () {\n ctrl.isShowZoom = false;\n };\n ctrl.lensMove = ctrl.update;\n ctrl.getZoomerClass = function () {\n var obj = {};\n obj['zoomer-' + ctrl.type] = true;\n obj['zoomer-processing'] = ctrl.isProcessing;\n return obj;\n };\n}\nZoomerCtrl.$inject = [\"$element\", \"$q\", \"$window\"];\nexport default ZoomerCtrl;", "import zoomerWindowTemplate from '../templates/zoomerWindow.html';\nvar isTouchDevice = 'ontouchstart' in document.documentElement;\n\n/* @ngInject */\nfunction zoomerDirective($rootScope, $window, $compile, zoomerConfig) {\n return {\n restrict: 'A',\n scope: {\n previewPath: '=',\n originalPath: '=',\n type: '@',\n zoomWidth: '=?',\n zoomHeight: '=?',\n zoomerTitle: '=?'\n },\n replace: true,\n transclude: true,\n template: '',\n controller: 'ZoomerCtrl',\n controllerAs: 'zoomer',\n bindToController: true,\n link: function (scope, element, attrs, ctrl) {\n var init = function () {\n if (angular.isUndefined(ctrl.zoomWidth)) {\n ctrl.zoomWidth = zoomerConfig.zoomWidth;\n }\n if (angular.isUndefined(ctrl.zoomHeight)) {\n ctrl.zoomHeight = zoomerConfig.zoomHeight;\n }\n if (angular.isUndefined(ctrl.type)) {\n ctrl.type = zoomerConfig.type;\n }\n var scopeWindow = scope.$new(),\n zoomerWindow = angular.element('
    ');\n scopeWindow.parentScope = ctrl;\n element.after(zoomerWindow);\n $compile(zoomerWindow)(scopeWindow);\n ['touchstart', 'mouseenter'].forEach(function (eventName) {\n element[0].addEventListener(eventName, function (event) {\n ctrl.active(event);\n scope.$apply();\n });\n });\n ['touchmove', 'mousemove'].forEach(function (eventName) {\n element[0].addEventListener(eventName, function (event) {\n ctrl.update(event);\n scope.$apply();\n });\n });\n ['touchend', 'mouseleave'].forEach(function (eventName) {\n element[0].addEventListener(eventName, function (event) {\n ctrl.deactive(event);\n scope.$apply();\n });\n });\n if (ctrl.type !== 'inner') {\n var scopeLens = $rootScope.$new(),\n zoomerLens = angular.element('
    ');\n scopeLens.parentScope = ctrl;\n element.append(zoomerLens);\n $compile(zoomerLens)(scopeLens);\n }\n };\n if (document.readyState != `complete`) {\n $window.addEventListener('load', function load() {\n $window.removeEventListener('load', load);\n init();\n });\n } else {\n init();\n }\n }\n };\n}\nzoomerDirective.$inject = [\"$rootScope\", \"$window\", \"$compile\", \"zoomerConfig\"];\nfunction zoomerLensDirective() {\n return {\n //require: '^zoomer',\n restrict: 'A',\n replace: true,\n scope: true,\n template: \"
    \",\n link: function (scope, element, attrs, ctrl) {\n //var zoomerCtrl = ctrl;\n //element[0].addEventListener('touchmove', function (event) {\n // zoomerCtrl.update(event);\n // scope.$apply();\n //});\n }\n };\n}\nfunction zoomerWindowDirective() {\n return {\n restrict: 'A',\n replace: true,\n scope: true,\n templateUrl: zoomerWindowTemplate,\n link: function (scope, element, attrm, ctrls) {\n //var zoomerCtrl = ctrls[0];\n\n //element[0].addEventListener('mouseenter', zoomerCtrl.active);\n //element[0].addEventListener('mouseleave', zoomerCtrl.deactive);\n //element[0].addEventListener('mousemove', zoomerCtrl.update);\n\n if (scope.$parent.parentScope.type === 'inner') {\n ['touchstart', 'mouseenter'].forEach(function (eventName) {\n element[0].addEventListener(eventName, function (event) {\n scope.$parent.parentScope.active(event);\n scope.$apply();\n });\n });\n }\n ['touchmove', 'mousemove'].forEach(function (eventName) {\n element[0].addEventListener(eventName, function (event) {\n scope.$parent.parentScope.update(event);\n scope.$apply();\n });\n });\n ['touchend', 'mouseleave'].forEach(function (eventName) {\n element[0].addEventListener(eventName, function (event) {\n scope.$parent.parentScope.deactive(event);\n scope.$apply();\n });\n });\n }\n };\n}\nexport { zoomerDirective, zoomerLensDirective, zoomerWindowDirective };", "\uFEFFimport './styles/zoomer.scss';\n\nimport ZoomerCtrl from './controllers/zoomerController.js';\nimport { zoomerDirective, zoomerLensDirective, zoomerWindowDirective } from './directives/zoomerDirectives.js';\n\nconst moduleName = 'zoomer';\n\nangular\n .module(moduleName, [])\n .controller('ZoomerCtrl', ZoomerCtrl)\n .directive('zoomer', zoomerDirective)\n .directive('zoomerLens', zoomerLensDirective)\n .directive('zoomerWindow', zoomerWindowDirective)\n .constant('zoomerConfig', {\n zoomWidth: 350,\n zoomHeight: 350,\n type: 'right', // right/inner\n });\n\nexport default moduleName;\n", ".custom-options-list {\r\n display: table;\r\n width: 100%;\r\n table-layout: fixed;\r\n}\r\n.custom-options-row {\r\n display: table-row;\r\n}\r\n.custom-options-name, .custom-options-value {\r\n display: table-cell;\r\n vertical-align: middle;\r\n}\r\n.custom-options-name {\r\n padding: 0.3125rem 0.3125rem 0.3125rem 0;\r\n}\r\n.custom-options-value {\r\n padding: 0.3125rem 0 0.3125rem 0.3125rem;\r\n}\r\n.custom-options--additional-goods .custom-options-list {\r\n display: grid !important;\r\n grid-row-gap: 20px;\r\n row-gap: 20px;\r\n}\r\n.custom-options--additional-goods .custom-options-name,\r\n.custom-options--additional-goods .custom-options-list,\r\n.custom-options--additional-goods .custom-options-value,\r\n.custom-options--additional-goods .custom-options-row {\r\n display: block;\r\n}\r\n.custom-options--additional-goods .custom-options-name {\r\n padding: 0;\r\n display: grid;\r\n grid-row-gap: 10px;\r\n row-gap: 10px;\r\n}\r\n.custom-options--additional-goods .custom-options-name > label {\r\n font-weight: 600;\r\n font-size: 28px;\r\n line-height: 1.1 !important;\r\n}\r\n.custom-options--additional-goods .custom-options-value {\r\n padding: 0;\r\n}\r\n.custom-options--additional-goods .custom-options-inner {\r\n display: grid;\r\n grid-row-gap: 10px;\r\n row-gap: 10px;\r\n}\r\n.custom-options--additional-goods .custom-options-control {\r\n display: flex;\r\n align-items: center;\r\n -moz-column-gap: 16px;\r\n column-gap: 16px;\r\n padding: 16px 16px 16px 20px;\r\n border-radius: 15px;\r\n border-width: 1px;\r\n border-style: solid;\r\n border-color: transparent;\r\n background: #fff;\r\n}\r\n.custom-options--additional-goods .custom-options-control .adv-checkbox-emul,\r\n.custom-options--additional-goods .custom-options-control .adv-radio-emul {\r\n margin-right: 0;\r\n}\r\n.custom-options--additional-goods .custom-options-control .custom-input-native:focus ~ .custom-input-checkbox {\r\n box-shadow: none !important;\r\n}\r\n.custom-options--additional-goods .custom-options-control .custom-input-checkbox:hover,\r\n.custom-options--additional-goods .custom-options-control .custom-input-radio:hover {\r\n box-shadow: none !important;\r\n}\r\n.custom-options--additional-goods .custom-options-control--pointer {\r\n cursor: pointer;\r\n}\r\n.custom-options--additional-goods .custom-options-control-info {\r\n display: grid;\r\n grid-row-gap: 12px;\r\n row-gap: 12px;\r\n flex-grow: 1;\r\n}\r\n.custom-options--additional-goods .custom-options-img-wrap {\r\n max-width: 70px;\r\n}\r\n.custom-options--additional-goods .custom-options-img-wrap > img {\r\n display: block;\r\n}\r\n.custom-options--additional-goods .custom-options-text-header {\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n -moz-column-gap: 5px;\r\n column-gap: 5px;\r\n}\r\n.custom-options--additional-goods .custom-options-text {\r\n display: grid;\r\n grid-row-gap: 6px;\r\n row-gap: 6px;\r\n padding-top: 0 !important;\r\n}\r\n.custom-options--additional-goods .custom-options-price {\r\n font-size: 14px;\r\n font-weight: bolder;\r\n line-height: 1.1;\r\n}\r\n.custom-options--additional-goods .custom-options-title {\r\n font-size: 14px;\r\n font-weight: 600;\r\n line-height: 1.1;\r\n}\r\n.custom-options--additional-goods .custom-options-item-description {\r\n font-size: 14px;\r\n line-height: 1.2;\r\n}\r\n.custom-options--additional-goods .custom-options-item-counter {\r\n width: 110px;\r\n cursor: auto;\r\n}\r\n.custom-options--additional-goods .custom-options-item-counter .spinbox-input {\r\n pointer-events: none !important;\r\n}\r\n.custom-options--additional-goods .custom-options-item-counter .spinbox-button-disabled {\r\n opacity: 0.5;\r\n}", "function CustomOptionsCtrl(customOptionsService, toaster, $timeout, $q) {\n var ctrl = this,\n canceler = null,\n timeoutId;\n ctrl.$onInit = function () {\n customOptionsService.getData(ctrl.productId).then(function (customOptions) {\n ctrl.items = customOptions;\n $timeout(() => {\n customOptionsService.get(ctrl.productId, ctrl.items).then(function (data) {\n ctrl.xml = data.xml;\n ctrl.jsonHash = data.jsonHash;\n if (ctrl.initFn != null) {\n ctrl.initFn({\n customOptions: ctrl\n });\n }\n ctrl.changeFn();\n });\n }, 0);\n });\n };\n ctrl.eventDebounce = function (value, item, option, customOptionComboView = false) {\n if (timeoutId != null) {\n clearTimeout(timeoutId);\n }\n timeoutId = setTimeout(ctrl.change.bind(ctrl, value, item, option, customOptionComboView), 0);\n };\n ctrl.change = function (value, item, option, customOptionComboView = false) {\n if (value == null) {\n if (item.DefaultQuantity != null) {\n item.DefaultQuantity = item.MinQuantity || 0;\n } else {\n option.DefaultQuantity = option.MinQuantity || 0;\n }\n }\n if (option) {\n if (item.InputType === 6) {\n if (option.MaxQuantity > 1 && option.DefaultQuantity === 0) {\n option.Selected = false;\n }\n }\n if (item.InputType === 2) {\n if (item.MaxQuantity > 1) {\n item.Selected = !(option.DefaultQuantity === 0 && item.IsRequired === false);\n }\n }\n if (!ctrl.isValidQuantity(option.DefaultQuantity || 1, item, option)) {\n option.Selected = false;\n return;\n }\n }\n if (canceler) {\n canceler.resolve();\n }\n canceler = $q.defer();\n customOptionsService.get(ctrl.productId, ctrl.items, canceler.promise).then(function (data) {\n if (!data) return;\n ctrl.xml = data.xml;\n ctrl.jsonHash = data.jsonHash;\n ctrl.changeFn({\n item: item\n });\n });\n };\n ctrl.findSelectedOptionByOptionId = function (selectedOption, options) {\n return options.find(it => selectedOption.OptionId === it.OptionId);\n };\n ctrl.isValidQuantity = function (nextValueOption, item, option) {\n const isValid = customOptionsService.isValidAddOption(nextValueOption, item, option);\n if (isValid === false) {\n ctrl.notifyWarning(`\u0412\u044B \u043C\u043E\u0436\u0435\u0442\u0435 \u0432\u044B\u0431\u0440\u0430\u0442\u044C \u0438\u0437 \u044D\u0442\u043E\u0439 \u0433\u0440\u0443\u043F\u043F\u044B \u043D\u0435 \u0431\u043E\u043B\u044C\u0448\u0435 ${item.MaxQuantity} \u0442\u043E\u0432\u0430\u0440\u043E\u0432`);\n }\n return isValid;\n };\n ctrl.notifyWarning = function (text) {\n toaster.pop('warning', '', text);\n };\n ctrl.initSelect = function (item) {\n if (item.SelectedOptions != null) {\n if (item.InputType === 6 && item.SelectedOptions?.every(it => it.DefaultQuantity === 0)) {\n item.SelectedOptions.length = 0;\n } else {\n const selectedOptions = [];\n item.Options.forEach(function (option) {\n const selectedOption = item.SelectedOptions.find(selectedOption => selectedOption.OptionId === option.OptionId);\n if (!selectedOption) return;\n option.Selected = true;\n option.DefaultQuantity = selectedOption.DefaultQuantity;\n selectedOptions.push(option);\n });\n if (selectedOptions.length > 0) {\n item.SelectedOptions = selectedOptions;\n }\n }\n } else {\n item.SelectedOptions = item.IsRequired ? [item.Options[0]] : null;\n }\n };\n\n // \u0435\u0441\u043B\u0438 \u043D\u0435\u0442 label \u0434\u043B\u044F checkbox`a\n // \u0438\u0437 \u0437\u0430 label \u0432\u044B\u0437\u044B\u0432\u0430\u0435\u0442\u0441\u044F change 2 \u0440\u0430\u0437\u0430 (\u043E\u0442 spinbox \u0438 label)\n ctrl.selectOption = function (item, option) {\n if (item.InputType === 2 && (item.MaxQuantity === 1 || item.MaxQuantity == null)) {\n item.Selected = !item.Selected;\n ctrl.change(item.Selected, item, option);\n }\n };\n}\nCustomOptionsCtrl.$inject = [\"customOptionsService\", \"toaster\", \"$timeout\", \"$q\"];\nexport default CustomOptionsCtrl;", "import customOptionsTemplate from '../templates/customOptions.html';\n\n/* @ngInject */\nfunction customOptionsDirective(urlHelper) {\n return {\n scope: {\n productId: '<',\n initFn: '&',\n changeFn: '&',\n beforeChangeFn: '&',\n customOptionPicture: ' {\n if (reason?.xhrStatus !== 'abort') {\n console.error(reason);\n }\n });\n };\n service.getSelectedOptions = function (items) {\n let selectedOptions = [];\n for (let i = 0; i < items.length; i++) {\n const customOption = items[i];\n switch (customOption.InputType) {\n // DropDownList, RadioButton\n case 0:\n case 1:\n if (customOption.SelectedOptions != null) {\n if (Array.isArray(customOption.SelectedOptions)) {\n if (customOption.SelectedOptions.length > 0 && customOption.SelectedOptions[0] != null) {\n // \u0440\u0430\u0434\u0438\u043E \u043A\u043D\u043E\u043F\u043A\u0430 \u043D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D\u043D\u0430\u044F \u0438\u043C\u0435\u0435\u0442 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 0\n customOption.SelectedOptions[0].DefaultQuantity = customOption.SelectedOptions[0].DefaultQuantity || 1;\n selectedOptions.push(customOption.SelectedOptions[0]);\n }\n } else {\n customOption.SelectedOptions.DefaultQuantity = customOption.SelectedOptions.DefaultQuantity || 1;\n selectedOptions.push(customOption.SelectedOptions);\n }\n }\n break;\n // TextBoxSingleLine, TextBoxMultiLine\n case 4:\n case 3:\n if (customOption.SelectedOptions != null && customOption.SelectedOptions?.OptionText.length) {\n selectedOptions.push(customOption.SelectedOptions);\n }\n break;\n //CheckBox\n case 2:\n if (customOption.Selected || customOption.IsRequired) {\n customOption.Options[0].DefaultQuantity = customOption.Options[0].DefaultQuantity || 1;\n selectedOptions.push(customOption.Options[0]);\n }\n break;\n //ChoiceOfProduct\n case 5:\n if (customOption.SelectedOptions != null && customOption.SelectedOptions.length > 0 && customOption.SelectedOptions[0] != null) {\n selectedOptions.push(customOption.SelectedOptions[0]);\n } else {\n for (let j = 0; j < customOption.Options.length; j++) {\n var option = customOption.Options[j];\n if (option.MaxQuantity > 0 && option.DefaultQuantity > 0) {\n selectedOptions.push(option);\n }\n }\n }\n break;\n // MultiCheckBox\n case 6:\n for (let j = 0; j < customOption.Options.length; j++) {\n var chekboxOption = customOption.Options[j];\n if (!chekboxOption.Selected) {\n continue;\n }\n if (chekboxOption.MaxQuantity === 1) {\n chekboxOption.DefaultQuantity = 1;\n }\n selectedOptions.push(chekboxOption);\n }\n break;\n default:\n throw Error('Not found InputType for custom options: ' + customOption.InputType);\n }\n }\n return selectedOptions;\n };\n service.isValidAddOption = function (nextValueOption, item, option) {\n if (item.MaxQuantity == null) return true;\n const {\n InputType,\n Options,\n MaxQuantity\n } = item;\n let isValid = true;\n if (InputType === 1) {\n isValid = MaxQuantity >= nextValueOption;\n } else if (InputType === 5) {\n const count = Options.reduce((prev, cur) => prev + (cur.OptionId === option.OptionId ? nextValueOption : cur.DefaultQuantity), 0);\n isValid = MaxQuantity >= count;\n } else if (InputType === 6) {\n const countAllSelected = Options.reduce((prev, cur) => prev + (cur.Selected && cur.OptionId !== option.OptionId ? cur.DefaultQuantity || 1 : 0), 0);\n const count = countAllSelected + nextValueOption;\n isValid = MaxQuantity >= count;\n }\n return isValid;\n };\n service.isValidOptions = function (options) {\n const invalidOptions = new Set();\n let isValidOptions = true;\n options.forEach(it => {\n let isValid = true;\n const {\n MinQuantity,\n MaxQuantity,\n InputType,\n SelectedOptions,\n Options,\n IsRequired\n } = it;\n const getTotalCount = filterFn => Options.reduce((prev, cur) => prev + (filterFn(cur) ? cur.DefaultQuantity || 1 : 0), 0);\n if (MinQuantity != null && MaxQuantity != null) {\n if (InputType === 0 || InputType === 1) {\n if (SelectedOptions?.length > 0 && SelectedOptions[0] != null) {\n isValid = MinQuantity <= SelectedOptions[0].DefaultQuantity && MaxQuantity >= SelectedOptions[0].DefaultQuantity;\n }\n } else if (InputType === 5) {\n const count = getTotalCount(() => true);\n isValid = MinQuantity <= count && MaxQuantity >= count;\n } else if (InputType === 6) {\n const count = getTotalCount(cur => cur.Selected);\n isValid = IsRequired ? count > 0 && MinQuantity <= count && MaxQuantity >= count : MinQuantity <= count && MaxQuantity >= count;\n }\n } else if (InputType === 6) {\n const count = getTotalCount(cur => cur.Selected);\n if (IsRequired && count === 0) {\n isValid = false;\n }\n }\n if (!isValid) {\n isValidOptions = false;\n invalidOptions.add(it);\n }\n });\n return {\n invalidOptions,\n isValidOptions\n };\n };\n service.isEqualCustomOptions = function (target, other) {\n /** @type{(t: IEvaluatedCustomOptions, o: IEvaluatedCustomOptions) => boolean }*/\n const compareOptionsId = (_target, _other) => {\n return _target.CustomOptionId === _other.CustomOptionId && _other.OptionId === _target.OptionId;\n };\n /** @type{(t: IEvaluatedCustomOptions, o: IEvaluatedCustomOptions) => boolean }*/\n const compareOptionValue = (_target, _other) => {\n if (_other.OptionAmount == null && _target.OptionAmount == null) {\n return _other.OptionTitle === _target.OptionTitle;\n }\n return _other.OptionAmount === _target.OptionAmount;\n };\n return target.every(t => {\n return other.find(o => compareOptionsId(t, o) && compareOptionValue(t, o));\n });\n };\n service.customOptionItemToEvaluatedCustomOptionsMapper = options => {\n return options.map(x => {\n return {\n CustomOptionId: x.CustomOptionsId,\n OptionId: x.OptionId,\n OptionAmount: x.DefaultQuantity,\n OptionTitle: x.OptionText,\n OptionPriceBc: x.PriceString,\n CustomOptionTitle: x.Title\n };\n });\n };\n}\ncustomOptionsService.$inject = [\"$http\", \"urlHelper\"];\nexport default customOptionsService;", "\uFEFFimport './styles/customOptions.scss';\n\nimport CustomOptionsCtrl from './controllers/customOptionsController.js';\nimport { customOptionsDirective } from './directives/customOptionsDirectives.js';\nimport customOptionsService from './services/customOptionsService.js';\n\nconst moduleName = 'customOptions';\n\nangular\n .module(moduleName, [])\n .controller('CustomOptionsCtrl', CustomOptionsCtrl)\n .directive('customOptions', customOptionsDirective)\n .service('customOptionsService', customOptionsService);\n\nexport default moduleName;\n", ".color-viewer-item {\r\n line-height: 0;\r\n font-size: 0;\r\n display: inline-block;\r\n padding: 0.0625rem;\r\n /* margin: rem-calc(1px); */\r\n box-sizing: border-box;\r\n border: 1px transparent solid;\r\n vertical-align: middle;\r\n}\r\n\r\n.color-viewer-item,\r\n.color-viewer-inner {\r\n border-radius: 0.1875rem;\r\n position: relative;\r\n cursor: pointer;\r\n}\r\n\r\n.color-viewer-alt .color-viewer-inner {\r\n width: auto !important;\r\n height: auto !important;\r\n padding: 10px;\r\n font-size: 12px;\r\n line-height: 1;\r\n background: transparent !important;\r\n border: 0;\r\n}\r\n\r\n.color-viewer-inner {\r\n display: inline-flex;\r\n background-repeat: no-repeat;\r\n margin: 2px;\r\n background-size: 100% 100%;\r\n border-width: 1px;\r\n border-style: solid;\r\n}\r\n\r\n.color-viewer-header {\r\n font-size: 0.75rem;\r\n margin-bottom: 0.3125rem;\r\n}\r\n\r\n.carousel-colors-wrap {\r\n text-align: center;\r\n}\r\n.carousel-colors-wrap .carousel-inner {\r\n padding: 0;\r\n /* padding: 0 1px; */\r\n}\r\n\r\n.color-viewer-list,\r\n.color-viewer {\r\n display: flex;\r\n flex-wrap: wrap;\r\n /* justify-content: center; */\r\n}\r\n\r\n.carousel-colors {\r\n padding: 0 1.25rem;\r\n}\r\n.carousel-colors.carousel-nav-not-show {\r\n padding: 0;\r\n}\r\n.carousel-colors .color-viewer-list {\r\n flex-wrap: nowrap;\r\n}\r\n\r\n.carousel-colors:not(.carousel-nav-not-show) .carousel-inner,\r\n.products-view-tile .carousel-colors .carousel-inner {\r\n margin-left: auto;\r\n margin-right: auto;\r\n}\r\n\r\n.products-view .carousel-colors {\r\n display: block;\r\n max-width: 100%;\r\n}\r\n\r\n.products-view-tile .carousel-colors.carousel-initilized {\r\n display: block;\r\n}\r\n\r\n.color-viewer-item-block {\r\n border: 1px transparent solid;\r\n display: inline-flex;\r\n cursor: pointer;\r\n border-radius: 0.1875rem;\r\n padding: 2px;\r\n align-items: center;\r\n justify-content: center;\r\n box-sizing: border-box;\r\n width: 100%;\r\n vertical-align: middle;\r\n}\r\n\r\n.color-viewer-item-wrap {\r\n padding: 2px;\r\n vertical-align: middle;\r\n box-sizing: border-box;\r\n flex-shrink: 0;\r\n}\r\n\r\n.color-viewer-item-name {\r\n font-size: 13px;\r\n box-sizing: border-box;\r\n line-height: 1;\r\n}\r\n\r\n.color-viewer-inner + .color-viewer-item-name {\r\n padding-left: 5px;\r\n}\r\n\r\n.color-viewer__color-selected-name {\r\n flex-basis: 100%;\r\n}\r\n\r\n.color-viewer-item-disabled {\r\n position: relative;\r\n pointer-events: none;\r\n color: #94969b;\r\n}\r\n\r\n.color-viewer--icon .color-viewer-item-disabled .color-viewer-inner::after,\r\n.color-viewer--iconandtext .color-viewer-item-disabled .color-viewer-inner::after {\r\n position: absolute;\r\n top: 0;\r\n right: 0;\r\n bottom: 0;\r\n left: 0;\r\n content: \"\";\r\n display: block;\r\n cursor: default;\r\n pointer-events: none;\r\n background-color: rgba(255, 255, 255, 0.7);\r\n background-size: 100% 100%;\r\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 460.775 460.775' style='enable-background:new 0 0 460.775 460.775' xml:space='preserve'%3E%3Cpath fill='red' d='M285.08 230.397 456.218 59.27c6.076-6.077 6.076-15.911 0-21.986L423.511 4.565a15.55 15.55 0 0 0-21.985 0l-171.138 171.14L59.25 4.565a15.551 15.551 0 0 0-21.985 0L4.558 37.284c-6.077 6.075-6.077 15.909 0 21.986l171.138 171.128L4.575 401.505c-6.074 6.077-6.074 15.911 0 21.986l32.709 32.719a15.555 15.555 0 0 0 21.986 0l171.117-171.12 171.118 171.12a15.551 15.551 0 0 0 21.985 0l32.709-32.719c6.074-6.075 6.074-15.909 0-21.986L285.08 230.397z'/%3E%3C/svg%3E\");\r\n}\r\n\r\n.colors-viewer--in-filter.color-viewer--iconandtext, .colors-viewer--in-filter.color-viewer--text {\r\n justify-content: start;\r\n}\r\n.colors-viewer--in-filter.color-viewer--iconandtext .color-viewer-item-wrap, .colors-viewer--in-filter.color-viewer--text .color-viewer-item-wrap {\r\n flex-grow: 1;\r\n flex-basis: 100%;\r\n}\r\n.colors-viewer--in-filter.color-viewer--iconandtext .color-viewer-item-block, .colors-viewer--in-filter.color-viewer--text .color-viewer-item-block {\r\n justify-content: start;\r\n}\r\n.colors-viewer--in-filter.color-viewer--iconandtext .color-viewer-item-selected, .colors-viewer--in-filter.color-viewer--text .color-viewer-item-selected {\r\n border-color: transparent !important;\r\n}\r\n.colors-viewer--in-filter.color-viewer--iconandtext .color-viewer-item-wrap,\r\n.colors-viewer--in-filter.color-viewer--iconandtext .color-viewer-item-block, .colors-viewer--in-filter.color-viewer--text .color-viewer-item-wrap,\r\n.colors-viewer--in-filter.color-viewer--text .color-viewer-item-block {\r\n padding: 0;\r\n}\r\n.colors-viewer--in-filter.color-viewer--iconandtext.color-viewer--text .color-viewer-item-wrap, .colors-viewer--in-filter.color-viewer--text.color-viewer--text .color-viewer-item-wrap {\r\n padding-top: 3px;\r\n padding-bottom: 3px;\r\n}\r\n.colors-viewer--in-filter.color-viewer--icon {\r\n margin-left: -8px;\r\n}\r\n\r\n.select-custom .color-viewer-item-block,\r\n.select-custom .color-viewer-item-wrap {\r\n border: 0;\r\n padding: 0;\r\n}\r\n.select-custom .color-viewer-item-name {\r\n font-size: inherit;\r\n}\r\n.select-custom .color-viewer-inner {\r\n max-width: 50px;\r\n max-height: 50px;\r\n}\r\n\r\n[ng-transclude-slot=colorsViewerItemBefore]:empty {\r\n display: none;\r\n}", "function ColorsViewerCtrl($element, $scope, $transclude) {\n var ctrl = this,\n stopLoop = false,\n isFindedByStart = false,\n findedStartColorById,\n findedStartColorByIdAndMain;\n ctrl.$onInit = function () {\n ctrl.dirty = false;\n ctrl.multiselect = ctrl.multiselect === true;\n if (ctrl.multiselect === true) {\n ctrl.colorSelected = [];\n if (ctrl.colors != null && ctrl.colors.length > 0) {\n for (var i = 0, len = ctrl.colors.length; i < len; i++) {\n if (ctrl.colors[i].Selected === true) {\n ctrl.colorSelected.push(ctrl.colors[i]);\n }\n }\n }\n ctrl.colorSelectedNamesList = ctrl.colorSelected.join(',');\n } else {\n if (ctrl.startSelectedColors != null && ctrl.startSelectedColors.length > 0) {\n for (var s = 0, lenS = ctrl.startSelectedColors.length; s < lenS; s++) {\n for (var c = 0, lenC = ctrl.colors.length; c < lenC; c++) {\n if (ctrl.colors[c].ColorId === ctrl.startSelectedColors[s]) {\n if (ctrl.colors[c].Main === 1) {\n findedStartColorByIdAndMain = ctrl.colors[c];\n stopLoop = true;\n } else if (findedStartColorById == null) {\n findedStartColorById = ctrl.colors[c];\n }\n isFindedByStart = true;\n }\n }\n if (stopLoop === true) {\n stopLoop = false;\n break;\n }\n }\n }\n if (isFindedByStart === false) {\n for (var m = 0, l = ctrl.colors.length; m < l; m++) {\n if (ctrl.colors[m].Main == true) {\n ctrl.colorSelected = ctrl.colors[m];\n break;\n }\n }\n if (ctrl.colorSelected == null) {\n ctrl.colorSelected = ctrl.colors[0];\n }\n } else {\n ctrl.colorSelected = findedStartColorByIdAndMain || findedStartColorById;\n }\n }\n if (ctrl.initColors != null) {\n ctrl.initColors({\n colorsViewer: ctrl\n });\n }\n };\n ctrl.$postLink = function () {\n if (ctrl.carousel != null) {\n var colorSelectedFirst = ctrl.multiselect ? ctrl.colorSelected[0] : ctrl.colorSelected;\n var colorSelectedFirstIndex = ctrl.colors.indexOf(colorSelectedFirst);\n ctrl.carousel.load = true;\n ctrl.carousel.whenCarouselInit().then(function (carousel) {\n carousel.carouselNative.setItemSelect(colorSelectedFirstIndex);\n carousel.carouselNative.goto(colorSelectedFirstIndex, false);\n });\n }\n };\n ctrl.getImagePath = function (photoName) {\n return photoName.indexOf('://') != -1 ? photoName : 'pictures/color/' + ctrl.imageType.toLowerCase() + '/' + photoName;\n };\n ctrl.selectColor = function (event, color) {\n var indexInSelectedArray;\n if (ctrl.multiselect === true) {\n indexInSelectedArray = ctrl.colorSelected.indexOf(color);\n if (indexInSelectedArray > -1) {\n ctrl.colorSelected.splice(indexInSelectedArray, 1);\n //\u0441\u0432\u043E\u0439\u0441\u0442\u0432\u043E \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0441\u044F \u0432 \u0444\u0438\u043B\u044C\u0442\u0440\u0430\u0445\n color.Selected = false;\n } else {\n ctrl.colorSelected.push(color);\n //\u0441\u0432\u043E\u0439\u0441\u0442\u0432\u043E \u0438\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0435\u0442\u0441\u044F \u0432 \u0444\u0438\u043B\u044C\u0442\u0440\u0430\u0445\n color.Selected = true;\n }\n ctrl.colorSelectedNamesList = ctrl.colorSelected.join(',');\n } else {\n ctrl.colorSelected = color;\n }\n ctrl.dirty = true;\n ctrl.changeColor({\n event: event,\n color: color\n });\n };\n ctrl.selectColorById = function (colorId) {\n var color = ctrl.colors.filter(function (x) {\n return x.ColorId == colorId;\n });\n if (color != null && color.length > 0) {\n ctrl.selectColor(null, color[0]);\n }\n };\n ctrl.getDirtyState = function () {\n return ctrl.dirty;\n };\n}\nColorsViewerCtrl.$inject = [\"$element\", \"$scope\", \"$transclude\"];\nexport default ColorsViewerCtrl;", "import colorsTemplate from '../templates/colors.html';\nimport colorsSelectTemplate from '../templates/colorsSelect.html';\nfunction colorsViewerDirective() {\n return {\n require: {\n carousel: '?^carousel'\n },\n restrict: 'A',\n replace: true,\n templateUrl: (element, attrs) => attrs?.controlType === 'select' ? colorsSelectTemplate : colorsTemplate,\n controller: 'ColorsViewerCtrl',\n controllerAs: 'colorsViewer',\n bindToController: true,\n transclude: {\n colorsViewerItemBefore: '?colorsViewerItemBefore'\n },\n scope: {\n colors: '=',\n colorSelected: '=?',\n startSelectedColors: ' {\n return {\n controllerAs: 'colorsViewerItemBefore',\n controller: [\"$scope\", function ($scope) {\n const ctrl = this;\n ctrl.$onInit = function () {\n $scope.$itemScope = findPropertyInScope($scope, `color`);\n };\n }]\n };\n};\nexport { colorsViewerDirective, colorsViewerItemBeforeComponent };\nconst findPropertyInScope = (scope, propertyName) => {\n let result;\n let item = scope;\n while (item != null) {\n if (item[propertyName] != null) {\n result = item;\n break;\n } else {\n item = item.$parent;\n }\n }\n return result;\n};", "\uFEFFimport './styles/colors-viewer.scss';\n\nimport ColorsViewerCtrl from './controllers/colorsViewerController.js';\nimport { colorsViewerDirective, colorsViewerItemBeforeComponent } from './directives/colorsViewerDirectives.js';\n\nconst moduleName = 'colorsViewer';\n\nangular\n .module(moduleName, [])\n .controller('ColorsViewerCtrl', ColorsViewerCtrl)\n .directive('colorsViewer', colorsViewerDirective)\n .directive('colorsViewerItemBefore', colorsViewerItemBeforeComponent);\n\nexport default moduleName;\n", ".sizes-viewer-block {\r\n display: inline-block;\r\n text-align: center;\r\n}\r\n\r\n.sizes-viewer-item,\r\n.sizes-viewer-inner {\r\n border-radius: 0.1875rem;\r\n position: relative;\r\n cursor: pointer;\r\n}\r\n\r\n.sizes-viewer-item {\r\n border: 1px transparent solid;\r\n display: inline-block;\r\n}\r\n\r\n.sizes-viewer-inner {\r\n margin: 0.25rem;\r\n line-height: 1;\r\n padding: 0.3125rem;\r\n font-size: 0.875rem;\r\n}\r\n\r\n.sizes-viewer-selector {\r\n font-size: 0;\r\n line-height: 0;\r\n}\r\n\r\n.sizes-viewer-radio {\r\n border: 0;\r\n padding: 0;\r\n margin: 0;\r\n top: 0;\r\n left: 0;\r\n width: 100%;\r\n height: 100%;\r\n opacity: 0;\r\n cursor: pointer;\r\n position: absolute;\r\n}\r\n\r\n.sizes-viewer-block-slider {\r\n padding: 0 20px;\r\n}\r\n\r\n.sizes-viewer-header {\r\n font-size: 0.75rem;\r\n margin-bottom: 0.3125rem;\r\n}\r\n\r\n.sizes-viewer-item-disabled {\r\n opacity: 0.5;\r\n cursor: default;\r\n}", "\uFEFFfunction SizesViewerCtrl() {\n var ctrl = this;\n\n ctrl.$onInit = function () {\n if (ctrl.startSelectedSizes != null && ctrl.startSelectedSizes.length > 0) {\n for (var s = 0, lenS = ctrl.startSelectedSizes.length; s < lenS; s++) {\n for (var c = 0, lenC = ctrl.sizes.length; c < lenC; c++) {\n if (ctrl.sizes[c].SizeId === ctrl.startSelectedSizes[s]) {\n ctrl.sizeSelected = ctrl.sizes[c];\n break;\n }\n }\n }\n }\n\n ctrl.initSizes({ sizesViewer: ctrl });\n };\n}\n\nexport default SizesViewerCtrl;\n", "import sizesTemplate from '../templates/sizes.html';\nimport sizesSelectTemplate from '../templates/sizesSelect.html';\nfunction sizesViewerDirective() {\n return {\n restrict: 'A',\n replace: true,\n templateUrl: (element, attrs) => (attrs?.controlType === 'select' ? sizesSelectTemplate : sizesTemplate),\n controller: 'SizesViewerCtrl',\n controllerAs: 'sizesViewer',\n bindToController: true,\n scope: {\n sizes: ' 0) {\n toaster.pop('error', null, result.error);\n if (captchaExist) {\n CaptchaSourceBuyInOneClick.ReloadImage();\n }\n } else {\n ctrl.result = result;\n ctrl.success = true;\n ctrl.successFn({\n result: result\n });\n if (ctrl.autoReset != null) {\n $timeout(ctrl.reset, ctrl.autoReset);\n }\n }\n ctrl.process = false;\n });\n }\n };\n ctrl.initCaptcha = function (ngModel) {\n return $http.post('/commonExt/getCaptchaHtml', {\n ngModel: ngModel,\n captchaId: 'CaptchaSourceBuyInOneClick'\n }).then(function (response) {\n return $sce.trustAsHtml(response.data);\n });\n };\n}\nBuyOneClickFormCtrl.$inject = [\"$sce\", \"$timeout\", \"$window\", \"buyOneClickService\", \"toaster\", \"$scope\", \"$http\"];\nexport default BuyOneClickFormCtrl;", "import formTemplate from '../templates/form.html';\n/* @ngInject */\nfunction buyOneClickTriggerDirective(buyOneClickService) {\n return {\n restrict: 'A',\n scope: true,\n controller: 'BuyOneClickTriggerCtrl',\n controllerAs: 'buyOneClickTrigger',\n bindToController: true,\n link: function (scope, element, attrs, ctrl) {\n element.on('click', function (event) {\n event.preventDefault();\n var modalId = element[0].getAttribute('data-buy-one-click-modal');\n ctrl.modalId = modalId != null ? modalId : 'modalBuyOneClick';\n scope.$apply(function () {\n buyOneClickService.showDialog(ctrl.modalId);\n });\n });\n }\n };\n}\nbuyOneClickTriggerDirective.$inject = [\"buyOneClickService\"];\nfunction buyOneClickFormDirective() {\n return {\n restrict: 'A',\n scope: {\n buttonText: '@',\n page: '@',\n orderType: '@',\n offerId: '=?',\n productId: '=?',\n amount: '=?',\n attributesXml: '=?',\n formInit: '&',\n successFn: '&',\n fieldsOptions: '=?',\n autoReset: '=?',\n buyOneClickValid: '&',\n compactMode: '@',\n agreementDefaultChecked: ' void} function for remove it callback\n */\n subscribe(eventName, callback) {\n if (!this.events[eventName]) {\n this.events[eventName] = [];\n }\n\n const id = this.events[eventName].push(callback) - 1;\n\n return () => {\n this.events[eventName].splice(id, 1);\n };\n }\n /**\n * Notify subscribes callbacks\n * @param {string} eventName\n * @param {any} data - data to params callback.\n * @returns {boolean} True, if publish success. False, if fail\n */\n publish(eventName, ...data) {\n const event = this.events[eventName];\n if (!event) {\n return false;\n }\n\n event.forEach((callback) => callback(...data));\n\n //TODO: remove when we give up JQ\n $(document).trigger(eventName, [...data]);\n\n return true;\n }\n /**\n * Get all subscribes on event\n * @param {string} eventName\n * @returns {Array} array subscribes\n */\n getSubscribes(eventName) {\n return this.events[eventName];\n }\n /**\n * Clear all events.\n */\n clear() {\n this.events = {};\n }\n}\n\nconst PubSub = new PubSubClass();\nglobalThis.PubSub = PubSub;\nexport { PubSub };\n", "import { PubSub } from '../../../_common/PubSub/PubSub.js';\n/* @ngInject */\nfunction buyOneClickService($http, $sce, modalService) {\n var service = this,\n modalId = 'modalBuyOneClick',\n isRenderDialog = false;\n service.showDialog = function (modalId) {\n modalService.open(modalId);\n PubSub.publish('buy_one_click_pre');\n };\n service.getFieldsOptions = function () {\n return $http.get('checkout/checkoutbuyinoneclickfields').then(function (response) {\n return response.data;\n });\n };\n service.getCustomerInfo = function () {\n return $http.get('checkout/checkoutbuyinoneclickcustomer').then(function (response) {\n return response.data;\n });\n };\n service.modalFooterShow = function (modalId, show) {\n modalService.setVisibleFooter(modalId, show);\n };\n service.checkout = function (page, orderType, offerId, productId, amount, attributesXml, name, email, phone, comment, captchaCode, captchaSource, isAgreeForPromotionalNewsletter) {\n let params = {\n page: page,\n orderType: orderType,\n offerId: offerId,\n productId: productId,\n amount: amount,\n attributesXml: attributesXml,\n name: name,\n email: email,\n phone: phone,\n comment: comment,\n captchaCode: captchaCode,\n captchaSource: captchaSource,\n isAgreeForPromotionalNewsletter: isAgreeForPromotionalNewsletter\n };\n return $http.post('checkout/checkoutbuyinoneclick', params).then(function (response) {\n if (response.data.error === null || response.data.length === 0) {\n PubSub.publish('buy_one_click_confirm');\n }\n return response.data;\n });\n };\n}\nbuyOneClickService.$inject = [\"$http\", \"$sce\", \"modalService\"];\nexport default buyOneClickService;", "\uFEFFimport './styles/buyOneClick.scss';\n\nimport BuyOneClickTriggerCtrl from './controllers/buyOneClickTriggerController.js';\nimport BuyOneClickFormCtrl from './controllers/buyOneClickFormController.js';\nimport { buyOneClickFormDirective, buyOneClickTriggerDirective } from './directives/buyOneClickDirectives.js';\nimport buyOneClickService from './services/buyOneClickService.js';\n\nconst moduleName = 'buyOneClick';\n\nangular\n .module(moduleName, [])\n .service('buyOneClickService', buyOneClickService)\n .directive('buyOneClickForm', buyOneClickFormDirective)\n .directive('buyOneClickTrigger', buyOneClickTriggerDirective)\n .controller('BuyOneClickTriggerCtrl', BuyOneClickTriggerCtrl)\n .controller('BuyOneClickFormCtrl', BuyOneClickFormCtrl);\n\nexport default moduleName;\n", "/* stylelint-disable */\r\n/* stylelint-enable */\r\n.adv-modal .adv-modal-inner.pre-order-dialog,\r\n.pre-order-dialog {\r\n min-width: 35vw;\r\n max-width: 35vw;\r\n}\r\n\r\n@media (min-device-width : 768px) and (max-device-width : 1024px) {\r\n .pre-order-dialog {\r\n min-width: 70vw;\r\n }\r\n}\r\n.pre-order-dialog-buttons {\r\n text-align: right;\r\n margin-top: 0.625rem;\r\n}", "function PreOrderTriggerCtrl($window, toaster, preOrderService) {\n var ctrl = this;\n ctrl.formInit = function (form) {\n ctrl.form = form;\n };\n ctrl.modalCallbackClose = function (modalScope) {\n if (ctrl.form.result != null && ctrl.form.showRedirectButton === true) {\n window.location = ctrl.form.result.url;\n }\n if (ctrl.form.success === true) {\n ctrl.form.reset();\n }\n };\n ctrl.successFn = function (result) {\n if (result != null) {\n window.location = result;\n } else {\n preOrderService.modalFooterShow(ctrl.modalId, false);\n }\n };\n}\nPreOrderTriggerCtrl.$inject = [\"$window\", \"toaster\", \"preOrderService\"];\nexport default PreOrderTriggerCtrl;", "function PreOrderFormCtrl($sce, $timeout, $window, preOrderService, toaster, $scope, $http) {\n var ctrl = this;\n ctrl.$onInit = function () {\n ctrl.getFormData();\n if (ctrl.formInit != null) {\n ctrl.formInit({\n form: ctrl\n });\n }\n };\n ctrl.getFormData = function () {\n return preOrderService.getFormData().then(function (responseData) {\n ctrl.data = responseData.data;\n ctrl.field = responseData.field;\n if (ctrl.field.EnableCaptchaInPreOrder) {\n ctrl.initCaptcha('preOrderForm.captchaCode').then(function (data) {\n ctrl.captchaHtml = data;\n });\n }\n return ctrl.data;\n });\n };\n ctrl.reset = function () {\n ctrl.data.FirstName = '';\n ctrl.data.LastName = '';\n ctrl.data.Email = '';\n ctrl.data.Phone = '';\n ctrl.data.Comment = '';\n ctrl.form.$setPristine();\n };\n ctrl.send = function () {\n var isValid = ctrl.preOrderValid();\n if (isValid === true || isValid == null) {\n ctrl.process = true;\n var captchaExist = typeof CaptchaSourcePreOrder != 'undefined' && CaptchaSourcePreOrder != null;\n var captchaInstanceId = captchaExist ? CaptchaSourcePreOrder.InstanceId : null;\n ctrl.data.OfferId = ctrl.offerId;\n ctrl.data.ProductId = ctrl.productId;\n ctrl.data.Amount = ctrl.amount;\n ctrl.data.OptionsHash = ctrl.jsonHash;\n ctrl.data.IsLanding = ctrl.isLanding;\n ctrl.data.CaptchaCode = ctrl.captchaCode;\n ctrl.data.CaptchaSource = captchaInstanceId;\n preOrderService.send(ctrl.data).then(function (data) {\n if (data.result === true) {\n ctrl.result = data.obj;\n ctrl.successFn({\n result: ctrl.result\n });\n if (ctrl.autoReset != null) {\n $timeout(ctrl.reset, ctrl.autoReset);\n }\n } else if (data.errors && data.errors.length) {\n data.errors.forEach(function (error) {\n toaster.pop('error', error);\n });\n ctrl.captchaCode = null;\n } else {\n toaster.pop('error', '\u041E\u0448\u0438\u0431\u043A\u0430 \u043F\u0440\u0438 \u043E\u0442\u043F\u0440\u0430\u0432\u043A\u0435');\n ctrl.captchaCode = null;\n }\n if (captchaExist) {\n CaptchaSourcePreOrder.ReloadImage();\n }\n ctrl.process = false;\n });\n }\n };\n ctrl.initCaptcha = function (ngModel) {\n return $http.post('/commonExt/getCaptchaHtml', {\n ngModel: ngModel,\n captchaId: 'CaptchaSourcePreOrder'\n }).then(function (response) {\n return $sce.trustAsHtml(response.data);\n });\n };\n}\nPreOrderFormCtrl.$inject = [\"$sce\", \"$timeout\", \"$window\", \"preOrderService\", \"toaster\", \"$scope\", \"$http\"];\nexport default PreOrderFormCtrl;", "import formTemplate from '../templates/preOrderForm.html';\n/* @ngInject */\nfunction preOrderTriggerDirective(preOrderService) {\n return {\n restrict: 'A',\n scope: true,\n controller: 'PreOrderTriggerCtrl',\n controllerAs: 'preOrderTrigger',\n bindToController: true,\n link: function (scope, element, attrs, ctrl) {\n element.on('click', function (event) {\n event.preventDefault();\n var modalId = element[0].getAttribute('data-pre-order-modal');\n ctrl.modalId = modalId != null ? modalId : 'modalPreOrder';\n scope.$apply(function () {\n preOrderService.showDialog(ctrl.modalId);\n });\n });\n }\n };\n}\npreOrderTriggerDirective.$inject = [\"preOrderService\"];\nfunction preOrderFormDirective() {\n return {\n restrict: 'A',\n scope: {\n offerId: '=?',\n productId: '=?',\n formInit: '&',\n successFn: '&',\n preOrderValid: '&',\n amount: '=?',\n jsonHash: '=?',\n isLanding: '='\n },\n controller: 'PreOrderFormCtrl',\n controllerAs: 'preOrderForm',\n bindToController: true,\n templateUrl: formTemplate\n };\n}\nexport { preOrderTriggerDirective, preOrderFormDirective };", "function preOrderService($http, $sce, modalService, toaster) {\n var service = this,\n modalId = 'modalPreOrder',\n isRenderDialog = false;\n service.showDialog = function (modalId) {\n modalService.open(modalId);\n };\n service.getFormData = function () {\n return $http.get('checkout/getpreorderformdata').then(function (response) {\n return response.data;\n });\n };\n service.modalFooterShow = function (modalId, show) {\n modalService.setVisibleFooter(modalId, show);\n };\n service.send = function (data) {\n return $http.post('checkout/checkoutpreorder', data).then(function (response) {\n return response.data;\n });\n };\n}\npreOrderService.$inject = [\"$http\", \"$sce\", \"modalService\", \"toaster\"];\nexport default preOrderService;", "\uFEFFimport './styles/styles.scss';\nimport PreOrderTriggerCtrl from './controllers/preOrderTriggerController.js';\nimport PreOrderFormCtrl from './controllers/preOrderFormController.js';\nimport { preOrderFormDirective, preOrderTriggerDirective } from './directives/preOrderDirectives.js';\nimport preOrderService from './services/preOrderService.js';\n\nconst moduleName = 'preOrder';\n\nangular\n .module(moduleName, [])\n .service('preOrderService', preOrderService)\n .directive('preOrderForm', preOrderFormDirective)\n .directive('preOrderTrigger', preOrderTriggerDirective)\n .controller('PreOrderTriggerCtrl', PreOrderTriggerCtrl)\n .controller('PreOrderFormCtrl', PreOrderFormCtrl);\n\nexport default moduleName;\n", ".gallery-block {\r\n padding-right: 3.75rem;\r\n}\r\n\r\n.gallery-picture-link {\r\n max-width: 100%;\r\n}\r\n\r\n.gallery-picture {\r\n text-align: center;\r\n white-space: nowrap;\r\n position: relative;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n.gallery-picture-obj {\r\n display: inline-block;\r\n vertical-align: middle;\r\n}\r\n\r\n.details-additional-graphics {\r\n margin: 2.5rem 2.5rem 1rem;\r\n}\r\n\r\n.gallery-zoom {\r\n position: relative;\r\n padding-left: 1.25rem;\r\n font-size: 0.6875rem;\r\n}\r\n\r\n.gallery-photos-item {\r\n white-space: nowrap;\r\n border: 1px transparent solid;\r\n border-radius: 0.3125rem;\r\n padding: 0.625rem;\r\n display: flex;\r\n position: relative;\r\n justify-content: center;\r\n align-items: center;\r\n margin: auto;\r\n}\r\n\r\n.details-carousel .gallery-photos-item-obj.img-not-resize {\r\n max-width: 100%;\r\n}\r\n\r\n.gallery-photos-slider {\r\n padding: 0 1.25rem;\r\n}\r\n\r\n.gallery-picture-labels {\r\n position: absolute;\r\n right: 0;\r\n top: 0;\r\n z-index: 0;\r\n}\r\n\r\n.gallery-photos-slider-list-horizontal {\r\n font-size: 0;\r\n line-height: 0;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n}\r\n\r\n.gallery-photos-slider-list-vertical {\r\n height: 100%;\r\n}\r\n\r\n.prod-photo-view-change {\r\n display: inline-block;\r\n height: 27px;\r\n width: 25px;\r\n background-image: url(\"data:image/gif;base64,R0lGODlhMgAbAPf/AMvLyx1ptsbGxu7u7jCa8UGi69XV1Wtqa3Jycb29vkar/CmT7NnZ2Tig7/b29iZ3vMLCwmqw6Pr6+BlOjImJiRZ75Zubm9LT1RxRjpWVlR163/7+/LKysj2j89zc3P/+/93e4IGBgSsrKx6B5XZ2dUSu/uzs7Dak+h1+4+jo6CKX8SSQ60dHR7m5uerq6hwaGk2s9DKe9jKU5BuH6xl66F5eXVZWVeTk5OLi4uDg4D2N3Q0NDSs+UJGRkSN9z6SkpCKG5kyl5jmk+iuZ8enp6h10y1hYWEKq/bS0tPb29FBQUKysrDg4OKenpxZ56KKiohMTEiIjJCqA2z4+PWZmZjuq/zKa7x2A4jQzM7e3t6+vrzWf9c3NzSSJ5hl65g0UHCk8TCSK6hQVGDGN5FpaWlxZV3p6eVRQTiI4SEE8PDEtLCg5Snx8fVZWWBx64gMDAwkIAwoGASw9TwUOFxEOD/Dw8Pv7+/Pz8/r6+vn5+UtPWKWnq/j4+Hd6gfT09f/9/vT09GFkbLOzs/78/fX19fHx8VZZYsfIytPT0/Ly8pmcoWxvd7CytoOGjLSztExMTOfn55+goFVSURt73yY3SP37/Pz8+rGxsdDQ0DWf8zuk+P39/z05OT2Kx2Wn30aZ4jWI2jo7O2BgYJaXmJiYl/z6+zOf87S0s46Rlj9AQPf391hVUyKG6FJPTerp6iiU8h1SjyB/3E6o6kOq+0Wq+zyW4TWF2DWI1FtbXF1bWBhDe/r6/HR0cyczPTs3NjOX6eHh4pa84V5cWHx7exxx0CclJPn599/f4BURECExQRl99CiE0evr7Pn7+nh4d6mpq/3//iAfH2Cf3iKK6CKI7CeQ6CmH4yB/4iWM7hkYGFWt8RsZFC1+wezk3ExLRzSg9TeU3jGDxDaIyjij+y+L1Tml/BuB5rSzszGK3vT09jKP2NTh6TeL3hx95VCp6gAGDfz+/SGQ7ieR7Bt87Bx96VtbWTil+vn3+Dql+xk8aS+G3fz8/P39/f7+/v///////yH/C1hNUCBEYXRhWE1QPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS41LWMwMjEgNzkuMTU1NzcyLCAyMDE0LzAxLzEzLTE5OjQ0OjAwICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxNCAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Qjc0N0JEQjlEQzUzMTFFNDkzNzc4RDg3RUQyRDc3QzMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Qjc0N0JEQkFEQzUzMTFFNDkzNzc4RDg3RUQyRDc3QzMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpCNzQ3QkRCN0RDNTMxMUU0OTM3NzhEODdFRDJENzdDMyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpCNzQ3QkRCOERDNTMxMUU0OTM3NzhEODdFRDJENzdDMyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgH//v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh4N/e3dzb2tnY19bV1NPS0dDPzs3My8rJyMfGxcTDwsHAv769vLu6ubi3trW0s7KxsK+urayrqqmop6alpKOioaCfnp2cm5qZmJeWlZSTkpGQj46NjIuKiYiHhoWEg4KBgH9+fXx7enl4d3Z1dHNycXBvbm1sa2ppaGdmZWRjYmFgX15dXFtaWVhXVlVUU1JRUE9OTUxLSklIR0ZFRENCQUA/Pj08Ozo5ODc2NTQzMjEwLy4tLCsqKSgnJiUkIyIhIB8eHRwbGhkYFxYVFBMSERAPDg0MCwoJCAcGBQQDAgEAACH5BAEAAP8ALAAAAAAyABsAAAj/AP8JHEiwoEGC/hIqXMiQYb8EBzA19Hfw4MSLDQEtQUDKBCIjFCZWNIjx4h0tFA4lahIKzqMExwz0aziyYEmFAwAgGeCCFxQxbHII+AGBmcI/gwZ9+FCpJsF9dv5UuqewXx0DDPZxYbEjFYcbS5xlGcCvIdJ+/ezsczowj50Ppf7YEeDB3w8R2RBgQhSCys6ZGM/a8cfvH6M+jQ79I7KnMSM/AhO+HeSCyZQlN7QYEXUJ0s2F/fjxU+vvQqA9jfQQuaBnjyJDgSAnJOTvDxG8xSAMsGMHMKFEM/MUyuOvH6A7CdHO3OdvrUDWF1gL9GNI0T9VCvGkEPHiRQYAqSR5/zBBBUuTfk+wHBjgQUkqAYAyEOHXLw+/PGtBHFq06J90gYr08Q80++AxEyRTRBNNKFGIkAAwRuzABjOjiJEKIlyEkk0kRJAgQiH0+cNHQv/s0YchffjxX4kCwtNMc2kdAMUL2yAjQhpqIPMCJ75kg4waaRRDRzRpYLGDEYSF5g9xA/lx2oqoCOiPKswxFwIUvfDAAxhorCGHHGtQIseWlKyxJRrJiFGDZKLdYQcRRPzj5B7/HaKHYnnUp9AwdHRSwiy0KCCoAkcUSksJgx5ayxfCEOaPA3jskwcjevQRSGysLaKHIXsIROWjzJmxgzhV4GOPEKdqAoM2MHRQjj2wlv9TBTiMJuRCDgYQ0c8/IEQ3UHQgEMQeDlD5I2o4J2yxRSZbNOBOAQ0UIEsBMXzD7AnqfFGGPzck4IFohbH1z5LAtDCAP87swE0MBBBgBQFBWFFAASrA+267MZCjrT9Z1OEPbXbws4k/u4w4Ex54FBfaYP0wcAm6cDwwxAIU//JJPBGsE4E8tcggzwLyvLLMHKv480QdzCE3WDrFjeaPgbQtOZg/dfTgDwkRv1JNNSvIAM4MnnQTTBhjjDFNGGFg48MckvgDQQ84ODClDc8cE1xzzDUXqT+ADPBDAje/8UA8XXQBBBA6oPCJNOaMoIM1Z7NCzdJN22EBAhl8W0MbuLT/wMBMfOwjeD8J30AKCT/QhsAbAcxwxRXXoKAPO7FUcA06oKDw+BXmFME0YfsQ8QMujxiBSw2ikJFBgf2MaAAFNtRDih0SJLR4APRMorsGk0hhiw63SMH7JG640Y7nZxDGDx94lGWEEQecgsjLgC3pzwZ2GGOJBLXfrgwNXtBAgxPkj+9EBeKLPw8xc7SiMD94BGxEEwYktA/gL19vRxL+WOIP/wd4Qz4mQMAJYAADsEigAg9YQF28wxvJWUjWEpKwmZRFNFXpB3MiAYc4xKGDcAihCEfYQQ/G4Q0hqAro/DGYsrzsghHMH2AKkQBBnEIQOMyhDnXoCEecowWuqApzMSyYnQiKBi0zmxkgCnGHJjrxiVB8YiESwRDRDCZrM7liQ1w4pTp48YtgDKMYAeGPgAAAOw==\");\r\n background-repeat: no-repeat;\r\n}\r\n.prod-photo-view-change.rotate {\r\n background-position: left top;\r\n}\r\n.prod-photo-view-change.video {\r\n background-position: right top;\r\n}\r\n\r\n.prod-photo-view-change + .prod-photo-view-change {\r\n margin-left: 20px;\r\n}", ".product-color {\r\n display: inline-block;\r\n vertical-align: middle;\r\n text-indent: 100%;\r\n border-radius: 0.1875rem;\r\n margin: 0 0.3125rem;\r\n overflow: hidden;\r\n}", "@charset \"UTF-8\";\r\n.details-block {\r\n margin-bottom: 1.875rem;\r\n border-radius: 0.3125rem;\r\n}\r\n\r\n.details-payment {\r\n border-style: solid;\r\n border-width: 0.0625rem 0;\r\n padding: 7px 0;\r\n}\r\n.details-payment .price {\r\n margin-bottom: 0.3125rem;\r\n display: block;\r\n}\r\n.details-payment .price-current,\r\n.details-payment .price-new {\r\n font-size: 1.625rem;\r\n}\r\n.details-payment .price-old {\r\n font-size: 0.875rem;\r\n}\r\n.details-payment .price-discount {\r\n font-size: 0.6875rem;\r\n}\r\n\r\n.instead__text-price {\r\n font-size: 16px;\r\n font-weight: 600;\r\n}\r\n\r\n.details-payment-price {\r\n white-space: nowrap;\r\n}\r\n\r\n.details-amount .availability {\r\n vertical-align: inherit;\r\n}\r\n\r\n.details-payment-item {\r\n padding-left: 0.625rem;\r\n}\r\n\r\n.details-payment-inline {\r\n display: inline-block;\r\n margin-bottom: 0.3125rem;\r\n vertical-align: top;\r\n}\r\n\r\n.availability {\r\n display: inline-block;\r\n vertical-align: middle;\r\n border-radius: 0.1875rem;\r\n color: #fff;\r\n padding: 0.3125rem;\r\n line-height: 1;\r\n}\r\n\r\ndiv[show-stocks] {\r\n cursor: pointer;\r\n}\r\n\r\n.available {\r\n background-color: #b1cd03;\r\n}\r\n\r\n.not-available {\r\n background-color: #fb6363;\r\n}\r\n\r\n.details-brand {\r\n text-align: center;\r\n margin-bottom: 2.5rem;\r\n}\r\n\r\n.details-aside {\r\n /* padding-left: rem-calc(40px); */\r\n}\r\n\r\n.details-aside .social-btns {\r\n padding: 0.9375rem;\r\n}\r\n\r\n.details-social {\r\n margin-bottom: 2.5rem;\r\n}\r\n\r\n.details-payment-block {\r\n display: flex;\r\n flex-wrap: wrap;\r\n}\r\n.details-payment-block .btn {\r\n white-space: nowrap;\r\n}\r\n\r\n.details-payment-cell {\r\n margin-top: 7px;\r\n margin-bottom: 7px;\r\n}\r\n\r\n.details-carousel-item,\r\n.details-carousel-item-vertical {\r\n border: 0.0625rem transparent solid;\r\n cursor: pointer;\r\n vertical-align: middle;\r\n box-sizing: border-box;\r\n text-align: center;\r\n}\r\n\r\n.details-carousel-item {\r\n display: inline-block;\r\n}\r\n\r\n.details-carousel-item-vertical {\r\n display: block;\r\n}\r\n\r\n.details-carousel-selected {\r\n border-radius: 0.3125rem;\r\n opacity: 0.5;\r\n border-color: #efd706;\r\n cursor: default;\r\n}\r\n\r\n.first-payment-note {\r\n font-size: 0.6875rem;\r\n}\r\n\r\n.modal .details-modal-preview {\r\n /* max-width: 100% !important;\n position: absolute;\n top: rem-calc(45px);\n right: rem-calc(45px);\n bottom: rem-calc(45px);\n left: rem-calc(45px); */\r\n width: 100%;\r\n height: calc(100% - 45px - 45px);\r\n display: inline-flex;\r\n flex-direction: column;\r\n}\r\n.modal .details-modal-preview .modal-content {\r\n overflow-y: visible;\r\n position: relative;\r\n max-height: 100%;\r\n flex-grow: 1;\r\n /* height: 1px; */\r\n /* \u0447\u0442\u043E\u0431\u044B \u0434\u043E\u0447\u0435\u0440\u043D\u0438\u0439 \u0431\u043B\u043E\u043A \u0440\u0430\u0441\u0442\u044F\u0433\u0438\u0432\u0430\u043B\u0441\u044F \u043D\u0430 \u0432\u0441\u044E \u0432\u044B\u0441\u043E\u0442\u0443 */\r\n}\r\n\r\n.modal-preview-image-load {\r\n opacity: 0;\r\n}\r\n\r\n.modal-preview-image-complete {\r\n opacity: 1;\r\n transition: opacity linear 0.5s;\r\n}\r\n\r\n.details-buy-one-click {\r\n line-height: 1;\r\n}\r\n\r\n.details-carousel,\r\n.details-tabs {\r\n margin-top: 0.9375rem;\r\n}\r\n\r\n.details-carousel-hidden {\r\n opacity: 0;\r\n}\r\n\r\n.details-preview-block {\r\n font-size: 0;\r\n line-height: 0;\r\n}\r\n\r\n.details-preview-block .zoomer-window-title {\r\n line-height: 1;\r\n font-size: 12px;\r\n}\r\n\r\n.details-preview-block .zoomer-inner ~ .zoomer-window .zoomer-window-title {\r\n top: auto;\r\n bottom: 0;\r\n}\r\n\r\n.details-modal-preview-block {\r\n /* display: table;\n width: 100%;\n height: 100%; */\r\n display: flex;\r\n flex-direction: row;\r\n height: 100%;\r\n}\r\n\r\n.details-modal-preview-cell {\r\n /* display: table-cell; */\r\n vertical-align: top;\r\n}\r\n\r\n.details-modal-preview-cell-photo {\r\n width: 100%;\r\n vertical-align: middle;\r\n align-self: center;\r\n}\r\n\r\n.details-modal-carousel {\r\n padding: 1.625rem 0;\r\n height: auto !important;\r\n}\r\n\r\n.details-briefdescription p {\r\n margin: 0;\r\n padding: 0;\r\n}\r\n\r\n.details-spinbox-block {\r\n width: 5rem;\r\n}\r\n\r\n.details-rotate {\r\n display: flex;\r\n justify-content: center;\r\n box-sizing: border-box;\r\n flex-flow: column wrap;\r\n}\r\n\r\n.top-shipping-row {\r\n margin-bottom: 5px;\r\n}\r\n\r\n.details-param-name,\r\n.details-param-value,\r\n.details-param-value-weight {\r\n display: inline;\r\n font-size: 0.75rem;\r\n}\r\n\r\n.details-avalable-text,\r\n.details-avalable-unit {\r\n display: inline-block;\r\n}\r\n\r\n.gifts-list {\r\n display: none;\r\n}\r\n\r\n.gift-properties {\r\n display: table;\r\n padding: 0;\r\n margin: 0.3125rem 0 0;\r\n}\r\n\r\n.gift-properties__item {\r\n display: table-row;\r\n}\r\n\r\n.gift-properties__itemName,\r\n.gift-properties__itemValue {\r\n display: table-cell;\r\n vertical-align: middle;\r\n padding-right: 0.625rem;\r\n font-size: 0.75rem;\r\n}\r\n\r\n.product-gift-image {\r\n height: 69.9px;\r\n width: 75.9px;\r\n /* background: url('../../images/misc/giftIcon.png') no-repeat top left/100% 100%; */\r\n background: url(\"../../images/misc/giftIcon.png\") no-repeat top left/100% 100%;\r\n position: absolute;\r\n z-index: 10;\r\n bottom: 0;\r\n right: -10px;\r\n}\r\n.product-gift-image .gifts-list-container {\r\n background: white;\r\n position: relative;\r\n border-radius: 0.3125rem;\r\n z-index: 1;\r\n}\r\n.product-gift-image .gifts-list {\r\n display: none;\r\n box-shadow: 0 0 9px 0 rgba(0, 0, 0, 0.25);\r\n width: 300px;\r\n position: absolute;\r\n top: 50%;\r\n transform: translateY(-50%);\r\n right: -320px;\r\n white-space: normal;\r\n}\r\n.product-gift-image .gifts-list .gift-txt {\r\n text-align: left;\r\n}\r\n.product-gift-image .gifts-list .gift-txt-descr {\r\n font-size: 0.6875rem;\r\n color: #e20a0a;\r\n}\r\n.product-gift-image .gifts-list::before, .product-gift-image .gifts-list::after {\r\n content: \"\";\r\n display: inline-block;\r\n left: -20px;\r\n width: 20px;\r\n top: 0;\r\n bottom: 0;\r\n margin: auto 0;\r\n position: absolute;\r\n}\r\n.product-gift-image .gifts-list::before {\r\n background: white;\r\n height: 20px;\r\n width: 20px;\r\n left: -10px;\r\n transform: rotate(45deg);\r\n box-shadow: 0 0 9px 0 rgba(0, 0, 0, 0.25);\r\n}\r\n.product-gift-image .gifts-list::after {\r\n background-color: transparent;\r\n height: 100%;\r\n}\r\n.product-gift-image.active .gifts-list {\r\n display: block;\r\n}\r\n\r\n.details-modal-preview-arrow {\r\n width: 100px;\r\n align-self: center;\r\n font-size: 40px;\r\n text-align: center;\r\n}\r\n\r\n.details-photos__left {\r\n margin: 0 10px;\r\n display: flex;\r\n}\r\n\r\n.details-photos__right {\r\n margin: 0 10px;\r\n}\r\n\r\n.details-photos__trigger-360,\r\n.details-photos__trigger-video {\r\n height: 27px;\r\n width: 25px;\r\n padding: 0;\r\n}\r\n\r\n.details-photos__trigger + .details-photos__trigger {\r\n margin-left: 20px;\r\n}\r\n\r\n.products-view-video-wrap {\r\n margin-bottom: 40px;\r\n}\r\n.products-view-video-wrap:last-child {\r\n margin-bottom: 0;\r\n}\r\n.products-view-video-wrap .video-name,\r\n.products-view-video-wrap .video-description {\r\n font-size: 14px;\r\n line-height: 1.5;\r\n}\r\n.products-view-video-wrap .video-name {\r\n margin-bottom: 10px;\r\n font-size: 22px;\r\n}\r\n.products-view-video-wrap .video-description {\r\n margin-top: 10px;\r\n white-space: normal;\r\n}\r\n\r\n.product-videos-in-modal {\r\n display: flex;\r\n}\r\n.product-videos-in-modal .products-view-video-wrap {\r\n margin-bottom: 0;\r\n}\r\n\r\n.carousel-product-video-in-modal:not(.carousel-nav-not-show) {\r\n /* padding: 0 45px; */\r\n}\r\n\r\n.carousel-product-video-in-modal-btn {\r\n font-size: 36px;\r\n}\r\n\r\n.carousel-product-video-in-modal-content {\r\n width: 650px;\r\n}\r\n\r\n.cart-popup-product-sku {\r\n font-size: 13px;\r\n}\r\n\r\n.related-product-carousel-wrap {\r\n margin-right: -0.625rem;\r\n margin-left: -0.625rem;\r\n}\r\n\r\n.details-row {\r\n margin-top: 0.9375rem;\r\n}\r\n.details-row__amount-table {\r\n margin-top: 20px;\r\n margin-bottom: 20px;\r\n}\r\n\r\n.product-card--quickview .details-size-color-picker--cols-1 .color-select-custom,\r\n.product-card--quickview .details-size-color-picker--cols-1 .sizes-select-custom {\r\n width: 50%;\r\n}\r\n\r\n.details-size-color-picker--cols-1 .color-select-custom,\r\n.details-size-color-picker--cols-1 .sizes-select-custom {\r\n width: 60%;\r\n}\r\n\r\n.details-size-color-picker--cols-2 {\r\n display: flex;\r\n flex-wrap: nowrap;\r\n -moz-column-gap: 10px;\r\n column-gap: 10px;\r\n}\r\n.details-size-color-picker--cols-2 .details-colors,\r\n.details-size-color-picker--cols-2 .details-sizes {\r\n flex-grow: 1;\r\n min-width: calc(50% - 5px);\r\n}\r\n.details-size-color-picker--cols-2 .sizes-viewer-list {\r\n height: 100%;\r\n display: flex;\r\n flex-direction: column;\r\n}\r\n.details-size-color-picker--cols-2 .sizes-viewer-list [data-sizes-viewer] {\r\n flex-grow: 1;\r\n}\r\n.details-size-color-picker--cols-2 .sizes-viewer-list .select-custom,\r\n.details-size-color-picker--cols-2 .sizes-viewer-list .choices,\r\n.details-size-color-picker--cols-2 .sizes-viewer-list .form-select {\r\n height: 100%;\r\n}\r\n.details-size-color-picker--cols-2 .sizes-viewer-list .form-select {\r\n display: flex;\r\n align-items: center;\r\n}\r\n\r\n.marketplace-button-header {\r\n font-style: normal;\r\n font-weight: normal;\r\n font-size: 18px;\r\n color: #000;\r\n margin-bottom: 10px;\r\n}\r\n\r\n.marketplace-buttons {\r\n height: 50px;\r\n gap: 20px;\r\n}\r\n\r\n.product-preview-modal-wrap .details-modal-preview {\r\n max-width: 100vw !important;\r\n height: 100% !important;\r\n border-radius: 0 !important;\r\n}\r\n.product-preview-modal-wrap .details-modal-preview .modal-header {\r\n display: none;\r\n}\r\n.product-preview-modal-wrap .details-modal-preview .adv-modal-close {\r\n top: 15px !important;\r\n overflow: visible;\r\n color: black !important;\r\n}\r\n.product-preview-modal-wrap .details-modal-preview .adv-modal-close::after {\r\n content: \"\\e829\" !important;\r\n right: 50px !important;\r\n top: -13px;\r\n background: none !important;\r\n}\r\n.product-preview-modal-wrap .details-modal-preview-cell {\r\n align-self: center !important;\r\n}\r\n.product-preview-modal-wrap .details-modal-carousel {\r\n padding-top: 2rem;\r\n margin-top: 2rem;\r\n}\r\n\r\n.product-review-card {\r\n padding: 12px;\r\n height: 100%;\r\n background: #fff;\r\n border-style: solid;\r\n border-width: 1px;\r\n border-radius: 8px;\r\n display: block;\r\n}\r\n\r\n.product-review-card__name {\r\n font-style: normal;\r\n font-weight: 500;\r\n font-size: 14px;\r\n color: #4b4f58;\r\n}\r\n\r\n.product-review-card__add-date {\r\n font-style: normal;\r\n font-weight: 400;\r\n font-size: 14px;\r\n color: #868695;\r\n white-space: nowrap;\r\n}\r\n\r\n.product-review-card__text {\r\n padding: 20px 0 0;\r\n display: block;\r\n font-style: normal;\r\n font-weight: 400;\r\n font-size: 14px;\r\n color: #666;\r\n}\r\n\r\n.product-reviews-sliders-title {\r\n margin-bottom: 24px;\r\n}\r\n\r\n.product-reviews-sliders {\r\n margin-top: 60px;\r\n padding: 0 13px;\r\n}\r\n\r\n.product-review-card-wrap .carousel-inner--min-height-default,\r\n.product-review-card-wrap .carousel-inner--min-height-twocolumns {\r\n min-height: 200px;\r\n}\r\n\r\n.product-review-card-wrap .glide__arrow {\r\n display: none;\r\n justify-content: center;\r\n align-items: center;\r\n text-align: center;\r\n border-radius: 100%;\r\n box-shadow: none;\r\n background-color: transparent;\r\n color: currentcolor;\r\n}\r\n\r\n.product-review-card-wrap .glide__arrow--prev.carousel-nav-prev {\r\n left: -32px;\r\n}\r\n\r\n.product-review-card-wrap .glide__arrow--prev.carousel-nav-prev::after {\r\n transform: rotate(180deg);\r\n}\r\n\r\n.product-review-card-wrap .carousel-nav-next {\r\n right: -32px;\r\n}\r\n\r\n.product-review-card-wrap .glide__arrow--prev.carousel-nav-prev::after,\r\n.product-review-card-wrap .glide__arrow--next.carousel-nav-next::after {\r\n content: \"\";\r\n font-size: 14px;\r\n width: 18px;\r\n height: 18px;\r\n display: block;\r\n -webkit-mask: url(\"../../images/chevron-right.svg\");\r\n mask: url(\"../../images/chevron-right.svg\");\r\n background-color: currentcolor;\r\n -webkit-mask-repeat: no-repeat;\r\n mask-repeat: no-repeat;\r\n -webkit-mask-position: center;\r\n mask-position: center;\r\n}\r\n\r\n.product-review-card-wrap .carousel-item-img {\r\n border-radius: 40px;\r\n}\r\n\r\n.product-review-card-wrap .carousel-ext__slide {\r\n height: auto !important;\r\n padding-right: 5px;\r\n}\r\n\r\n.product-review-card-rating {\r\n display: inline-block;\r\n vertical-align: middle;\r\n}\r\n\r\n.product-review-card-rating__item {\r\n display: inline-block;\r\n vertical-align: middle;\r\n}\r\n\r\n.product-review-card-rating__count--likes {\r\n color: #298800;\r\n}\r\n\r\n.product-review-card-rating__count--dislikes {\r\n color: #f81f1f;\r\n}\r\n\r\n.product-review-card-buttons {\r\n vertical-align: middle;\r\n}\r\n\r\n.product-review-card__photo-list {\r\n display: flex;\r\n flex-wrap: wrap;\r\n align-items: center;\r\n width: 100%;\r\n}\r\n\r\n.product-review-card__photo-item {\r\n width: 50%;\r\n padding: 6px;\r\n margin: 0;\r\n text-align: center;\r\n}\r\n\r\n@media (min-width: 992px) {\r\n .product-review-card:hover {\r\n box-shadow: 0 0 9px 0 rgba(0, 0, 0, 0.25);\r\n -webkit-text-decoration: none;\r\n text-decoration: none;\r\n }\r\n .product-reviews-sliders {\r\n padding: 0;\r\n }\r\n .product-review-card-wrap {\r\n margin-top: -0.625rem;\r\n margin-left: -0.625rem;\r\n margin-right: -0.625rem;\r\n }\r\n .product-review-card-wrap .carousel-ext__slide {\r\n padding: 0.625rem;\r\n }\r\n .product-review-card-wrap .glide__arrow {\r\n display: flex;\r\n }\r\n .product-review-card {\r\n padding: 16px;\r\n }\r\n}", "import { PubSub } from '../../_common/PubSub/PubSub.js';\n\n/*@ngInject*/\nvar ProductCtrl = function ($q, $scope, $sce, $timeout, productService, modalService, toaster, $translate, $window, urlHelper, customOptionsService) {\n var ctrl = this;\n var callbackListColorsAndSizes = [];\n const deferPostLoad = $q.defer();\n let lastValueChangesSizeColor = undefined;\n ctrl.$onInit = function () {\n ctrl.productView = 'photo';\n ctrl.Price = {};\n ctrl.picture = {};\n ctrl.dirty = false;\n ctrl.offerSelected = {};\n ctrl.carouselHidden = true;\n productService.addToStorage(ctrl);\n ctrl.isOpenPreviewModal = false;\n };\n ctrl.$onDestroy = function () {\n modalService.destroy('modalProductVideo');\n };\n ctrl.productTabsModeInMobile = function (isAccordion, isMobile) {\n if (isAccordion && isMobile) {\n document.querySelectorAll('.accordion-css__state')[0].checked = true;\n }\n };\n ctrl.getPrice = function () {\n return productService.getPrice(ctrl.offerSelected.OfferId, ctrl.customOptions != null ? ctrl.customOptions.xml : null, ctrl.lpBlockId, ctrl.offerSelected.AmountBuy).then(function (price) {\n ctrl.Price = price;\n ctrl.Price.PriceString = $sce.trustAsHtml(ctrl.Price.PriceString);\n ctrl.Price.Bonuses = $sce.trustAsHtml(ctrl.Price.Bonuses);\n ctrl.offerSelected.AllowBuyOutOfStockProducts = price.AllowBuyOutOfStockProducts;\n ctrl.offerSelected.IsAvailableForPurchase = price.IsAvailableForPurchase;\n ctrl.offerSelected.IsAvailableForPurchaseOnBuyOneClick = price.IsAvailableForPurchaseOnBuyOneClick;\n return ctrl.Price;\n });\n };\n ctrl.getFirstPaymentPrice = function (price, discount, discountAmount) {\n if (price == null || discount == null || discountAmount == null) {\n return null;\n }\n return productService.getFirstPaymentPrice(price, discount, discountAmount).then(function (firstPaymentPrice) {\n ctrl.FirstPaymentPrice = $sce.trustAsHtml(firstPaymentPrice);\n ctrl.visibilityFirstPaymentButton = firstPaymentPrice != null && firstPaymentPrice.length > 0;\n });\n };\n ctrl.refreshPrice = function () {\n var defer = $q.defer();\n if (ctrl.offerSelected.AmountBuy == null) return;\n ctrl.getPrice().then(function (price) {\n return ctrl.getFirstPaymentPrice(price.PriceOldNumber != null && price.PriceOldNumber != 0 ? price.PriceOldNumber : price.PriceNumber, ctrl.discount, ctrl.discountAmount);\n }).then(function () {\n if (ctrl.priceAmountList != null) {\n ctrl.priceAmountList.update().then(function (data) {\n defer.resolve(data);\n return data;\n });\n } else {\n defer.resolve();\n }\n }).then(function () {\n if (ctrl.shippingVariants != null) {\n ctrl.shippingVariants.update().then(function (data) {\n defer.resolve(data);\n return data;\n });\n } else {\n defer.resolve();\n }\n productService.processCallback('refreshPrice');\n });\n return defer.promise;\n };\n ctrl.prepareOffers = function (data) {\n for (var i = 0, len = data.Offers.length; i < len; i++) {\n if (data.Offers[i].Available != null && angular.isString(data.Offers[i].Available) === true) {\n data.Offers[i].Available = $sce.trustAsHtml(data.Offers[i].Available);\n }\n }\n return data;\n };\n ctrl.loadData = function (productId, colorId, sizeId, hiddenPrice, filterPhotosEnable, preventChangeLocation) {\n ctrl.productId = productId;\n ctrl.hiddenPrice = hiddenPrice;\n ctrl.filterPhotosEnable = filterPhotosEnable != null ? filterPhotosEnable : true;\n ctrl.preventChangeLocation = preventChangeLocation === true;\n return productService.getOffers(productId, colorId, sizeId).then(function (data) {\n if (data == null) {\n if (colorId == null) {\n ctrl.carouselHidden = false;\n }\n return null;\n }\n ctrl.data = ctrl.prepareOffers(data);\n ctrl.offerSelected = productService.findOfferSelected(data.Offers, data.StartOfferIdSelected);\n ctrl.dirty = true;\n ctrl.getColorsViewer().then(function () {\n if (ctrl.colorsViewer != null && ctrl.offerSelected.Color != null) {\n ctrl.setColorSelected(ctrl.colorsViewer, ctrl.offerSelected.Color != null ? ctrl.offerSelected.Color.ColorId : null);\n }\n return ctrl.data;\n }).then(ctrl.getSizesViewer).then(function () {\n if (ctrl.sizesViewer != null && ctrl.offerSelected.Size != null) {\n ctrl.setSizeSelected(ctrl.sizesViewer, ctrl.offerSelected.Size.SizeId);\n }\n return ctrl.data;\n }).then(ctrl.getCarousel).then(function () {\n if (ctrl.filterPhotosEnable === true && ctrl.carousel != null) {\n ctrl.filterPhotos(ctrl.offerSelected.Color != null ? ctrl.offerSelected.Color.ColorId : null, ctrl.carousel);\n }\n ctrl.carouselHidden = false;\n }).finally(() => {\n ctrl.isPostLoad = true;\n deferPostLoad.resolve();\n });\n return ctrl.data;\n });\n };\n ctrl.refreshSelectedOffer = function () {\n if (ctrl.offerSelected == null) {\n return false;\n }\n productService.getOffers(ctrl.offerSelected.ProductId, ctrl.offerSelected.Color?.ColorId, ctrl.offerSelected.Size?.SizeId).then(function (data) {\n if (data == null || data.Offers == null) {\n return null;\n }\n ctrl.data = ctrl.prepareOffers(data);\n ctrl.offerSelected = productService.findOfferSelected(ctrl.data.Offers, ctrl.offerSelected.OfferId);\n return ctrl.data;\n });\n };\n ctrl.validate = function () {\n if (ctrl.customOptions == null) {\n return true;\n }\n const {\n invalidOptions,\n isValidOptions\n } = customOptionsService.isValidOptions(ctrl.customOptions.items);\n const form = ctrl.customOptions.customOptionsForm;\n if (form.$invalid || !isValidOptions) {\n form.$setSubmitted();\n form.$setDirty();\n if (invalidOptions.size > 0) {\n invalidOptions.forEach(option => {\n let errorText = '';\n const {\n MinQuantity,\n MaxQuantity,\n InputType,\n Title\n } = option;\n if (MinQuantity != null && MaxQuantity != null && MaxQuantity === MinQuantity) {\n errorText = `: \u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 ${MaxQuantity} \u0432\u0430\u0440\u0438\u0430\u043D\u0442\u0430`;\n } else {\n const minText = MinQuantity != null ? `\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435 \u0434\u043E\u043B\u0436\u043D\u043E \u0431\u044B\u0442\u044C \u043E\u0442 ${MinQuantity}` : '';\n const maxText = MaxQuantity != null && MaxQuantity !== MinQuantity ? ` \u0434\u043E ${MaxQuantity}` : '';\n errorText = `${minText}${minText && maxText ? ' \u0434\u043E ' : ''}${maxText}`;\n }\n const errorMsg = InputType === 6 ? `\u041D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D\u043E \u043F\u043E\u043B\u0435 ${Title} ${errorText}` : `\u041D\u0435\u0432\u0435\u0440\u043D\u043E \u0437\u0430\u043F\u043E\u043B\u043D\u0435\u043D\u043E \u043F\u043E\u043B\u0435 ${Title} ${errorText}`;\n toaster.pop('error', errorMsg);\n });\n } else {\n toaster.pop('error', $translate.instant('Js.Product.InvalidCustomOptions'));\n }\n return false;\n }\n return true;\n };\n\n //#region compare and wishlist\n\n ctrl.compareInit = function (compare) {\n ctrl.compare = compare;\n };\n ctrl.wishlistControlInit = function (wishlistControl) {\n ctrl.wishlistControl = wishlistControl;\n };\n\n //#endregion\n\n //#region customOptions\n\n ctrl.customOptionsInitFn = function (customOptions) {\n ctrl.customOptions = customOptions;\n };\n ctrl.customOptionsChange = function (data) {\n if (!ctrl.hiddenPrice) {\n ctrl.refreshPrice().then(() => {\n ctrl.disabledBuyButton = false;\n });\n }\n PubSub.publish('product.customOptions.change', {\n productId: ctrl.productId,\n offerId: ctrl.offerSelected.OfferId,\n items: ctrl.customOptions.items\n });\n };\n ctrl.beforeCustomOptionsChange = function () {\n if (!ctrl.hiddenPrice) {\n ctrl.disabledBuyButton = true;\n }\n };\n\n //#endregion\n\n //#region colors\n\n ctrl.initColors = function (colorsViewer) {\n ctrl.colorsViewer = colorsViewer;\n if (ctrl.colorsViewerDefer != null) {\n ctrl.colorsViewerDefer.resolve();\n delete ctrl.colorsViewerDefer;\n }\n };\n ctrl.getColorsViewer = function () {\n var defer = $q.defer();\n if (ctrl.colorsExist === true && ctrl.colorsViewer == null) {\n ctrl.colorsViewerDefer = defer;\n } else {\n defer.resolve(ctrl.colorsViewer);\n }\n return defer.promise;\n };\n ctrl.changeColor = function (color) {\n ctrl.colorSelected = color;\n if (ctrl.sizesViewer != null) {\n ctrl.sizeSelected = ctrl.getSizeAvalable(ctrl.data.Offers, ctrl.colorSelected.ColorId, ctrl.sizesViewer.sizes, ctrl.data.AllowPreOrder);\n if (ctrl.preventChangeLocation !== true) {\n urlHelper.setLocationQueryParams('size', ctrl.sizeSelected != null && ctrl.sizeSelected.SizeId != null ? ctrl.sizeSelected.SizeId : null, true);\n }\n }\n ctrl.offerSelected = productService.getOffer(ctrl.data.Offers, ctrl.colorSelected.ColorId, ctrl.sizeSelected != null && ctrl.sizeSelected.isDisabled === false ? ctrl.sizeSelected.SizeId : null, ctrl.data.AllowPreOrder);\n if (!ctrl.hiddenPrice) {\n ctrl.refreshPrice();\n }\n if (ctrl.compare != null) {\n ctrl.compare.checkStatus(ctrl.offerSelected.OfferId);\n }\n if (ctrl.wishlistControl != null) {\n ctrl.wishlistControl.checkStatus(ctrl.offerSelected.OfferId);\n }\n ctrl.setPreviewByColorId(ctrl.colorSelected.ColorId, ctrl.filterPhotosEnable, ctrl.carousel);\n if (ctrl.preventChangeLocation !== true) {\n urlHelper.setLocationQueryParams('color', ctrl.colorSelected.ColorId, true);\n }\n ctrl.processChangeSizeAndColorCallback(ctrl.colorSelected, 'color', {\n offer: ctrl.offerSelected\n });\n if (ctrl.sizesViewer != null) {\n ctrl.processChangeSizeAndColorCallback(ctrl.sizeSelected, 'size', {\n offer: ctrl.offerSelected\n });\n }\n };\n ctrl.setColorSelected = function (colorsViewer, colorId) {\n for (var i = colorsViewer.colors.length - 1; i >= 0; i--) {\n if (colorsViewer.colors[i].ColorId === colorId) {\n ctrl.colorSelected = colorsViewer.colors[i];\n break;\n }\n }\n ctrl.processChangeSizeAndColorCallback(ctrl.colorSelected, 'color', {\n offer: ctrl.offerSelected\n });\n };\n\n //#endregion\n\n //#region sizes\n\n ctrl.initSizes = function (sizesViewer) {\n ctrl.sizesViewer = sizesViewer;\n if (ctrl.sizesViewerDefer != null) {\n ctrl.sizesViewer.sizes = JSON.parse(JSON.stringify(ctrl.sizesViewer.sizes));\n ctrl.sizesViewerDefer.resolve();\n delete ctrl.sizesViewerDefer;\n }\n };\n ctrl.getSizesViewer = function () {\n var defer = $q.defer();\n if (ctrl.sizesExist === true && ctrl.sizesViewer == null) {\n ctrl.sizesViewerDefer = defer;\n } else {\n defer.resolve(ctrl.sizesViewer);\n }\n return defer.promise;\n };\n ctrl.changeSize = function (size) {\n ctrl.sizeSelected = size;\n ctrl.offerSelected = productService.getOffer(ctrl.data.Offers, ctrl.colorSelected != null ? ctrl.colorSelected.ColorId : 0, ctrl.sizeSelected.isDisabled ? null : ctrl.sizeSelected.SizeId, ctrl.data.AllowPreOrder);\n if (!ctrl.hiddenPrice) {\n ctrl.refreshPrice();\n }\n if (ctrl.compare != null) {\n ctrl.compare.checkStatus(ctrl.offerSelected.OfferId);\n }\n if (ctrl.wishlistControl != null) {\n ctrl.wishlistControl.checkStatus(ctrl.offerSelected.OfferId);\n }\n if (ctrl.preventChangeLocation !== true) {\n urlHelper.setLocationQueryParams('size', ctrl.sizeSelected.SizeId, true);\n }\n ctrl.processChangeSizeAndColorCallback(ctrl.sizeSelected, 'size', {\n offer: ctrl.offerSelected\n });\n };\n ctrl.setSizeSelected = function (sizesViewer, sizeId) {\n for (var i = sizesViewer.sizes.length - 1; i >= 0; i--) {\n if (sizesViewer.sizes[i].SizeId === sizeId) {\n ctrl.sizeSelected = sizesViewer.sizes[i];\n break;\n }\n }\n ctrl.sizeSelected = ctrl.getSizeAvalable(ctrl.data.Offers, ctrl.colorSelected != null ? ctrl.colorSelected.ColorId : 0, ctrl.sizesViewer.sizes, ctrl.data.AllowPreOrder, true);\n ctrl.processChangeSizeAndColorCallback(ctrl.sizeSelected, 'size', {\n offer: ctrl.offerSelected\n });\n };\n ctrl.getSizeAvalable = function (offers, colorId, sizes, allowPreorder, notChangeSelectdSize) {\n var offerItem, sizeSelected, loopCheckStart;\n sizes.forEach(function (item) {\n item.isDisabled = true;\n });\n for (var i = offers.length - 1; i >= 0; i--) {\n offerItem = offers[i];\n if (colorId == null || offerItem.Color == null) {\n loopCheckStart = true;\n } else {\n loopCheckStart = offerItem.Color != null && offerItem.Color.ColorId === colorId;\n }\n if (loopCheckStart === true) {\n for (var s = sizes.length - 1; s >= 0; s--) {\n if (offerItem.Size.SizeId == sizes[s].SizeId && (allowPreorder === true || offerItem.Amount > 0)) {\n sizes[s].isDisabled = false;\n break;\n }\n }\n }\n }\n if (!notChangeSelectdSize && (ctrl.sizeSelected == null || ctrl.sizeSelected.isDisabled === true)) {\n for (var j = 0, l = sizes.length; j < l; j++) {\n if (sizes[j].isDisabled == null || sizes[j].isDisabled == false) {\n sizeSelected = sizes[j];\n break;\n }\n }\n } else {\n sizeSelected = ctrl.sizeSelected;\n }\n return sizeSelected;\n };\n\n //#endregion\n\n //#region carousels\n\n ctrl.addCarousel = function (carousel) {\n ctrl.carousel = carousel;\n if (ctrl.carouselDefer != null) {\n if (ctrl.carousel.options.asNavFor != null) {\n ctrl.carousel.whenAsNavForReady(ctrl.carousel.options.asNavFor, function () {\n ctrl.carouselDefer.resolve();\n delete ctrl.carouselDefer;\n });\n } else {\n ctrl.carouselDefer.resolve();\n delete ctrl.carouselDefer;\n }\n }\n };\n ctrl.getCarousel = function () {\n var defer = $q.defer();\n if (ctrl.carouselExist === true && ctrl.carousel == null) {\n ctrl.carouselDefer = defer;\n } else {\n defer.resolve();\n }\n return defer.promise;\n };\n ctrl.carouselItemSelect = function (carousel, item, index) {\n ctrl.setPreview(item.parameters);\n ctrl.updateModalPreview(item.parameters.originalPath);\n if (carousel != null && ctrl.carousel != null && carousel != ctrl.carousel) {\n ctrl.carousel.setItemSelect(index);\n } else if (ctrl.carouselPreview != null && carousel != ctrl.carouselPreview) {\n ctrl.carouselPreview.setItemSelect(index);\n }\n };\n\n //#endregion\n\n //#region modal preview\n\n ctrl.carouselPreviewNext = function () {\n var items = ctrl.carouselPreview.getItems(),\n itemSelected,\n itemSelectedNew,\n newIndex;\n itemSelected = ctrl.carouselPreview.getSelectedItem() || (items != null ? items[0] : null);\n if (ctrl.carouselPreview.getSelectedItem() === items[items.length - 1]) {\n ctrl.carouselPreview.goto(0, false);\n newIndex = 0;\n } else {\n ctrl.carouselPreview.next();\n newIndex = itemSelected.carouselItemData.index + 1;\n }\n if (itemSelected != null) {\n itemSelectedNew = items[newIndex];\n if (itemSelectedNew) {\n ctrl.carouselPreview.setItemSelect(itemSelectedNew);\n ctrl.setPreview(itemSelectedNew.carouselItemData.parameters);\n ctrl.updateModalPreview(itemSelectedNew.carouselItemData.parameters.originalPath);\n }\n }\n };\n ctrl.carouselPreviewPrev = function () {\n var items = ctrl.carouselPreview.getItems(),\n itemSelected,\n itemSelectedNew,\n newIndex;\n itemSelected = ctrl.carouselPreview.getSelectedItem() || (items != null ? items[0] : null);\n if (ctrl.carouselPreview.getSelectedItem() === items[0]) {\n ctrl.carouselPreview.goto(items.length - 1, false);\n newIndex = items.length - 1;\n } else {\n ctrl.carouselPreview.prev();\n newIndex = itemSelected.carouselItemData.index - 1;\n }\n if (itemSelected != null) {\n itemSelectedNew = items[newIndex];\n if (itemSelectedNew) {\n ctrl.carouselPreview.setItemSelect(itemSelectedNew);\n ctrl.setPreview(itemSelectedNew.carouselItemData.parameters);\n ctrl.updateModalPreview(itemSelectedNew.carouselItemData.parameters.originalPath);\n }\n }\n };\n ctrl.addModalPictureCarousel = function (carouselPreview) {\n ctrl.carouselPreview = carouselPreview;\n ctrl.carouselPreviewUpdate();\n };\n ctrl.carouselPreviewUpdate = function () {\n if (ctrl.carouselPreview != null) {\n ctrl.getDialog().then(function (modal) {\n if (modal.modalScope.isOpen === true) {\n ctrl.filterPreviewCarouselItems();\n ctrl.carouselPreview.update();\n }\n });\n }\n };\n ctrl.updateModalPreview = function (imgSrc) {\n productService.getPhoto(imgSrc).then(function (img) {\n $timeout(function () {\n ctrl.maxHeightModalPreview = ctrl.getMaxHeightModalPreview();\n ctrl.modalPreviewHeight = img.naturalHeight > ctrl.maxHeightModalPreview ? ctrl.maxHeightModalPreview : img.naturalHeight;\n }, 0);\n });\n };\n ctrl.modalPreviewCallbackOpen = function () {\n ctrl.setPreviewByColorId(ctrl.offerSelected.Color != null ? ctrl.offerSelected.Color.ColorId : null, ctrl.filterPhotosEnable, ctrl.carouselPreview);\n $timeout(function () {\n ctrl.carouselPreviewUpdate();\n ctrl.isOpenPreviewModal = true;\n }, 100);\n };\n ctrl.modalPreviewCallbackClose = function () {\n if (!('ontouchstart' in window)) {\n $window.removeEventListener(`keydown`, ctrl.onKeydownBackForward);\n }\n ctrl.isOpenPreviewModal = false;\n };\n ctrl.modalPreviewOpen = function (event, picture) {\n event.preventDefault();\n event.stopPropagation();\n if (ctrl.isPostLoad !== true) {\n return;\n }\n ctrl.modalPreviewState = 'load';\n ctrl.dialogOpen().then(function (modal) {\n let modalElement = modal.modalElement[0];\n modalElement.classList.add('product-preview-modal-wrap');\n let htmlMain = document.querySelector('html');\n htmlMain.classList.add('overflow-hidden');\n modal.modalScope.callbackClose = function () {\n htmlMain.classList.remove('overflow-hidden');\n };\n productService.getPhoto(picture == null ? ctrl.picture.originalPath : picture.originalPath).then(function (img) {\n $timeout(function () {\n ctrl.maxHeightModalPreview = ctrl.getMaxHeightModalPreview();\n ctrl.modalPreviewHeight = img.naturalHeight > ctrl.maxHeightModalPreview ? ctrl.maxHeightModalPreview : img.naturalHeight;\n //ctrl.carouselPreviewUpdate();\n ctrl.modalPreviewState = 'complete';\n if (ctrl.carouselPreview != null) {\n ctrl.filterPreviewCarouselItems();\n }\n }, 0);\n });\n });\n };\n ctrl.getMaxHeightModalPreview = function () {\n var result = 0,\n height,\n modalElement,\n modaPreview = document.getElementById('modalPreview_' + ctrl.productId);\n if (modaPreview != null) {\n modalElement = modaPreview.querySelector('.modal-content');\n }\n if (modalElement != null) {\n height = parseFloat(getComputedStyle(modalElement).height);\n result = isNaN(height) === false ? height : 0;\n }\n return result;\n };\n ctrl.dialogOpen = function () {\n return deferPostLoad.promise.then(() => ctrl.getDialog()).then(function (modal) {\n if (!('ontouchstart' in window)) {\n $window.addEventListener(`keydown`, ctrl.onKeydownBackForward);\n }\n modal.modalScope.open();\n return modal;\n });\n };\n ctrl.getDialog = function () {\n return modalService.getModal('modalPreview_' + ctrl.productId);\n };\n ctrl.resizeModalPreview = function () {\n $scope.$apply(function () {\n ctrl.updateModalPreview(ctrl.picture.originalPath);\n ctrl.carouselPreviewUpdate();\n });\n };\n\n //#endregion\n\n //#region productViewChange\n\n ctrl.showVideo = function (visible) {\n ctrl.visibleVideo = visible;\n if (visible === false) {\n ctrl.videosInModalReceived = false;\n ctrl.carouselVideosInModalInit = false;\n }\n };\n ctrl.onReceiveVideosInModal = function () {\n ctrl.videosInModalReceived = true;\n };\n ctrl.onInitCarouselVideosInModal = function () {\n ctrl.carouselVideosInModalInit = true;\n };\n ctrl.showRotate = function (visible) {\n ctrl.visibleRotate = visible;\n };\n\n //#endregion\n\n //#region shippingVariants\n ctrl.addShippingVariants = function (shippingVariants) {\n ctrl.shippingVariants = shippingVariants;\n };\n //#endregion\n\n //#region priceAmountList\n ctrl.addPriceAmountList = function (priceAmountList) {\n ctrl.priceAmountList = priceAmountList;\n };\n //#endregion\n\n //#region spinbox amount\n ctrl.updateAmount = function () {\n ctrl.refreshPrice();\n };\n //#endregion\n\n ctrl.filterPhotosFunction = function (item, index) {\n return item != null && (item.carouselItemData.parameters.colorId == null || ctrl.offerSelected.Color == null || item.carouselItemData.parameters.colorId == ctrl.offerSelected.Color.ColorId);\n };\n ctrl.setPreviewByColorId = function (colorId, filterEnabled, carousel) {\n var findArray;\n if (ctrl.carousel) {\n if (filterEnabled === true) {\n ctrl.filterPhotos(colorId, carousel, ctrl.picture.PhotoId);\n } else {\n findArray = ctrl.carousel.items.filter(ctrl.filterPhotosFunction);\n if (findArray != null && findArray.length > 0) {\n ctrl.setPreview(findArray[0].carouselItemData.parameters);\n }\n }\n }\n };\n ctrl.filterPhotos = function (colorId, carousel, selectedPhotoId) {\n var selectedItem, items, oldItem;\n if (carousel) {\n oldItem = carousel.getActiveItem();\n items = carousel.filterItems(ctrl.filterPhotosFunction, colorId);\n\n /*if (selectedPhotoId != null) {\n items = carousel.getItems();\n for (var i = 0, len = items.length; i < len; i++) {\n if (items[i].carouselItemData.parameters.colorId === colorId) {\n carousel.setItemSelect(items[i]);\n findedSelected = true;\n break;\n }\n }\n }*/\n\n if (items == null || items.length === 0) {\n carousel.addItem(oldItem);\n }\n selectedItem = carousel.getActiveItem();\n if (selectedItem != null) {\n carousel.setItemSelect(selectedItem);\n ctrl.setPreview(selectedItem.carouselItemData.parameters);\n }\n }\n };\n ctrl.setView = function (viewName) {\n ctrl.productView = viewName;\n ctrl.stopVideo();\n };\n ctrl.setPreview = function (picture) {\n ctrl.picture = picture;\n };\n ctrl.getUrl = function (url) {\n var result = url,\n params = [];\n if (ctrl.colorsViewer != null && ctrl.colorsViewer.colorSelected != null) {\n params.push('color=' + ctrl.colorsViewer.colorSelected.ColorId);\n }\n if (ctrl.sizesViewer != null && ctrl.sizesViewer.sizeSelected != null) {\n params.push('size=' + ctrl.sizesViewer.sizeSelected.SizeId);\n }\n if (params.length > 0) {\n result = result + '?' + params.join('&');\n }\n return result;\n };\n ctrl.getCommentsCount = function () {\n productService.getReviewsCount(ctrl.productId).then(function (result) {\n if (result != null) {\n ctrl.reviewsCount = result.reviewsCount;\n }\n });\n };\n ctrl.addChangeSizeAndColorCallback = function (callback) {\n if (callback == null) {\n throw new Error('Parameter \"callback is required\"');\n }\n callbackListColorsAndSizes.push(callback);\n if (lastValueChangesSizeColor !== undefined) {\n callback(lastValueChangesSizeColor);\n }\n };\n ctrl.processChangeSizeAndColorCallback = function (value, type, additionalData) {\n lastValueChangesSizeColor = value;\n if (callbackListColorsAndSizes.length > 0) {\n callbackListColorsAndSizes.forEach(fn => fn(value, type, additionalData));\n }\n };\n ctrl.onKeydownBackForward = e => {\n if (e.code === `ArrowRight`) {\n ctrl.carouselPreviewNext();\n }\n if (e.code === `ArrowLeft`) {\n ctrl.carouselPreviewPrev();\n }\n };\n ctrl.handleChangeInplaceArtNo = function (value, $scope) {\n ctrl.offerSelected.ArtNo = value;\n };\n ctrl.filterPreviewCarouselItems = function () {\n if (ctrl.carouselPreview != null) {\n if (ctrl.filterPhotosEnable === true && ctrl.picture != null) {\n ctrl.filterPhotos(ctrl.offerSelected.Color != null ? ctrl.offerSelected.Color.ColorId : null, ctrl.carouselPreview, ctrl.picture.PhotoId);\n }\n var items = ctrl.carouselPreview.getItems();\n for (var i = 0; i < items.length; i++) {\n if (items[i].carouselItemData.parameters.PhotoId == ctrl.picture.PhotoId) {\n ctrl.carouselPreview.setItemSelect(items[i]);\n ctrl.setPreview(items[i].carouselItemData.parameters);\n ctrl.updateModalPreview(items[i].carouselItemData.parameters.originalPath);\n break;\n }\n }\n }\n };\n\n //\u043C\u043E\u0434\u0430\u043B\u044C\u043D\u043E\u0435 \u043E\u043A\u043D\u043E \u0441 \u043C\u0430\u0433\u0430\u0437\u0438\u043D\u0430\u043C\u0438\n const modalId = 'mapShops';\n ctrl.openShopsMap = function (offerId, isMobile, yaMapsKey) {\n modalService.renderModal(modalId, $translate.instant('Js.Product.ShopsMap.Header'), ``, null, {\n destroyOnClose: true,\n modalClass: 'warehouses-list-modal'\n });\n modalService.getModal(modalId).then(function (modal) {\n modal.modalScope.open();\n });\n };\n};\nProductCtrl.$inject = [\"$q\", \"$scope\", \"$sce\", \"$timeout\", \"productService\", \"modalService\", \"toaster\", \"$translate\", \"$window\", \"urlHelper\", \"customOptionsService\"];\nexport default ProductCtrl;", "function productService($http, $q) {\n var service = this,\n _product,\n callbacks = {};\n service.getOffers = function (productId, colorId, sizeId) {\n return $http.get('productExt/getoffers', {\n params: {\n productId: productId,\n colorId: colorId,\n sizeId: sizeId\n }\n }).then(function (response) {\n return response.data;\n });\n };\n service.findOfferSelected = function (offers, offerIdSelected) {\n var offer;\n for (var i = offers.length - 1; i >= 0; i--) {\n if (offers[i].OfferId === offerIdSelected) {\n offer = offers[i];\n break;\n }\n }\n return offer;\n };\n service.findOffersByColorId = function (offers, colorId) {\n return offers.filter(function (item) {\n return colorId != null && item.Color != null && item.Color.ColorId === colorId;\n });\n };\n service.findOffersBySizeId = function (offers, sizeId) {\n return offers.filter(function (item) {\n return sizeId != null && item.Size != null && item.Size.SizeId === sizeId;\n });\n };\n service.getOffer = function (offers, colorId, sizeId) {\n var arrayOffers = offers.slice(),\n arrayOffersByColor = [],\n arrayOffersBySize = [],\n stopLoop = false,\n offer;\n arrayOffersByColor = service.findOffersByColorId(arrayOffers, colorId);\n arrayOffersBySize = service.findOffersBySizeId(arrayOffers, sizeId);\n if (arrayOffersByColor.length > 0 && arrayOffersBySize.length > 0) {\n for (var i = 0, lenC = arrayOffersByColor.length; i < lenC; i++) {\n for (var j = 0, lenS = arrayOffersBySize.length; j < lenS; j++) {\n if (arrayOffersByColor[i].OfferId === arrayOffersBySize[j].OfferId) {\n offer = arrayOffersByColor[i];\n stopLoop = true;\n break;\n }\n }\n if (stopLoop === true) {\n break;\n }\n }\n }\n if (offer == null && arrayOffersByColor.length > 0) {\n offer = arrayOffersByColor[0];\n }\n if (offer == null && arrayOffersBySize.length > 0) {\n offer = arrayOffersBySize[0];\n }\n return offer;\n };\n service.getPrice = function (offerId, attributesXml, lpBlockId, amount) {\n return $http.post('productExt/getofferprice', {\n offerId: offerId,\n attributesXml: attributesXml,\n lpBlockId: lpBlockId,\n amount: amount\n }).then(function (response) {\n return response.data;\n });\n };\n service.getFirstPaymentPrice = function (price, discount, discountAmount) {\n return $http.get('productExt/getfirstpaymentprice', {\n params: {\n price: price,\n discount: discount,\n discountAmount: discountAmount\n }\n }).then(function (response) {\n return response.data;\n });\n };\n service.getShippings = function (offerId) {\n return $http.get('productExt/getshippings', {\n params: {\n offerId: offerId\n }\n }).then(function (response) {\n return response.data;\n });\n };\n service.addCallback = function (name, func) {\n callbacks[name] = callbacks[name] || [];\n callbacks[name].push(func);\n };\n service.processCallback = function (name, data) {\n var arrFunc = callbacks[name];\n if (arrFunc != null && arrFunc.length > 0) {\n for (var i = 0, len = arrFunc.length; i < len; i++) {\n arrFunc[i](data);\n }\n }\n };\n service.getPhoto = function (url) {\n var defered = $q.defer(),\n img = new Image();\n img.src = url;\n if (img.complete == true || typeof img.naturalWidth !== 'undefined' && img.naturalWidth > 0) {\n defered.resolve(img);\n } else {\n img.onload = function () {\n defered.resolve(img);\n };\n }\n return defered.promise.then(function (response) {\n return response;\n });\n };\n service.addToStorage = function (product) {\n _product = product;\n };\n service.getProduct = function () {\n return _product;\n };\n service.getReviewsCount = function (productId) {\n return $http.get('productExt/getReviewsCount', {\n params: {\n productId: productId\n }\n }).then(function (response) {\n return response.data;\n });\n };\n service.getOfferStocks = function (offerId) {\n return $http.get('productExt/getofferstocks', {\n params: {\n offerId: offerId\n }\n }).then(function (response) {\n return response.data;\n });\n };\n}\nproductService.$inject = [\"$http\", \"$q\"];\nexport default productService;", "\uFEFFimport carouselModule from '../_common/carousel/carousel.module.js';\nimport ratingModule from '../_common/rating/rating.module.js';\nimport rotateModule from '../_common/rotate/rotate.module.js';\nimport videosModule from '../_partials/videos/videos.module.js';\nimport zoomerModule from '../_common/zoomer/zoomer.module.js';\n\nimport customOptionsModule from '../_partials/custom-options/customOptions.module.js';\nimport colorsViewerModule from '../_partials/colors-viewer/colorsViewer.module.js';\nimport sizesViewerModule from '../_partials/sizes-viewer/sizesViewer.module.js';\nimport buyOneClickModule from '../_partials/buy-one-click/buyOneClick.module.js';\nimport preOrderModule from '../_partials/pre-order/preOrder.module.js';\n\nimport '../../styles/partials/gallery.scss';\nimport '../../styles/partials/product-color.scss';\n\nimport '../../styles/views/product.scss';\n\nimport ProductCtrl from './controllers/productController.js';\nimport productService from './services/productService.js';\n\nconst moduleName = 'productQuickView';\n\nconst deps = [\n ratingModule,\n carouselModule,\n zoomerModule,\n rotateModule,\n customOptionsModule,\n colorsViewerModule,\n sizesViewerModule,\n buyOneClickModule,\n videosModule,\n preOrderModule,\n];\n\nangular.module(moduleName, deps).controller('ProductCtrl', ProductCtrl).service('productService', productService);\n\nexport default moduleName;\n", "[uib-tooltip-popup].tooltip.top-left > .tooltip-arrow,\r\n[uib-tooltip-popup].tooltip.top-right > .tooltip-arrow,\r\n[uib-tooltip-popup].tooltip.bottom-left > .tooltip-arrow,\r\n[uib-tooltip-popup].tooltip.bottom-right > .tooltip-arrow,\r\n[uib-tooltip-popup].tooltip.left-top > .tooltip-arrow,\r\n[uib-tooltip-popup].tooltip.left-bottom > .tooltip-arrow,\r\n[uib-tooltip-popup].tooltip.right-top > .tooltip-arrow,\r\n[uib-tooltip-popup].tooltip.right-bottom > .tooltip-arrow,\r\n[uib-tooltip-html-popup].tooltip.top-left > .tooltip-arrow,\r\n[uib-tooltip-html-popup].tooltip.top-right > .tooltip-arrow,\r\n[uib-tooltip-html-popup].tooltip.bottom-left > .tooltip-arrow,\r\n[uib-tooltip-html-popup].tooltip.bottom-right > .tooltip-arrow,\r\n[uib-tooltip-html-popup].tooltip.left-top > .tooltip-arrow,\r\n[uib-tooltip-html-popup].tooltip.left-bottom > .tooltip-arrow,\r\n[uib-tooltip-html-popup].tooltip.right-top > .tooltip-arrow,\r\n[uib-tooltip-html-popup].tooltip.right-bottom > .tooltip-arrow,\r\n[uib-tooltip-template-popup].tooltip.top-left > .tooltip-arrow,\r\n[uib-tooltip-template-popup].tooltip.top-right > .tooltip-arrow,\r\n[uib-tooltip-template-popup].tooltip.bottom-left > .tooltip-arrow,\r\n[uib-tooltip-template-popup].tooltip.bottom-right > .tooltip-arrow,\r\n[uib-tooltip-template-popup].tooltip.left-top > .tooltip-arrow,\r\n[uib-tooltip-template-popup].tooltip.left-bottom > .tooltip-arrow,\r\n[uib-tooltip-template-popup].tooltip.right-top > .tooltip-arrow,\r\n[uib-tooltip-template-popup].tooltip.right-bottom > .tooltip-arrow,\r\n[uib-popover-popup].popover.top-left > .arrow,\r\n[uib-popover-popup].popover.top-right > .arrow,\r\n[uib-popover-popup].popover.bottom-left > .arrow,\r\n[uib-popover-popup].popover.bottom-right > .arrow,\r\n[uib-popover-popup].popover.left-top > .arrow,\r\n[uib-popover-popup].popover.left-bottom > .arrow,\r\n[uib-popover-popup].popover.right-top > .arrow,\r\n[uib-popover-popup].popover.right-bottom > .arrow,\r\n[uib-popover-html-popup].popover.top-left > .arrow,\r\n[uib-popover-html-popup].popover.top-right > .arrow,\r\n[uib-popover-html-popup].popover.bottom-left > .arrow,\r\n[uib-popover-html-popup].popover.bottom-right > .arrow,\r\n[uib-popover-html-popup].popover.left-top > .arrow,\r\n[uib-popover-html-popup].popover.left-bottom > .arrow,\r\n[uib-popover-html-popup].popover.right-top > .arrow,\r\n[uib-popover-html-popup].popover.right-bottom > .arrow,\r\n[uib-popover-template-popup].popover.top-left > .arrow,\r\n[uib-popover-template-popup].popover.top-right > .arrow,\r\n[uib-popover-template-popup].popover.bottom-left > .arrow,\r\n[uib-popover-template-popup].popover.bottom-right > .arrow,\r\n[uib-popover-template-popup].popover.left-top > .arrow,\r\n[uib-popover-template-popup].popover.left-bottom > .arrow,\r\n[uib-popover-template-popup].popover.right-top > .arrow,\r\n[uib-popover-template-popup].popover.right-bottom > .arrow {\r\n top: auto;\r\n bottom: auto;\r\n left: auto;\r\n right: auto;\r\n margin: 0;\r\n}\r\n\r\n[uib-popover-popup].popover,\r\n[uib-popover-html-popup].popover,\r\n[uib-popover-template-popup].popover {\r\n display: block !important;\r\n}\r\n", "angular.module('ui.bootstrap.position', [])\n\n/**\n * A set of utility methods for working with the DOM.\n * It is meant to be used where we need to absolute-position elements in\n * relation to another element (this is the case for tooltips, popovers,\n * typeahead suggestions etc.).\n */\n .factory('$uibPosition', ['$document', '$window', function($document, $window) {\n /**\n * Used by scrollbarWidth() function to cache scrollbar's width.\n * Do not access this variable directly, use scrollbarWidth() instead.\n */\n var SCROLLBAR_WIDTH;\n /**\n * scrollbar on body and html element in IE and Edge overlay\n * content and should be considered 0 width.\n */\n var BODY_SCROLLBAR_WIDTH;\n var OVERFLOW_REGEX = {\n normal: /(auto|scroll)/,\n hidden: /(auto|scroll|hidden)/\n };\n var PLACEMENT_REGEX = {\n auto: /\\s?auto?\\s?/i,\n primary: /^(top|bottom|left|right)$/,\n secondary: /^(top|bottom|left|right|center)$/,\n vertical: /^(top|bottom)$/\n };\n var BODY_REGEX = /(HTML|BODY)/;\n\n return {\n\n /**\n * Provides a raw DOM element from a jQuery/jQLite element.\n *\n * @param {element} elem - The element to convert.\n *\n * @returns {element} A HTML element.\n */\n getRawNode: function(elem) {\n return elem.nodeName ? elem : elem[0] || elem;\n },\n\n /**\n * Provides a parsed number for a style property. Strips\n * units and casts invalid numbers to 0.\n *\n * @param {string} value - The style value to parse.\n *\n * @returns {number} A valid number.\n */\n parseStyle: function(value) {\n value = parseFloat(value);\n return isFinite(value) ? value : 0;\n },\n\n /**\n * Provides the closest positioned ancestor.\n *\n * @param {element} element - The element to get the offest parent for.\n *\n * @returns {element} The closest positioned ancestor.\n */\n offsetParent: function(elem) {\n elem = this.getRawNode(elem);\n\n var offsetParent = elem.offsetParent || $document[0].documentElement;\n\n function isStaticPositioned(el) {\n return ($window.getComputedStyle(el).position || 'static') === 'static';\n }\n\n while (offsetParent && offsetParent !== $document[0].documentElement && isStaticPositioned(offsetParent)) {\n offsetParent = offsetParent.offsetParent;\n }\n\n return offsetParent || $document[0].documentElement;\n },\n\n /**\n * Provides the scrollbar width, concept from TWBS measureScrollbar()\n * function in https://github.com/twbs/bootstrap/blob/master/js/modal.js\n * In IE and Edge, scollbar on body and html element overlay and should\n * return a width of 0.\n *\n * @returns {number} The width of the browser scollbar.\n */\n scrollbarWidth: function(isBody) {\n if (isBody) {\n if (angular.isUndefined(BODY_SCROLLBAR_WIDTH)) {\n var bodyElem = $document.find('body');\n bodyElem.addClass('uib-position-body-scrollbar-measure');\n BODY_SCROLLBAR_WIDTH = $window.innerWidth - bodyElem[0].clientWidth;\n BODY_SCROLLBAR_WIDTH = isFinite(BODY_SCROLLBAR_WIDTH) ? BODY_SCROLLBAR_WIDTH : 0;\n bodyElem.removeClass('uib-position-body-scrollbar-measure');\n }\n return BODY_SCROLLBAR_WIDTH;\n }\n\n if (angular.isUndefined(SCROLLBAR_WIDTH)) {\n var scrollElem = angular.element('
    ');\n $document.find('body').append(scrollElem);\n SCROLLBAR_WIDTH = scrollElem[0].offsetWidth - scrollElem[0].clientWidth;\n SCROLLBAR_WIDTH = isFinite(SCROLLBAR_WIDTH) ? SCROLLBAR_WIDTH : 0;\n scrollElem.remove();\n }\n\n return SCROLLBAR_WIDTH;\n },\n\n /**\n * Provides the padding required on an element to replace the scrollbar.\n *\n * @returns {object} An object with the following properties:\n *
      \n *
    • **scrollbarWidth**: the width of the scrollbar
    • \n *
    • **widthOverflow**: whether the the width is overflowing
    • \n *
    • **right**: the amount of right padding on the element needed to replace the scrollbar
    • \n *
    • **rightOriginal**: the amount of right padding currently on the element
    • \n *
    • **heightOverflow**: whether the the height is overflowing
    • \n *
    • **bottom**: the amount of bottom padding on the element needed to replace the scrollbar
    • \n *
    • **bottomOriginal**: the amount of bottom padding currently on the element
    • \n *
    \n */\n scrollbarPadding: function(elem) {\n elem = this.getRawNode(elem);\n\n var elemStyle = $window.getComputedStyle(elem);\n var paddingRight = this.parseStyle(elemStyle.paddingRight);\n var paddingBottom = this.parseStyle(elemStyle.paddingBottom);\n var scrollParent = this.scrollParent(elem, false, true);\n var scrollbarWidth = this.scrollbarWidth(BODY_REGEX.test(scrollParent.tagName));\n\n return {\n scrollbarWidth: scrollbarWidth,\n widthOverflow: scrollParent.scrollWidth > scrollParent.clientWidth,\n right: paddingRight + scrollbarWidth,\n originalRight: paddingRight,\n heightOverflow: scrollParent.scrollHeight > scrollParent.clientHeight,\n bottom: paddingBottom + scrollbarWidth,\n originalBottom: paddingBottom\n };\n },\n\n /**\n * Checks to see if the element is scrollable.\n *\n * @param {element} elem - The element to check.\n * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,\n * default is false.\n *\n * @returns {boolean} Whether the element is scrollable.\n */\n isScrollable: function(elem, includeHidden) {\n elem = this.getRawNode(elem);\n\n var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;\n var elemStyle = $window.getComputedStyle(elem);\n return overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX);\n },\n\n /**\n * Provides the closest scrollable ancestor.\n * A port of the jQuery UI scrollParent method:\n * https://github.com/jquery/jquery-ui/blob/master/ui/scroll-parent.js\n *\n * @param {element} elem - The element to find the scroll parent of.\n * @param {boolean=} [includeHidden=false] - Should scroll style of 'hidden' be considered,\n * default is false.\n * @param {boolean=} [includeSelf=false] - Should the element being passed be\n * included in the scrollable llokup.\n *\n * @returns {element} A HTML element.\n */\n scrollParent: function(elem, includeHidden, includeSelf) {\n elem = this.getRawNode(elem);\n\n var overflowRegex = includeHidden ? OVERFLOW_REGEX.hidden : OVERFLOW_REGEX.normal;\n var documentEl = $document[0].documentElement;\n var elemStyle = $window.getComputedStyle(elem);\n if (includeSelf && overflowRegex.test(elemStyle.overflow + elemStyle.overflowY + elemStyle.overflowX)) {\n return elem;\n }\n var excludeStatic = elemStyle.position === 'absolute';\n var scrollParent = elem.parentElement || documentEl;\n\n if (scrollParent === documentEl || elemStyle.position === 'fixed') {\n return documentEl;\n }\n\n while (scrollParent.parentElement && scrollParent !== documentEl) {\n var spStyle = $window.getComputedStyle(scrollParent);\n if (excludeStatic && spStyle.position !== 'static') {\n excludeStatic = false;\n }\n\n if (!excludeStatic && overflowRegex.test(spStyle.overflow + spStyle.overflowY + spStyle.overflowX)) {\n break;\n }\n scrollParent = scrollParent.parentElement;\n }\n\n return scrollParent;\n },\n\n /**\n * Provides read-only equivalent of jQuery's position function:\n * http://api.jquery.com/position/ - distance to closest positioned\n * ancestor. Does not account for margins by default like jQuery position.\n *\n * @param {element} elem - The element to caclulate the position on.\n * @param {boolean=} [includeMargins=false] - Should margins be accounted\n * for, default is false.\n *\n * @returns {object} An object with the following properties:\n *
      \n *
    • **width**: the width of the element
    • \n *
    • **height**: the height of the element
    • \n *
    • **top**: distance to top edge of offset parent
    • \n *
    • **left**: distance to left edge of offset parent
    • \n *
    \n */\n position: function(elem, includeMagins) {\n elem = this.getRawNode(elem);\n\n var elemOffset = this.offset(elem);\n if (includeMagins) {\n var elemStyle = $window.getComputedStyle(elem);\n elemOffset.top -= this.parseStyle(elemStyle.marginTop);\n elemOffset.left -= this.parseStyle(elemStyle.marginLeft);\n }\n var parent = this.offsetParent(elem);\n var parentOffset = {top: 0, left: 0};\n\n if (parent !== $document[0].documentElement) {\n parentOffset = this.offset(parent);\n parentOffset.top += parent.clientTop - parent.scrollTop;\n parentOffset.left += parent.clientLeft - parent.scrollLeft;\n }\n\n return {\n width: Math.round(angular.isNumber(elemOffset.width) ? elemOffset.width : elem.offsetWidth),\n height: Math.round(angular.isNumber(elemOffset.height) ? elemOffset.height : elem.offsetHeight),\n top: Math.round(elemOffset.top - parentOffset.top),\n left: Math.round(elemOffset.left - parentOffset.left)\n };\n },\n\n /**\n * Provides read-only equivalent of jQuery's offset function:\n * http://api.jquery.com/offset/ - distance to viewport. Does\n * not account for borders, margins, or padding on the body\n * element.\n *\n * @param {element} elem - The element to calculate the offset on.\n *\n * @returns {object} An object with the following properties:\n *
      \n *
    • **width**: the width of the element
    • \n *
    • **height**: the height of the element
    • \n *
    • **top**: distance to top edge of viewport
    • \n *
    • **right**: distance to bottom edge of viewport
    • \n *
    \n */\n offset: function(elem) {\n elem = this.getRawNode(elem);\n\n var elemBCR = elem.getBoundingClientRect();\n return {\n width: Math.round(angular.isNumber(elemBCR.width) ? elemBCR.width : elem.offsetWidth),\n height: Math.round(angular.isNumber(elemBCR.height) ? elemBCR.height : elem.offsetHeight),\n top: Math.round(elemBCR.top + ($window.pageYOffset || $document[0].documentElement.scrollTop)),\n left: Math.round(elemBCR.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft))\n };\n },\n\n /**\n * Provides offset distance to the closest scrollable ancestor\n * or viewport. Accounts for border and scrollbar width.\n *\n * Right and bottom dimensions represent the distance to the\n * respective edge of the viewport element. If the element\n * edge extends beyond the viewport, a negative value will be\n * reported.\n *\n * @param {element} elem - The element to get the viewport offset for.\n * @param {boolean=} [useDocument=false] - Should the viewport be the document element instead\n * of the first scrollable element, default is false.\n * @param {boolean=} [includePadding=true] - Should the padding on the offset parent element\n * be accounted for, default is true.\n *\n * @returns {object} An object with the following properties:\n *
      \n *
    • **top**: distance to the top content edge of viewport element
    • \n *
    • **bottom**: distance to the bottom content edge of viewport element
    • \n *
    • **left**: distance to the left content edge of viewport element
    • \n *
    • **right**: distance to the right content edge of viewport element
    • \n *
    \n */\n viewportOffset: function(elem, useDocument, includePadding) {\n elem = this.getRawNode(elem);\n includePadding = includePadding !== false ? true : false;\n\n var elemBCR = elem.getBoundingClientRect();\n var offsetBCR = {top: 0, left: 0, bottom: 0, right: 0};\n\n var offsetParent = useDocument ? $document[0].documentElement : this.scrollParent(elem);\n var offsetParentBCR = offsetParent.getBoundingClientRect();\n\n offsetBCR.top = offsetParentBCR.top + offsetParent.clientTop;\n offsetBCR.left = offsetParentBCR.left + offsetParent.clientLeft;\n if (offsetParent === $document[0].documentElement) {\n offsetBCR.top += $window.pageYOffset;\n offsetBCR.left += $window.pageXOffset;\n }\n offsetBCR.bottom = offsetBCR.top + offsetParent.clientHeight;\n offsetBCR.right = offsetBCR.left + offsetParent.clientWidth;\n\n if (includePadding) {\n var offsetParentStyle = $window.getComputedStyle(offsetParent);\n offsetBCR.top += this.parseStyle(offsetParentStyle.paddingTop);\n offsetBCR.bottom -= this.parseStyle(offsetParentStyle.paddingBottom);\n offsetBCR.left += this.parseStyle(offsetParentStyle.paddingLeft);\n offsetBCR.right -= this.parseStyle(offsetParentStyle.paddingRight);\n }\n\n return {\n top: Math.round(elemBCR.top - offsetBCR.top),\n bottom: Math.round(offsetBCR.bottom - elemBCR.bottom),\n left: Math.round(elemBCR.left - offsetBCR.left),\n right: Math.round(offsetBCR.right - elemBCR.right)\n };\n },\n\n /**\n * Provides an array of placement values parsed from a placement string.\n * Along with the 'auto' indicator, supported placement strings are:\n *
      \n *
    • top: element on top, horizontally centered on host element.
    • \n *
    • top-left: element on top, left edge aligned with host element left edge.
    • \n *
    • top-right: element on top, lerightft edge aligned with host element right edge.
    • \n *
    • bottom: element on bottom, horizontally centered on host element.
    • \n *
    • bottom-left: element on bottom, left edge aligned with host element left edge.
    • \n *
    • bottom-right: element on bottom, right edge aligned with host element right edge.
    • \n *
    • left: element on left, vertically centered on host element.
    • \n *
    • left-top: element on left, top edge aligned with host element top edge.
    • \n *
    • left-bottom: element on left, bottom edge aligned with host element bottom edge.
    • \n *
    • right: element on right, vertically centered on host element.
    • \n *
    • right-top: element on right, top edge aligned with host element top edge.
    • \n *
    • right-bottom: element on right, bottom edge aligned with host element bottom edge.
    • \n *
    \n * A placement string with an 'auto' indicator is expected to be\n * space separated from the placement, i.e: 'auto bottom-left' If\n * the primary and secondary placement values do not match 'top,\n * bottom, left, right' then 'top' will be the primary placement and\n * 'center' will be the secondary placement. If 'auto' is passed, true\n * will be returned as the 3rd value of the array.\n *\n * @param {string} placement - The placement string to parse.\n *\n * @returns {array} An array with the following values\n *
      \n *
    • **[0]**: The primary placement.
    • \n *
    • **[1]**: The secondary placement.
    • \n *
    • **[2]**: If auto is passed: true, else undefined.
    • \n *
    \n */\n parsePlacement: function(placement) {\n var autoPlace = PLACEMENT_REGEX.auto.test(placement);\n if (autoPlace) {\n placement = placement.replace(PLACEMENT_REGEX.auto, '');\n }\n\n placement = placement.split('-');\n\n placement[0] = placement[0] || 'top';\n if (!PLACEMENT_REGEX.primary.test(placement[0])) {\n placement[0] = 'top';\n }\n\n placement[1] = placement[1] || 'center';\n if (!PLACEMENT_REGEX.secondary.test(placement[1])) {\n placement[1] = 'center';\n }\n\n if (autoPlace) {\n placement[2] = true;\n } else {\n placement[2] = false;\n }\n\n return placement;\n },\n\n /**\n * Provides coordinates for an element to be positioned relative to\n * another element. Passing 'auto' as part of the placement parameter\n * will enable smart placement - where the element fits. i.e:\n * 'auto left-top' will check to see if there is enough space to the left\n * of the hostElem to fit the targetElem, if not place right (same for secondary\n * top placement). Available space is calculated using the viewportOffset\n * function.\n *\n * @param {element} hostElem - The element to position against.\n * @param {element} targetElem - The element to position.\n * @param {string=} [placement=top] - The placement for the targetElem,\n * default is 'top'. 'center' is assumed as secondary placement for\n * 'top', 'left', 'right', and 'bottom' placements. Available placements are:\n *
      \n *
    • top
    • \n *
    • top-right
    • \n *
    • top-left
    • \n *
    • bottom
    • \n *
    • bottom-left
    • \n *
    • bottom-right
    • \n *
    • left
    • \n *
    • left-top
    • \n *
    • left-bottom
    • \n *
    • right
    • \n *
    • right-top
    • \n *
    • right-bottom
    • \n *
    \n * @param {boolean=} [appendToBody=false] - Should the top and left values returned\n * be calculated from the body element, default is false.\n *\n * @returns {object} An object with the following properties:\n *
      \n *
    • **top**: Value for targetElem top.
    • \n *
    • **left**: Value for targetElem left.
    • \n *
    • **placement**: The resolved placement.
    • \n *
    \n */\n positionElements: function(hostElem, targetElem, placement, appendToBody) {\n hostElem = this.getRawNode(hostElem);\n targetElem = this.getRawNode(targetElem);\n\n // need to read from prop to support tests.\n var targetWidth = angular.isDefined(targetElem.offsetWidth) ? targetElem.offsetWidth : targetElem.prop('offsetWidth');\n var targetHeight = angular.isDefined(targetElem.offsetHeight) ? targetElem.offsetHeight : targetElem.prop('offsetHeight');\n\n placement = this.parsePlacement(placement);\n\n var hostElemPos = appendToBody ? this.offset(hostElem) : this.position(hostElem);\n var targetElemPos = {top: 0, left: 0, placement: ''};\n\n if (placement[2]) {\n var viewportOffset = this.viewportOffset(hostElem, appendToBody);\n\n var targetElemStyle = $window.getComputedStyle(targetElem);\n var adjustedSize = {\n width: targetWidth + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginLeft) + this.parseStyle(targetElemStyle.marginRight))),\n height: targetHeight + Math.round(Math.abs(this.parseStyle(targetElemStyle.marginTop) + this.parseStyle(targetElemStyle.marginBottom)))\n };\n\n placement[0] = placement[0] === 'top' && adjustedSize.height > viewportOffset.top && adjustedSize.height <= viewportOffset.bottom ? 'bottom' :\n placement[0] === 'bottom' && adjustedSize.height > viewportOffset.bottom && adjustedSize.height <= viewportOffset.top ? 'top' :\n placement[0] === 'left' && adjustedSize.width > viewportOffset.left && adjustedSize.width <= viewportOffset.right ? 'right' :\n placement[0] === 'right' && adjustedSize.width > viewportOffset.right && adjustedSize.width <= viewportOffset.left ? 'left' :\n placement[0];\n\n placement[1] = placement[1] === 'top' && adjustedSize.height - hostElemPos.height > viewportOffset.bottom && adjustedSize.height - hostElemPos.height <= viewportOffset.top ? 'bottom' :\n placement[1] === 'bottom' && adjustedSize.height - hostElemPos.height > viewportOffset.top && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom ? 'top' :\n placement[1] === 'left' && adjustedSize.width - hostElemPos.width > viewportOffset.right && adjustedSize.width - hostElemPos.width <= viewportOffset.left ? 'right' :\n placement[1] === 'right' && adjustedSize.width - hostElemPos.width > viewportOffset.left && adjustedSize.width - hostElemPos.width <= viewportOffset.right ? 'left' :\n placement[1];\n\n if (placement[1] === 'center') {\n if (PLACEMENT_REGEX.vertical.test(placement[0])) {\n var xOverflow = hostElemPos.width / 2 - targetWidth / 2;\n if (viewportOffset.left + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.right) {\n placement[1] = 'left';\n } else if (viewportOffset.right + xOverflow < 0 && adjustedSize.width - hostElemPos.width <= viewportOffset.left) {\n placement[1] = 'right';\n }\n } else {\n var yOverflow = hostElemPos.height / 2 - adjustedSize.height / 2;\n if (viewportOffset.top + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.bottom) {\n placement[1] = 'top';\n } else if (viewportOffset.bottom + yOverflow < 0 && adjustedSize.height - hostElemPos.height <= viewportOffset.top) {\n placement[1] = 'bottom';\n }\n }\n }\n }\n\n switch (placement[0]) {\n case 'top':\n targetElemPos.top = hostElemPos.top - targetHeight;\n break;\n case 'bottom':\n targetElemPos.top = hostElemPos.top + hostElemPos.height;\n break;\n case 'left':\n targetElemPos.left = hostElemPos.left - targetWidth;\n break;\n case 'right':\n targetElemPos.left = hostElemPos.left + hostElemPos.width;\n break;\n }\n\n switch (placement[1]) {\n case 'top':\n targetElemPos.top = hostElemPos.top;\n break;\n case 'bottom':\n targetElemPos.top = hostElemPos.top + hostElemPos.height - targetHeight;\n break;\n case 'left':\n targetElemPos.left = hostElemPos.left;\n break;\n case 'right':\n targetElemPos.left = hostElemPos.left + hostElemPos.width - targetWidth;\n break;\n case 'center':\n if (PLACEMENT_REGEX.vertical.test(placement[0])) {\n targetElemPos.left = hostElemPos.left + hostElemPos.width / 2 - targetWidth / 2;\n } else {\n targetElemPos.top = hostElemPos.top + hostElemPos.height / 2 - targetHeight / 2;\n }\n break;\n }\n\n targetElemPos.top = Math.round(targetElemPos.top);\n targetElemPos.left = Math.round(targetElemPos.left);\n targetElemPos.placement = placement[1] === 'center' ? placement[0] : placement[0] + '-' + placement[1];\n\n return targetElemPos;\n },\n\n /**\n * Provides a way to adjust the top positioning after first\n * render to correctly align element to top after content\n * rendering causes resized element height\n *\n * @param {array} placementClasses - The array of strings of classes\n * element should have.\n * @param {object} containerPosition - The object with container\n * position information\n * @param {number} initialHeight - The initial height for the elem.\n * @param {number} currentHeight - The current height for the elem.\n */\n adjustTop: function(placementClasses, containerPosition, initialHeight, currentHeight) {\n if (placementClasses.indexOf('top') !== -1 && initialHeight !== currentHeight) {\n return {\n top: containerPosition.top - currentHeight + 'px'\n };\n }\n },\n\n /**\n * Provides a way for positioning tooltip & dropdown\n * arrows when using placement options beyond the standard\n * left, right, top, or bottom.\n *\n * @param {element} elem - The tooltip/dropdown element.\n * @param {string} placement - The placement for the elem.\n */\n positionArrow: function(elem, placement) {\n elem = this.getRawNode(elem);\n\n var innerElem = elem.querySelector('.tooltip-inner, .popover-inner');\n if (!innerElem) {\n return;\n }\n\n var isTooltip = angular.element(innerElem).hasClass('tooltip-inner');\n\n var arrowElem = isTooltip ? elem.querySelector('.tooltip-arrow') : elem.querySelector('.arrow');\n if (!arrowElem) {\n return;\n }\n\n var arrowCss = {\n top: '',\n bottom: '',\n left: '',\n right: ''\n };\n\n placement = this.parsePlacement(placement);\n if (placement[1] === 'center') {\n // no adjustment necessary - just reset styles\n angular.element(arrowElem).css(arrowCss);\n return;\n }\n\n var borderProp = 'border-' + placement[0] + '-width';\n var borderWidth = $window.getComputedStyle(arrowElem)[borderProp];\n\n var borderRadiusProp = 'border-';\n if (PLACEMENT_REGEX.vertical.test(placement[0])) {\n borderRadiusProp += placement[0] + '-' + placement[1];\n } else {\n borderRadiusProp += placement[1] + '-' + placement[0];\n }\n borderRadiusProp += '-radius';\n var borderRadius = $window.getComputedStyle(isTooltip ? innerElem : elem)[borderRadiusProp];\n\n switch (placement[0]) {\n case 'top':\n arrowCss.bottom = isTooltip ? '0' : '-' + borderWidth;\n break;\n case 'bottom':\n arrowCss.top = isTooltip ? '0' : '-' + borderWidth;\n break;\n case 'left':\n arrowCss.right = isTooltip ? '0' : '-' + borderWidth;\n break;\n case 'right':\n arrowCss.left = isTooltip ? '0' : '-' + borderWidth;\n break;\n }\n\n arrowCss[placement[1]] = borderRadius;\n\n angular.element(arrowElem).css(arrowCss);\n }\n };\n }]);\n", "require('./position');\n\nvar MODULE_NAME = 'ui.bootstrap.module.position';\n\nangular.module(MODULE_NAME, ['ui.bootstrap.position']);\n\nmodule.exports = MODULE_NAME;\n", "angular.module('ui.bootstrap.stackedMap', [])\n/**\n * A helper, internal data structure that acts as a map but also allows getting / removing\n * elements in the LIFO order\n */\n .factory('$$stackedMap', function() {\n return {\n createNew: function() {\n var stack = [];\n\n return {\n add: function(key, value) {\n stack.push({\n key: key,\n value: value\n });\n },\n get: function(key) {\n for (var i = 0; i < stack.length; i++) {\n if (key === stack[i].key) {\n return stack[i];\n }\n }\n },\n keys: function() {\n var keys = [];\n for (var i = 0; i < stack.length; i++) {\n keys.push(stack[i].key);\n }\n return keys;\n },\n top: function() {\n return stack[stack.length - 1];\n },\n remove: function(key) {\n var idx = -1;\n for (var i = 0; i < stack.length; i++) {\n if (key === stack[i].key) {\n idx = i;\n break;\n }\n }\n return stack.splice(idx, 1)[0];\n },\n removeTop: function() {\n return stack.pop();\n },\n length: function() {\n return stack.length;\n }\n };\n }\n };\n });", "require('./stackedMap');\n\nvar MODULE_NAME = 'ui.bootstrap.module.stackedMap';\n\nangular.module(MODULE_NAME, ['ui.bootstrap.stackedMap']);\n\nmodule.exports = MODULE_NAME;\n", "angular.module(\"uib/template/tooltip/tooltip-popup.html\", []).run([\"$templateCache\", function ($templateCache) {\n $templateCache.put(\"uib/template/tooltip/tooltip-popup.html\",\n \"
    \\n\" +\n \"
    \\n\" +\n \"\");\n}]);\n", "angular.module(\"uib/template/tooltip/tooltip-html-popup.html\", []).run([\"$templateCache\", function ($templateCache) {\n $templateCache.put(\"uib/template/tooltip/tooltip-html-popup.html\",\n \"
    \\n\" +\n \"
    \\n\" +\n \"\");\n}]);\n", "angular.module(\"uib/template/tooltip/tooltip-template-popup.html\", []).run([\"$templateCache\", function ($templateCache) {\n $templateCache.put(\"uib/template/tooltip/tooltip-template-popup.html\",\n \"
    \\n\" +\n \"
    \\n\" +\n \"\");\n}]);\n", "/**\n * The following features are still outstanding: animation as a\n * function, placement as a function, inside, support for more triggers than\n * just mouse enter/leave, html tooltips, and selector delegation.\n */\nangular.module('ui.bootstrap.tooltip', ['ui.bootstrap.position', 'ui.bootstrap.stackedMap'])\n\n/**\n * The $tooltip service creates tooltip- and popover-like directives as well as\n * houses global options for them.\n */\n.provider('$uibTooltip', function() {\n // The default options tooltip and popover.\n var defaultOptions = {\n placement: 'top',\n placementClassPrefix: '',\n animation: true,\n popupDelay: 0,\n popupCloseDelay: 0,\n useContentExp: false\n };\n\n // Default hide triggers for each show trigger\n var triggerMap = {\n 'mouseenter': 'mouseleave',\n 'click': 'click',\n 'outsideClick': 'outsideClick',\n 'focus': 'blur',\n 'none': ''\n };\n\n // The options specified to the provider globally.\n var globalOptions = {};\n\n /**\n * `options({})` allows global configuration of all tooltips in the\n * application.\n *\n * var app = angular.module( 'App', ['ui.bootstrap.tooltip'], function( $tooltipProvider ) {\n * // place tooltips left instead of top by default\n * $tooltipProvider.options( { placement: 'left' } );\n * });\n */\n\tthis.options = function(value) {\n\t\tangular.extend(globalOptions, value);\n\t};\n\n /**\n * This allows you to extend the set of trigger mappings available. E.g.:\n *\n * $tooltipProvider.setTriggers( { 'openTrigger': 'closeTrigger' } );\n */\n this.setTriggers = function setTriggers(triggers) {\n angular.extend(triggerMap, triggers);\n };\n\n /**\n * This is a helper function for translating camel-case to snake_case.\n */\n function snake_case(name) {\n var regexp = /[A-Z]/g;\n var separator = '-';\n return name.replace(regexp, function(letter, pos) {\n return (pos ? separator : '') + letter.toLowerCase();\n });\n }\n\n /**\n * Returns the actual instance of the $tooltip service.\n * TODO support multiple triggers\n */\n this.$get = ['$window', '$compile', '$timeout', '$document', '$uibPosition', '$interpolate', '$rootScope', '$parse', '$$stackedMap', function($window, $compile, $timeout, $document, $position, $interpolate, $rootScope, $parse, $$stackedMap) {\n var openedTooltips = $$stackedMap.createNew();\n $document.on('keyup', keypressListener);\n\n $rootScope.$on('$destroy', function() {\n $document.off('keyup', keypressListener);\n });\n\n function keypressListener(e) {\n if (e.which === 27) {\n var last = openedTooltips.top();\n if (last) {\n last.value.close();\n last = null;\n }\n }\n }\n\n return function $tooltip(ttType, prefix, defaultTriggerShow, options) {\n options = angular.extend({}, defaultOptions, globalOptions, options);\n\n /**\n * Returns an object of show and hide triggers.\n *\n * If a trigger is supplied,\n * it is used to show the tooltip; otherwise, it will use the `trigger`\n * option passed to the `$tooltipProvider.options` method; else it will\n * default to the trigger supplied to this directive factory.\n *\n * The hide trigger is based on the show trigger. If the `trigger` option\n * was passed to the `$tooltipProvider.options` method, it will use the\n * mapped trigger from `triggerMap` or the passed trigger if the map is\n * undefined; otherwise, it uses the `triggerMap` value of the show\n * trigger; else it will just use the show trigger.\n */\n function getTriggers(trigger) {\n var show = (trigger || options.trigger || defaultTriggerShow).split(' ');\n var hide = show.map(function(trigger) {\n return triggerMap[trigger] || trigger;\n });\n return {\n show: show,\n hide: hide\n };\n }\n\n var directiveName = snake_case(ttType);\n\n var startSym = $interpolate.startSymbol();\n var endSym = $interpolate.endSymbol();\n var template =\n '
    ' +\n '
    ';\n\n return {\n compile: function(tElem, tAttrs) {\n var tooltipLinker = $compile(template);\n\n return function link(scope, element, attrs, tooltipCtrl) {\n var tooltip;\n var tooltipLinkedScope;\n var transitionTimeout;\n var showTimeout;\n var hideTimeout;\n var positionTimeout;\n var adjustmentTimeout;\n var appendToBody = angular.isDefined(options.appendToBody) ? options.appendToBody : false;\n var triggers = getTriggers(undefined);\n var hasEnableExp = angular.isDefined(attrs[prefix + 'Enable']);\n var ttScope = scope.$new(true);\n var repositionScheduled = false;\n var isOpenParse = angular.isDefined(attrs[prefix + 'IsOpen']) ? $parse(attrs[prefix + 'IsOpen']) : false;\n var contentParse = options.useContentExp ? $parse(attrs[ttType]) : false;\n var observers = [];\n var lastPlacement;\n\n var positionTooltip = function() {\n // check if tooltip exists and is not empty\n if (!tooltip || !tooltip.html()) { return; }\n\n if (!positionTimeout) {\n positionTimeout = $timeout(function() {\n var ttPosition = $position.positionElements(element, tooltip, ttScope.placement, appendToBody);\n var initialHeight = angular.isDefined(tooltip.offsetHeight) ? tooltip.offsetHeight : tooltip.prop('offsetHeight');\n var elementPos = appendToBody ? $position.offset(element) : $position.position(element);\n tooltip.css({ top: ttPosition.top + 'px', left: ttPosition.left + 'px' });\n var placementClasses = ttPosition.placement.split('-');\n\n if (!tooltip.hasClass(placementClasses[0])) {\n tooltip.removeClass(lastPlacement.split('-')[0]);\n tooltip.addClass(placementClasses[0]);\n }\n\n if (!tooltip.hasClass(options.placementClassPrefix + ttPosition.placement)) {\n tooltip.removeClass(options.placementClassPrefix + lastPlacement);\n tooltip.addClass(options.placementClassPrefix + ttPosition.placement);\n }\n\n adjustmentTimeout = $timeout(function() {\n var currentHeight = angular.isDefined(tooltip.offsetHeight) ? tooltip.offsetHeight : tooltip.prop('offsetHeight');\n var adjustment = $position.adjustTop(placementClasses, elementPos, initialHeight, currentHeight);\n if (adjustment) {\n tooltip.css(adjustment);\n }\n adjustmentTimeout = null;\n }, 0, false);\n\n // first time through tt element will have the\n // uib-position-measure class or if the placement\n // has changed we need to position the arrow.\n if (tooltip.hasClass('uib-position-measure')) {\n $position.positionArrow(tooltip, ttPosition.placement);\n tooltip.removeClass('uib-position-measure');\n } else if (lastPlacement !== ttPosition.placement) {\n $position.positionArrow(tooltip, ttPosition.placement);\n }\n lastPlacement = ttPosition.placement;\n\n positionTimeout = null;\n }, 0, false);\n }\n };\n\n // Set up the correct scope to allow transclusion later\n ttScope.origScope = scope;\n\n // By default, the tooltip is not open.\n // TODO add ability to start tooltip opened\n ttScope.isOpen = false;\n\n function toggleTooltipBind() {\n if (!ttScope.isOpen) {\n showTooltipBind();\n } else {\n hideTooltipBind();\n }\n }\n\n // Show the tooltip with delay if specified, otherwise show it immediately\n function showTooltipBind() {\n if (hasEnableExp && !scope.$eval(attrs[prefix + 'Enable'])) {\n return;\n }\n\n cancelHide();\n prepareTooltip();\n\n if (ttScope.popupDelay) {\n // Do nothing if the tooltip was already scheduled to pop-up.\n // This happens if show is triggered multiple times before any hide is triggered.\n if (!showTimeout) {\n showTimeout = $timeout(show, ttScope.popupDelay, false);\n }\n } else {\n show();\n }\n }\n\n function hideTooltipBind() {\n cancelShow();\n\n if (ttScope.popupCloseDelay) {\n if (!hideTimeout) {\n hideTimeout = $timeout(hide, ttScope.popupCloseDelay, false);\n }\n } else {\n hide();\n }\n }\n\n // Show the tooltip popup element.\n function show() {\n cancelShow();\n cancelHide();\n\n // Don't show empty tooltips.\n if (!ttScope.content) {\n return angular.noop;\n }\n\n createTooltip();\n\n // And show the tooltip.\n ttScope.$evalAsync(function() {\n ttScope.isOpen = true;\n assignIsOpen(true);\n positionTooltip();\n });\n }\n\n function cancelShow() {\n if (showTimeout) {\n $timeout.cancel(showTimeout);\n showTimeout = null;\n }\n\n if (positionTimeout) {\n $timeout.cancel(positionTimeout);\n positionTimeout = null;\n }\n }\n\n // Hide the tooltip popup element.\n function hide() {\n if (!ttScope) {\n return;\n }\n\n // First things first: we don't show it anymore.\n ttScope.$evalAsync(function() {\n if (ttScope) {\n ttScope.isOpen = false;\n assignIsOpen(false);\n // And now we remove it from the DOM. However, if we have animation, we\n // need to wait for it to expire beforehand.\n // FIXME: this is a placeholder for a port of the transitions library.\n // The fade transition in TWBS is 150ms.\n if (ttScope.animation) {\n if (!transitionTimeout) {\n transitionTimeout = $timeout(removeTooltip, 150, false);\n }\n } else {\n removeTooltip();\n }\n }\n });\n }\n\n function cancelHide() {\n if (hideTimeout) {\n $timeout.cancel(hideTimeout);\n hideTimeout = null;\n }\n\n if (transitionTimeout) {\n $timeout.cancel(transitionTimeout);\n transitionTimeout = null;\n }\n }\n\n function createTooltip() {\n // There can only be one tooltip element per directive shown at once.\n if (tooltip) {\n return;\n }\n\n tooltipLinkedScope = ttScope.$new();\n tooltip = tooltipLinker(tooltipLinkedScope, function(tooltip) {\n if (appendToBody) {\n $document.find('body').append(tooltip);\n } else {\n element.after(tooltip);\n }\n });\n\n openedTooltips.add(ttScope, {\n close: hide\n });\n\n prepObservers();\n }\n\n function removeTooltip() {\n cancelShow();\n cancelHide();\n unregisterObservers();\n\n if (tooltip) {\n tooltip.remove();\n \n tooltip = null;\n if (adjustmentTimeout) {\n $timeout.cancel(adjustmentTimeout);\n }\n }\n\n openedTooltips.remove(ttScope);\n \n if (tooltipLinkedScope) {\n tooltipLinkedScope.$destroy();\n tooltipLinkedScope = null;\n }\n }\n\n /**\n * Set the initial scope values. Once\n * the tooltip is created, the observers\n * will be added to keep things in sync.\n */\n function prepareTooltip() {\n ttScope.title = attrs[prefix + 'Title'];\n if (contentParse) {\n ttScope.content = contentParse(scope);\n } else {\n ttScope.content = attrs[ttType];\n }\n\n ttScope.popupClass = attrs[prefix + 'Class'];\n ttScope.placement = angular.isDefined(attrs[prefix + 'Placement']) ? attrs[prefix + 'Placement'] : options.placement;\n var placement = $position.parsePlacement(ttScope.placement);\n lastPlacement = placement[1] ? placement[0] + '-' + placement[1] : placement[0];\n\n var delay = parseInt(attrs[prefix + 'PopupDelay'], 10);\n var closeDelay = parseInt(attrs[prefix + 'PopupCloseDelay'], 10);\n ttScope.popupDelay = !isNaN(delay) ? delay : options.popupDelay;\n ttScope.popupCloseDelay = !isNaN(closeDelay) ? closeDelay : options.popupCloseDelay;\n }\n\n function assignIsOpen(isOpen) {\n if (isOpenParse && angular.isFunction(isOpenParse.assign)) {\n isOpenParse.assign(scope, isOpen);\n }\n }\n\n ttScope.contentExp = function() {\n return ttScope.content;\n };\n\n /**\n * Observe the relevant attributes.\n */\n attrs.$observe('disabled', function(val) {\n if (val) {\n cancelShow();\n }\n\n if (val && ttScope.isOpen) {\n hide();\n }\n });\n\n if (isOpenParse) {\n scope.$watch(isOpenParse, function(val) {\n if (ttScope && !val === ttScope.isOpen) {\n toggleTooltipBind();\n }\n });\n }\n\n function prepObservers() {\n observers.length = 0;\n\n if (contentParse) {\n observers.push(\n scope.$watch(contentParse, function(val) {\n ttScope.content = val;\n if (!val && ttScope.isOpen) {\n hide();\n }\n })\n );\n\n observers.push(\n tooltipLinkedScope.$watch(function() {\n if (!repositionScheduled) {\n repositionScheduled = true;\n tooltipLinkedScope.$$postDigest(function() {\n repositionScheduled = false;\n if (ttScope && ttScope.isOpen) {\n positionTooltip();\n }\n });\n }\n })\n );\n } else {\n observers.push(\n attrs.$observe(ttType, function(val) {\n ttScope.content = val;\n if (!val && ttScope.isOpen) {\n hide();\n } else {\n positionTooltip();\n }\n })\n );\n }\n\n observers.push(\n attrs.$observe(prefix + 'Title', function(val) {\n ttScope.title = val;\n if (ttScope.isOpen) {\n positionTooltip();\n }\n })\n );\n\n observers.push(\n attrs.$observe(prefix + 'Placement', function(val) {\n ttScope.placement = val ? val : options.placement;\n if (ttScope.isOpen) {\n positionTooltip();\n }\n })\n );\n }\n\n function unregisterObservers() {\n if (observers.length) {\n angular.forEach(observers, function(observer) {\n observer();\n });\n observers.length = 0;\n }\n }\n\n // hide tooltips/popovers for outsideClick trigger\n function bodyHideTooltipBind(e) {\n if (!ttScope || !ttScope.isOpen || !tooltip) {\n return;\n }\n // make sure the tooltip/popover link or tool tooltip/popover itself were not clicked\n if (!element[0].contains(e.target) && !tooltip[0].contains(e.target)) {\n hideTooltipBind();\n }\n }\n\n // KeyboardEvent handler to hide the tooltip on Escape key press\n function hideOnEscapeKey(e) {\n if (e.which === 27) {\n hideTooltipBind();\n }\n }\n\n var unregisterTriggers = function() {\n triggers.show.forEach(function(trigger) {\n if (trigger === 'outsideClick') {\n element.off('click', toggleTooltipBind);\n } else {\n element.off(trigger, showTooltipBind);\n element.off(trigger, toggleTooltipBind);\n }\n element.off('keypress', hideOnEscapeKey);\n });\n triggers.hide.forEach(function(trigger) {\n if (trigger === 'outsideClick') {\n $document.off('click', bodyHideTooltipBind);\n } else {\n element.off(trigger, hideTooltipBind);\n }\n });\n };\n\n function prepTriggers() {\n var showTriggers = [], hideTriggers = [];\n var val = scope.$eval(attrs[prefix + 'Trigger']);\n unregisterTriggers();\n\n if (angular.isObject(val)) {\n Object.keys(val).forEach(function(key) {\n showTriggers.push(key);\n hideTriggers.push(val[key]);\n });\n triggers = {\n show: showTriggers,\n hide: hideTriggers\n };\n } else {\n triggers = getTriggers(val);\n }\n\n if (triggers.show !== 'none') {\n triggers.show.forEach(function(trigger, idx) {\n if (trigger === 'outsideClick') {\n element.on('click', toggleTooltipBind);\n $document.on('click', bodyHideTooltipBind);\n } else if (trigger === triggers.hide[idx]) {\n element.on(trigger, toggleTooltipBind);\n } else if (trigger) {\n element.on(trigger, showTooltipBind);\n element.on(triggers.hide[idx], hideTooltipBind);\n }\n element.on('keypress', hideOnEscapeKey);\n });\n }\n }\n\n prepTriggers();\n\n var animation = scope.$eval(attrs[prefix + 'Animation']);\n ttScope.animation = angular.isDefined(animation) ? !!animation : options.animation;\n\n var appendToBodyVal;\n var appendKey = prefix + 'AppendToBody';\n if (appendKey in attrs && attrs[appendKey] === undefined) {\n appendToBodyVal = true;\n } else {\n appendToBodyVal = scope.$eval(attrs[appendKey]);\n }\n\n appendToBody = angular.isDefined(appendToBodyVal) ? appendToBodyVal : appendToBody;\n\n // Make sure tooltip is destroyed and removed.\n scope.$on('$destroy', function onDestroyTooltip() {\n unregisterTriggers();\n removeTooltip();\n ttScope = null;\n });\n };\n }\n };\n };\n }];\n})\n\n// This is mostly ngInclude code but with a custom scope\n.directive('uibTooltipTemplateTransclude', [\n '$animate', '$sce', '$compile', '$templateRequest',\nfunction ($animate, $sce, $compile, $templateRequest) {\n return {\n link: function(scope, elem, attrs) {\n var origScope = scope.$eval(attrs.tooltipTemplateTranscludeScope);\n\n var changeCounter = 0,\n currentScope,\n previousElement,\n currentElement;\n\n var cleanupLastIncludeContent = function() {\n if (previousElement) {\n previousElement.remove();\n previousElement = null;\n }\n\n if (currentScope) {\n currentScope.$destroy();\n currentScope = null;\n }\n\n if (currentElement) {\n $animate.leave(currentElement).then(function() {\n previousElement = null;\n });\n previousElement = currentElement;\n currentElement = null;\n }\n };\n\n scope.$watch($sce.parseAsResourceUrl(attrs.uibTooltipTemplateTransclude), function(src) {\n var thisChangeId = ++changeCounter;\n\n if (src) {\n //set the 2nd param to true to ignore the template request error so that the inner\n //contents and scope can be cleaned up.\n $templateRequest(src, true).then(function(response) {\n if (thisChangeId !== changeCounter) { return; }\n var newScope = origScope.$new();\n var template = response;\n\n var clone = $compile(template)(newScope, function(clone) {\n cleanupLastIncludeContent();\n $animate.enter(clone, elem);\n });\n\n currentScope = newScope;\n currentElement = clone;\n\n currentScope.$emit('$includeContentLoaded', src);\n }, function() {\n if (thisChangeId === changeCounter) {\n cleanupLastIncludeContent();\n scope.$emit('$includeContentError', src);\n }\n });\n scope.$emit('$includeContentRequested', src);\n } else {\n cleanupLastIncludeContent();\n }\n });\n\n scope.$on('$destroy', cleanupLastIncludeContent);\n }\n };\n}])\n\n/**\n * Note that it's intentional that these classes are *not* applied through $animate.\n * They must not be animated as they're expected to be present on the tooltip on\n * initialization.\n */\n.directive('uibTooltipClasses', ['$uibPosition', function($uibPosition) {\n return {\n restrict: 'A',\n link: function(scope, element, attrs) {\n // need to set the primary position so the\n // arrow has space during position measure.\n // tooltip.positionTooltip()\n if (scope.placement) {\n // // There are no top-left etc... classes\n // // in TWBS, so we need the primary position.\n var position = $uibPosition.parsePlacement(scope.placement);\n element.addClass(position[0]);\n }\n\n if (scope.popupClass) {\n element.addClass(scope.popupClass);\n }\n\n if (scope.animation) {\n element.addClass(attrs.tooltipAnimationClass);\n }\n }\n };\n}])\n\n.directive('uibTooltipPopup', function() {\n return {\n restrict: 'A',\n scope: { content: '@' },\n templateUrl: 'uib/template/tooltip/tooltip-popup.html'\n };\n})\n\n.directive('uibTooltip', [ '$uibTooltip', function($uibTooltip) {\n return $uibTooltip('uibTooltip', 'tooltip', 'mouseenter');\n}])\n\n.directive('uibTooltipTemplatePopup', function() {\n return {\n restrict: 'A',\n scope: { contentExp: '&', originScope: '&' },\n templateUrl: 'uib/template/tooltip/tooltip-template-popup.html'\n };\n})\n\n.directive('uibTooltipTemplate', ['$uibTooltip', function($uibTooltip) {\n return $uibTooltip('uibTooltipTemplate', 'tooltip', 'mouseenter', {\n useContentExp: true\n });\n}])\n\n.directive('uibTooltipHtmlPopup', function() {\n return {\n restrict: 'A',\n scope: { contentExp: '&' },\n templateUrl: 'uib/template/tooltip/tooltip-html-popup.html'\n };\n})\n\n.directive('uibTooltipHtml', ['$uibTooltip', function($uibTooltip) {\n return $uibTooltip('uibTooltipHtml', 'tooltip', 'mouseenter', {\n useContentExp: true\n });\n}]);\n", "require('../position/index-nocss.js');\nrequire('../stackedMap');\nrequire('../../template/tooltip/tooltip-popup.html.js');\nrequire('../../template/tooltip/tooltip-html-popup.html.js');\nrequire('../../template/tooltip/tooltip-template-popup.html.js');\nrequire('./tooltip');\n\nvar MODULE_NAME = 'ui.bootstrap.module.tooltip';\n\nangular.module(MODULE_NAME, ['ui.bootstrap.tooltip', 'uib/template/tooltip/tooltip-popup.html', 'uib/template/tooltip/tooltip-html-popup.html', 'uib/template/tooltip/tooltip-template-popup.html']);\n\nmodule.exports = MODULE_NAME;\n", "angular.module(\"uib/template/popover/popover.html\", []).run([\"$templateCache\", function ($templateCache) {\n $templateCache.put(\"uib/template/popover/popover.html\",\n \"
    \\n\" +\n \"\\n\" +\n \"
    \\n\" +\n \"

    \\n\" +\n \"
    \\n\" +\n \"
    \\n\" +\n \"\");\n}]);\n", "angular.module(\"uib/template/popover/popover-html.html\", []).run([\"$templateCache\", function ($templateCache) {\n $templateCache.put(\"uib/template/popover/popover-html.html\",\n \"
    \\n\" +\n \"\\n\" +\n \"
    \\n\" +\n \"

    \\n\" +\n \"
    \\n\" +\n \"
    \\n\" +\n \"\");\n}]);\n", "angular.module(\"uib/template/popover/popover-template.html\", []).run([\"$templateCache\", function ($templateCache) {\n $templateCache.put(\"uib/template/popover/popover-template.html\",\n \"
    \\n\" +\n \"\\n\" +\n \"
    \\n\" +\n \"

    \\n\" +\n \"
    \\n\" +\n \"
    \\n\" +\n \"\");\n}]);\n", "/**\n * The following features are still outstanding: popup delay, animation as a\n * function, placement as a function, inside, support for more triggers than\n * just mouse enter/leave, and selector delegatation.\n */\nangular.module('ui.bootstrap.popover', ['ui.bootstrap.tooltip'])\n\n.directive('uibPopoverTemplatePopup', function() {\n return {\n restrict: 'A',\n scope: { uibTitle: '@', contentExp: '&', originScope: '&' },\n templateUrl: 'uib/template/popover/popover-template.html'\n };\n})\n\n.directive('uibPopoverTemplate', ['$uibTooltip', function($uibTooltip) {\n return $uibTooltip('uibPopoverTemplate', 'popover', 'click', {\n useContentExp: true\n });\n}])\n\n.directive('uibPopoverHtmlPopup', function() {\n return {\n restrict: 'A',\n scope: { contentExp: '&', uibTitle: '@' },\n templateUrl: 'uib/template/popover/popover-html.html'\n };\n})\n\n.directive('uibPopoverHtml', ['$uibTooltip', function($uibTooltip) {\n return $uibTooltip('uibPopoverHtml', 'popover', 'click', {\n useContentExp: true\n });\n}])\n\n.directive('uibPopoverPopup', function() {\n return {\n restrict: 'A',\n scope: { uibTitle: '@', content: '@' },\n templateUrl: 'uib/template/popover/popover.html'\n };\n})\n\n.directive('uibPopover', ['$uibTooltip', function($uibTooltip) {\n return $uibTooltip('uibPopover', 'popover', 'click');\n}]);\n", "require('../tooltip/index-nocss.js');\nrequire('../../template/popover/popover.html.js');\nrequire('../../template/popover/popover-html.html.js');\nrequire('../../template/popover/popover-template.html.js');\nrequire('./popover');\n\nvar MODULE_NAME = 'ui.bootstrap.module.popover';\n\nangular.module(MODULE_NAME, ['ui.bootstrap.popover', 'uib/template/popover/popover.html', 'uib/template/popover/popover-html.html', 'uib/template/popover/popover-template.html']);\n\nmodule.exports = MODULE_NAME;\n", "require('../tooltip/tooltip.css');\nmodule.exports = require('./index-nocss.js');\n", "\uFEFFimport catalogModule from '../scripts/catalog/catalog.module.js';\n\nimport appDependency from '../scripts/appDependency.js';\n\nappDependency.addItem(catalogModule);\n", "\uFEFFimport '../../styles/partials/product-categories.scss';\nimport '../../styles/partials/pagenumberer.scss';\n\nimport productViewModule from '../_partials/product-view/productView.module.js';\nimport catalogFilterModule from '../_partials/catalog-filter/catalogFilter.module.js';\n\nimport CatalogCtrl from './contollers/catalogController.js';\n\nconst moduleName = 'catalog';\n\nangular.module(moduleName, [productViewModule, catalogFilterModule]).controller('CatalogCtrl', CatalogCtrl);\n\nexport default moduleName;\n", "\uFEFFimport carouselModule from '../../_common/carousel/carousel.module.js';\nimport ratingModule from '../../_common/rating/rating.module.js';\nimport quickviewModule from '../quickview/quickview.module.js';\nimport colorsViewerModule from '../colors-viewer/colorsViewer.module.js';\nimport productsCarouselModule from '../products-carousel/productsCarousel.module.js';\nimport photoViewListModule from '../../../scripts/_partials/photo-view-list/photoViewList.module.js';\n\nimport './styles/product-view.scss';\nimport '../price-amount-list/styles/price-amount-list.scss';\n\nimport productViewService from './services/productViewService.js';\nimport {\n productViewItemDirective,\n productViewCarouselPhotosDirective,\n productViewChangeModeDirective,\n productViewModeDirective,\n productViewImageListDirective,\n productViewScrollPhotosDirective,\n productViewImageDirective,\n} from './directives/productViewDirectives.js';\n\nimport ProductViewCarouselPhotosCtrl from './controllers/productViewCarouselPhotosController.js';\nimport ProductViewChangeModeCtrl from './controllers/productViewChangeModeController.js';\nimport ProductViewItemCtrl from './controllers/productViewItemController.js';\nimport ProductViewModeCtrl from './controllers/productViewModeController.js';\n\nimport '../../../styles/partials/modal-video.scss';\nimport ProductViewImageListCtrl from './controllers/productViewImageListController.js';\nimport ProductViewImageCtrl from './controllers/productViewImageController.js';\n\nconst moduleName = 'productView';\n\nangular\n .module(moduleName, [ratingModule, quickviewModule, colorsViewerModule, productsCarouselModule, photoViewListModule, carouselModule])\n .constant('viewPrefix', {\n desktop: '',\n mobile: 'mobile-',\n mobileModern: 'mobile-modern-',\n })\n .constant('viewList', {\n desktop: ['tile', 'list', 'table'],\n mobile: ['tile', 'list', 'single'],\n mobileModern: ['tile', 'list', 'single'],\n })\n .service('productViewService', productViewService)\n .directive('productViewItem', productViewItemDirective)\n .directive('productViewCarouselPhotos', productViewCarouselPhotosDirective)\n .directive('productViewChangeMode', productViewChangeModeDirective)\n .directive('productViewMode', productViewModeDirective)\n .directive('productViewImageList', productViewImageListDirective)\n .directive('productViewImage', productViewImageDirective)\n .directive('productViewScrollPhotos', productViewScrollPhotosDirective)\n .controller('ProductViewCarouselPhotosCtrl', ProductViewCarouselPhotosCtrl)\n .controller('ProductViewChangeModeCtrl', ProductViewChangeModeCtrl)\n .controller('ProductViewItemCtrl', ProductViewItemCtrl)\n .controller('ProductViewImageListCtrl', ProductViewImageListCtrl)\n .controller('ProductViewImageCtrl', ProductViewImageCtrl)\n .controller('ProductViewModeCtrl', ProductViewModeCtrl);\n\nexport default moduleName;\n", "\uFEFFimport './styles/quickview.scss';\n\nimport QuickviewCtrl from './controllers/quickviewController.js';\nimport { quickviewTriggerDirective } from './directives/quickviewDirectives.js';\nimport quickviewService from './services/quickviewService.js';\nimport priceAmountListModule from '../price-amount-list/priceAmountList.module.js';\n\nconst moduleName = 'quickview';\n\nangular\n .module(moduleName, [priceAmountListModule])\n .controller('QuickviewCtrl', QuickviewCtrl)\n .directive('quickviewTrigger', quickviewTriggerDirective)\n .service('quickviewService', quickviewService);\n\nexport default moduleName;\n", "function QuickviewCtrl(quickviewService, cartService, cartConfig, domService, $location, urlHelper, $q, $ocLazyLoad) {\n var ctrl = this,\n colorsAndSize = {},\n triggers = [];\n ctrl.addTrigger = function (productId) {\n triggers.push(productId);\n };\n ctrl.showModal = function (productId, colorId, typeView, modalClass, landingId, hideShipping, showLeadButton, blockId, showVideo, modalId, openFromHash, sizeId, onOpenModalCallback, spyAddress, descriptionMode, cartAddType) {\n /*\u0412\u042B\u0417\u042B\u0412\u0410\u0415\u0422 \u0410\u041D\u0413\u0423\u041B\u042F\u0420 \u041D\u0415\u0421\u041A\u041E\u041B\u042C\u041A\u041E\u0420 \u0420\u0410\u0417!!!!!!!!! Fly runtime*/\n\n let promise;\n if (quickviewService.dialogIsExist(modalId) !== true) {\n quickviewService.needOpenDialog(modalId);\n promise = import(/* webpackChunkName: \"productQuickview\" */\n /* webpackMode: \"lazy\" */\n '../../../product/productQuickview.module.js').then(module => {\n $ocLazyLoad.inject(module.default);\n }).then(() => {\n ctrl.cartAddTriggerName = 'quckview_' + Date.now();\n if (cartAddType !== cartConfig.cartAddType.WithSpinbox) {\n cartService.addCallback(cartConfig.callbackNames.add, () => ctrl.hideModal(modalId), ctrl.cartAddTriggerName);\n }\n });\n } else {\n promise = $q.resolve();\n }\n return promise.then(() => {\n if (quickviewService.checkDialogOpenById(modalId) !== true) {\n quickviewService.dialogOpen(ctrl, productId, colorId, typeView, modalClass, landingId, hideShipping, showLeadButton, blockId, showVideo, modalId, openFromHash, sizeId, onOpenModalCallback, spyAddress, descriptionMode, cartAddType);\n }\n });\n };\n ctrl.hideModal = function (modalId) {\n quickviewService.dialogClose(modalId);\n cartService.removeCallback(cartConfig.callbackNames.add, ctrl.cartAddTriggerName);\n };\n ctrl.setSiblings = function (element) {\n var items, sibling, id, modalId;\n ctrl.siblings = [];\n ctrl.modalIds = {};\n items = domService.closest(element, '.js-products-view-block').parentNode.children;\n for (var i = 0, len = items.length - 1; i <= len; i++) {\n sibling = items[i].querySelector('.js-products-view-item');\n if (sibling != null) {\n id = parseInt(sibling.getAttribute('data-product-id'));\n modalId = sibling.getAttribute('data-modal-id') || sibling.querySelector('[data-quickview-trigger]')?.dataset.modalId;\n if (angular.isNumber(id)) {\n ctrl.siblings.push(id);\n }\n if (modalId != null) {\n ctrl.modalIds[id] = modalId;\n }\n }\n }\n };\n ctrl.onChangeSizeAndColor = function (data) {\n if (ctrl.isSpyAddress && data != null) {\n var hash = $location.hash();\n var urlParams = hash.split('?');\n var originalHash = urlParams.shift();\n var urlParamsFromHash = urlHelper.getUrlParamsAsObject(urlParams.join('&'));\n if (data.ColorId != null) {\n colorsAndSize.colorId = data.ColorId;\n }\n if (data.SizeId != null) {\n colorsAndSize.sizeId = data.SizeId;\n }\n $location.hash((originalHash || ctrl.modalId) + '?' + urlHelper.paramsToString(Object.assign({}, colorsAndSize, urlParamsFromHash)));\n }\n };\n ctrl.onOpenModal = function () {\n if (ctrl.productCtrl != null) {\n ctrl.onChangeSizeAndColor(ctrl.productCtrl.colorSelected);\n ctrl.onChangeSizeAndColor(ctrl.productCtrl.sizeSelected);\n }\n };\n ctrl.addProductCtrl = function (productCtrl) {\n ctrl.productCtrl = productCtrl;\n };\n}\nQuickviewCtrl.$inject = [\"quickviewService\", \"cartService\", \"cartConfig\", \"domService\", \"$location\", \"urlHelper\", \"$q\", \"$ocLazyLoad\"];\nexport default QuickviewCtrl;", "function quickviewTriggerDirective($location, urlHelper, $window, modalService, $parse) {\n return {\n require: ['quickviewTrigger', '^productViewItem'],\n restrict: 'A',\n scope: true,\n controller: 'QuickviewCtrl',\n controllerAs: 'quickview',\n bindToController: true,\n link: function (scope, element, attrs, ctrls) {\n var hash = $location.hash();\n var quickviewCtrl = ctrls[0],\n productViewItemCtrl = ctrls[1];\n if (hash != null) {\n var splitedHash = hash.split('?');\n hash = splitedHash != null ? splitedHash[0] : hash;\n }\n var colorId, sizeId;\n //var originalHash = splitedHash[0];\n if (splitedHash != null && splitedHash.length > 1) {\n var addParams = urlHelper.getUrlParamsAsObject(splitedHash[1]);\n colorId = addParams.colorId;\n sizeId = addParams.sizeId;\n }\n quickviewCtrl.modalId = attrs.modalId != null ? attrs.modalId : 'modalQuickView';\n quickviewCtrl.isSpyAddress = attrs.spyAddress === 'true';\n const showModal = () => {\n if (attrs.modalId != null && attrs.categoryId != null) {\n quickviewCtrl.modalId = attrs.modalId + '?categoryId=' + attrs.categoryId;\n }\n if (quickviewCtrl.siblings == null) {\n quickviewCtrl.setSiblings(element[0]);\n }\n quickviewCtrl.showModal(productViewItemCtrl.productId != null && isNaN(productViewItemCtrl.productId) === false ? productViewItemCtrl.productId : $parse(attrs.productId)(scope), colorId || productViewItemCtrl.getSelectedColorId(), attrs.quickviewTypeView, element[0].getAttribute('data-modal-class'), attrs.landingId, attrs.hideShipping, attrs.showLeadButton, attrs.blockId, attrs.showVideo != null ? attrs.showVideo : null, quickviewCtrl.modalId, quickviewCtrl.openFromHash, sizeId, quickviewCtrl.onOpenModal, quickviewCtrl.isSpyAddress, attrs.descriptionMode, attrs.cartAddType);\n };\n if (hash === attrs.modalId) {\n quickviewCtrl.openFromHash = true;\n showModal();\n //scope.$digest();\n }\n element[0].addEventListener('click', function (event) {\n event.preventDefault();\n event.stopPropagation();\n showModal();\n scope.$apply();\n });\n }\n };\n}\nquickviewTriggerDirective.$inject = [\"$location\", \"urlHelper\", \"$window\", \"modalService\", \"$parse\"];\nexport { quickviewTriggerDirective };", "import quckviewModalTemplate from '../templates/quckviewModal.html';\n\n/* @ngInject */\nfunction quickviewService(modalService, $location, $timeout, urlHelper) {\n var service = this,\n needOpenDialogId,\n dialogIdOpen;\n service.dialogRender = function (parentScope) {\n modalService.renderModal(parentScope.modalId || 'modalQuickView', null, `
    `, null, {\n isOpen: false,\n modalClass: 'modal-quickview' + ' ' + (parentScope.modalClass || ''),\n backgroundEnable: true,\n modalOverlayClass: 'modal-quickview-wrap',\n spyAddress: parentScope.spyAddress,\n anchor: parentScope.modalId || 'modalQuickView',\n callbackOpen: parentScope.spyAddress ? 'quickview.onOpenModalCallback()' : '',\n callbackClose: 'quickview.onModalClose()',\n destroyOnClose: true\n }, {\n quickview: parentScope\n });\n modalService.getModal(parentScope.modalId || 'modalQuickView').then(function (modal) {\n modal.modalScope.open();\n });\n };\n service.getUrl = function (productId, colorId, typeView, landingId, hideShipping, showLeadButton, blockId, showVideo, sizeId, descriptionMode, cartAddType) {\n return 'product/productquickview' + '?productId=' + productId + (colorId != null ? '&color=' + colorId : '') + (sizeId != null ? '&size=' + sizeId : '') + (typeView != null ? '&from=' + typeView : '') + (landingId != null ? '&landingId=' + landingId : '') + (hideShipping != null ? '&hideShipping=' + hideShipping : '') + (showLeadButton != null ? '&showLeadButton=' + showLeadButton : '') + (blockId != null ? '&blockId=' + blockId : '') + (showVideo != null ? '&showVideo=' + showVideo : '') + (descriptionMode != null ? '&descriptionMode=' + descriptionMode : '') + (cartAddType != null ? '&cartAddType=' + cartAddType : '') + '&rnd=' + Math.random();\n };\n service.dialogOpen = function (itemData, productId, colorId, typeView, modalClass, landingId, hideShipping, showLeadButton, blockId, showVideo, modalId, openFromHash, sizeId, onOpenModalCallback, spyAddress, descriptionMode, cartAddType) {\n dialogIdOpen = modalId;\n const data = {};\n data.url = service.getUrl(productId, colorId, typeView, landingId, hideShipping, showLeadButton, blockId, showVideo, sizeId, descriptionMode, cartAddType);\n data.itemData = itemData;\n data.productId = productId;\n data.next = service.next;\n data.prev = service.prev;\n data.modalClass = modalClass;\n data.typeView = typeView;\n data.landingId = landingId;\n data.hideShipping = hideShipping;\n data.showLeadButton = showLeadButton;\n data.blockId = blockId;\n data.showVideo = showVideo;\n data.modalId = modalId;\n data.onOpenModalCallback = onOpenModalCallback;\n data.spyAddress = spyAddress;\n data.descriptionMode = descriptionMode;\n data.onModalClose = () => {\n data.url = null;\n modalService.destroy('modalProductRotate');\n $location.search({\n color: undefined,\n size: undefined\n });\n //remove hash\n history.pushState(null, document.title, location.pathname + location.search);\n dialogIdOpen = null;\n };\n data.cartAddType = cartAddType;\n var hash = $location.hash();\n var splitedHash = hash.split('?');\n var originalHash = splitedHash[0];\n if (!modalService.hasModal(modalId)) {\n service.dialogRender(data);\n } else {\n modalService.open(modalId);\n }\n if (modalId != null) {\n $timeout(() => $location.hash(modalId), 100);\n }\n service.removeNeedOpenDialog();\n };\n service.dialogClose = function (modalQuickViewId) {\n modalService.close(modalQuickViewId || 'modalQuickView');\n dialogIdOpen = null;\n };\n service.goTo = function (quickview, index) {\n if (quickview.itemData.siblings[index] != null) {\n quickview.productId = quickview.itemData.siblings[index];\n if (quickview.itemData.modalIds[quickview.productId] != null) {\n $location.hash(quickview.itemData.modalIds[quickview.productId]);\n }\n $location.search({\n color: undefined,\n size: undefined\n });\n quickview.url = service.getUrl(quickview.productId, null, quickview.typeView, quickview.landingId, quickview.hideShipping, quickview.showLeadButton, quickview.blockId, quickview.showVideo, null, quickview.descriptionMode, quickview.cartAddType);\n }\n };\n service.prev = function (quickview) {\n modalService.destroy('modalProductRotate');\n service.goTo(quickview, quickview.itemData.siblings.indexOf(quickview.productId) - 1);\n };\n service.next = function (quickview) {\n modalService.destroy('modalProductRotate');\n service.goTo(quickview, quickview.itemData.siblings.indexOf(quickview.productId) + 1);\n };\n service.dialogIsExist = function (modalQuickViewId) {\n return modalService.hasModal(modalQuickViewId) || needOpenDialogId != null;\n };\n service.checkDialogOpenById = function (modalQuickViewId) {\n return dialogIdOpen === modalQuickViewId;\n };\n service.needOpenDialog = function (modalQuickViewId) {\n needOpenDialogId = modalQuickViewId;\n };\n service.removeNeedOpenDialog = function () {\n needOpenDialogId = null;\n };\n}\nquickviewService.$inject = [\"modalService\", \"$location\", \"$timeout\", \"urlHelper\"];\nexport default quickviewService;", "\uFEFFimport './styles/price-amount-list.scss';\n\nimport PriceAmountListCtrl from './controllers/priceAmountListController.js';\nimport { priceAmountListDirective } from './directives/priceAmountListDirectives.js';\n\nconst moduleName = 'priceAmountList';\n\nangular.module(moduleName, []).controller('PriceAmountListCtrl', PriceAmountListCtrl).directive('priceAmountList', priceAmountListDirective);\n\nexport default moduleName;\n", "function PriceAmountListCtrl($http, $q) {\n let ctrl = this;\n ctrl.$postLink = function () {\n ctrl.getItems(ctrl.productId, ctrl.startOfferId);\n ctrl.initFn({\n priceAmountList: ctrl\n });\n };\n ctrl.getItems = function (productId, offerId) {\n let defer = $q.defer();\n if (productId == null || offerId == null) {\n defer.resolve();\n return defer.promise;\n }\n $http.get('productExt/getPriceAmountList', {\n params: {\n productId: productId,\n offerId: offerId\n }\n }).then(function (response) {\n ctrl.items = response.data != null ? response.data.obj : null;\n defer.resolve(ctrl.items);\n });\n return defer.promise;\n };\n ctrl.update = function () {\n return ctrl.getItems(ctrl.productId, ctrl.offerId).then(function (data) {\n return data;\n });\n };\n}\nPriceAmountListCtrl.$inject = [\"$http\", \"$q\"];\nexport default PriceAmountListCtrl;", "import priceAmountListTemplate from '../templates/priceAmountList.html';\n/* @ngInject */\nfunction priceAmountListDirective() {\n return {\n restrict: 'A',\n scope: {\n productId: '=',\n offerId: '=',\n startOfferId: '=',\n initFn: '&'\n },\n controller: 'PriceAmountListCtrl',\n controllerAs: 'priceAmountList',\n bindToController: true,\n replace: true,\n templateUrl: priceAmountListTemplate\n };\n}\nexport { priceAmountListDirective };", "\uFEFFimport ProductsCarouselCtrl from './controllers/productsCarouselController.js';\nimport { productsCarouselDirective } from './directives/productsCarouselDirectives.js';\nimport productsCarouselService from './services/productsCarouselService.js';\n\nconst moduleName = 'productsCarousel';\n\nangular\n .module(moduleName, [])\n .directive('productsCarousel', productsCarouselDirective)\n .controller('ProductsCarouselCtrl', ProductsCarouselCtrl)\n .service('productsCarouselService', productsCarouselService);\n\nexport default moduleName;\n", "function ProductsCarouselCtrl($scope, $compile, $element, productsCarouselService) {\n var ctrl = this;\n ctrl.$onInit = function () {\n ctrl.update();\n };\n ctrl.generate = function (ids, title, type, visibleItems, carouselResponsive) {\n productsCarouselService.getData(ids, title, type, visibleItems, carouselResponsive).then(function (result) {\n $element.empty();\n $element.append(result);\n $compile($element.contents())($scope);\n });\n };\n ctrl.update = function () {\n ctrl.generate(ctrl.ids, ctrl.title, ctrl.type, ctrl.visibleItems, ctrl.carouselResponsive);\n };\n}\nProductsCarouselCtrl.$inject = [\"$scope\", \"$compile\", \"$element\", \"productsCarouselService\"];\nexport default ProductsCarouselCtrl;", "\uFEFFfunction productsCarouselDirective() {\n return {\n restrict: 'A',\n scope: {\n ids: '@',\n title: '@',\n type: '@',\n visibleItems: '@',\n carouselResponsive: ' 0 ? $parse(attrs.offerId)(scope) : null;\n\n //productViewItemCtrl.getOffersProduct(productViewItemCtrl.productId);\n\n productViewService.addCallback('setView', function (viewMode) {\n productViewItemCtrl.viewName = viewMode.viewName;\n setTimeout(function () {\n var colorsViewerCarousel = productViewItemCtrl.getControl('colorsViewerCarousel');\n if (colorsViewerCarousel != null) {\n colorsViewerCarousel.update();\n }\n scope.$digest();\n }, 50);\n });\n element[0].addEventListener('mouseenter', function () {\n if (timerHover != null) {\n clearTimeout(timerHover);\n }\n timerHover = setTimeout(async function () {\n await productViewItemCtrl.enter();\n productViewItemCtrl.isLoad = true;\n scope.$digest();\n }, 100);\n });\n element[0].addEventListener('mouseleave', function () {\n clearTimeout(timerHover);\n productViewItemCtrl.leave();\n scope.$digest();\n });\n element[0].addEventListener('touchstart', async function () {\n //await productViewItemCtrl.enter();\n productViewItemCtrl.isLoad = true;\n scope.$digest();\n }, {\n passive: true\n });\n\n //windowService.addCallback('touchstart', function (eventObj) {\n // var isClickedMe = domService.closest(eventObj.event.target, element[0]) != null;\n\n // if (isClickedMe === false) {\n // productViewItemCtrl.leave();\n\n // scope.$digest();\n // }\n //});\n }\n };\n}\nproductViewItemDirective.$inject = [\"productViewService\", \"domService\", \"windowService\", \"$parse\"];\nfunction productViewCarouselPhotosDirective() {\n return {\n require: ['^productViewCarouselPhotos', '^productViewItem'],\n restrict: 'A',\n scope: {\n photoHeight: '@',\n photoWidth: '@',\n changePhoto: '&'\n },\n replace: true,\n templateUrl: photosTemplate,\n controller: 'ProductViewCarouselPhotosCtrl',\n controllerAs: 'photosCarousel',\n bindToController: true,\n link: function (scope, element, attrs, ctrl) {\n var carouselPhotosCtrl = ctrl[0],\n productViewItemCtrl = ctrl[1];\n carouselPhotosCtrl.parentScope = productViewItemCtrl;\n productViewItemCtrl.addControl('photosCarousel', carouselPhotosCtrl);\n }\n };\n}\n\n/* @ngInject */\nfunction productViewChangeModeDirective(productViewService, viewList) {\n return {\n restrict: 'A',\n scope: true,\n controller: 'ProductViewChangeModeCtrl',\n controllerAs: 'changeMode',\n bindToController: true,\n link: function (scope, element, attrs, ctrl) {\n ctrl.name = attrs.name;\n ctrl.currentViewList = viewList[attrs.viewListName || 'desktop'];\n ctrl.isMobile = attrs.isMobile === 'true';\n ctrl.isReadyViewMode = false;\n ctrl.defaultViewMode = attrs.defaultViewMode;\n if (ctrl.isMobile === true) {\n ctrl.current = productViewService.getViewFromCookie('mobile_viewmode', ctrl.currentViewList, ctrl.defaultViewMode);\n } else {\n ctrl.current = attrs.viewMode;\n }\n ctrl.isReadyViewMode = true;\n }\n };\n}\nproductViewChangeModeDirective.$inject = [\"productViewService\", \"viewList\"];\nfunction productViewModeDirective() {\n return {\n restrict: 'A',\n scope: true,\n require: {\n productViewMode: 'productViewMode'\n },\n controller: 'ProductViewModeCtrl',\n controllerAs: 'productViewMode',\n bindToController: true\n };\n}\nfunction productViewImageListDirective($q) {\n return {\n restrict: 'A',\n scope: true,\n require: {\n productViewMode: '?^productViewMode',\n productViewImageList: 'productViewImageList',\n productViewItem: '^^productViewItem'\n },\n controller: 'ProductViewImageListCtrl',\n controllerAs: 'productViewImageList',\n bindToController: true,\n link: function (scope, element, attrs, ctrls) {\n var productViewImageList = ctrls.productViewImageList,\n timerHover;\n element[0].addEventListener('mouseenter', function () {\n if (timerHover != null) {\n clearTimeout(timerHover);\n }\n timerHover = setTimeout(function () {\n $q.all(productViewImageList.insertHtml(), productViewImageList.getPhotos());\n }, 100);\n });\n element[0].addEventListener('mouseleave', function () {\n clearTimeout(timerHover);\n });\n element[0].addEventListener('touchstart', function () {\n $q.all(productViewImageList.insertHtml(), productViewImageList.getPhotos());\n }, {\n passive: true\n });\n }\n };\n}\nproductViewImageListDirective.$inject = [\"$q\"];\nfunction productViewImageDirective(productViewService) {\n return {\n restrict: 'A',\n scope: true,\n require: {\n productViewMode: '?^^productViewMode',\n productViewImageList: '?^productViewImageList',\n productViewImage: 'productViewImage'\n },\n // require: ['?^^productViewMode',\n // '^^productViewImageList',\n // 'productViewImage'],\n controller: 'ProductViewImageCtrl',\n controllerAs: 'productViewImage',\n bindToController: true\n };\n}\nproductViewImageDirective.$inject = [\"productViewService\"];\nfunction productViewScrollPhotosDirective() {\n return {\n restrict: 'A',\n scope: true,\n require: {\n productViewItem: '^productViewItem'\n },\n controller: ['$element', function ($element) {\n const ctrl = this;\n ctrl.$onInit = function () {\n ctrl.productViewItem.addControl('productViewScrollPhotos', ctrl);\n };\n ctrl.scrollToStart = function () {\n $element[0].scrollTo(0, 0);\n };\n }],\n controllerAs: 'productViewScrollPhotos',\n bindToController: true\n };\n}\nexport { productViewItemDirective, productViewCarouselPhotosDirective, productViewChangeModeDirective, productViewModeDirective, productViewScrollPhotosDirective, productViewImageListDirective, productViewImageDirective };", "\uFEFFfunction ProductViewCarouselPhotosCtrl() {\n var ctrl = this;\n\n ctrl.carouselInit = function (carousel) {\n ctrl.carousel = carousel;\n };\n}\n\nexport default ProductViewCarouselPhotosCtrl;\n", "function ProductViewChangeModeCtrl(productViewService, viewList) {\n var ctrl = this;\n ctrl.setView = function (name, view, isMobile) {\n ctrl.current = view;\n productViewService.setView(name, view, ctrl.currentViewList, isMobile);\n };\n ctrl.toggle = function (name) {\n var index = ctrl.currentViewList.indexOf(ctrl.current);\n var nextViewIndex = index !== -1 ? index + 1 : 0;\n ctrl.setView(name, ctrl.currentViewList[nextViewIndex < ctrl.currentViewList.length ? nextViewIndex : 0], ctrl.currentViewList, ctrl.isMobile);\n };\n}\nProductViewChangeModeCtrl.$inject = [\"productViewService\", \"viewList\"];\nexport default ProductViewChangeModeCtrl;", "import { productViewItemControls } from '../productViewItem.controls.js';\n\n/*@ngInject*/\nfunction ProductViewItemCtrl($document, $q, $timeout, productViewService, $translate, $scope, $parse, urlHelper, $attrs) {\n var ctrl = this,\n controls = {},\n needCarouselUpdate = false,\n requestGetPhotosInPending = false,\n isPhotosStorageMutation = false,\n photosStorage;\n var isMobile = $document[0].documentElement.classList.contains('mobile-version');\n const styles = new Map();\n ctrl.$onInit = function () {\n ctrl.photosVisible = false;\n ctrl.photos = [];\n ctrl.picture = {};\n ctrl.promisesGetPhotos = [];\n ctrl.colorSelected = null;\n ctrl.productId = $parse($attrs.productId)($scope);\n ctrl.offer = $parse($attrs.offer)($scope);\n };\n ctrl.getOffersProduct = function (productId) {\n return productViewService.getOfferId(productId).then(function (result) {\n if (result != null) {\n return result.Offers;\n }\n });\n };\n ctrl.getPhotos = function (productId) {\n var defer = $q.defer(),\n promise;\n if (requestGetPhotosInPending === false && (photosStorage == null || needCarouselUpdate === true)) {\n requestGetPhotosInPending = true;\n promise = productViewService.getPhotos(ctrl.productId || productId).then(function (photos) {\n isPhotosStorageMutation = true;\n for (var i = 0, len = ctrl.promisesGetPhotos.length; i < len; i++) {\n ctrl.promisesGetPhotos[i].resolve(photos);\n }\n ctrl.promisesGetPhotos.length = 0;\n requestGetPhotosInPending = false;\n return photosStorage = photos;\n });\n } else if (requestGetPhotosInPending === true) {\n promise = defer.promise;\n ctrl.promisesGetPhotos.push(defer);\n } else {\n promise = defer.promise;\n defer.resolve(photosStorage);\n }\n ctrl.gotPhotos = true;\n return promise;\n };\n ctrl.numberals = function (num) {\n if (num <= 0) return ctrl.textNumberals = num + ' ' + $translate.instant('Js.ProductView.Photos0');\n num = num % 100;\n var nums = num % 10;\n if (num > 10 && num < 20) return ctrl.textNumberals = num + ' ' + $translate.instant('Js.ProductView.Photos5');\n if (nums > 1 && nums < 5) return ctrl.textNumberals = num + ' ' + $translate.instant('Js.ProductView.Photos2');\n return nums === 1 ? ctrl.textNumberals = num + ' ' + $translate.instant('Js.ProductView.Photos1') : ctrl.textNumberals = num + ' ' + $translate.instant('Js.ProductView.Photos5');\n };\n ctrl.fill = function (photos) {\n if (ctrl.getControl('colorsViewer') != null) {\n ctrl.photos = ctrl.filterPhotos(photosStorage == null && isPhotosStorageMutation === false ? ctrl.getPhotos() : photos, ctrl.getControl('colorsViewer').colorSelected.ColorId, ctrl.onlyPhotoWithColor);\n } else {\n ctrl.photos = photos;\n }\n if (ctrl.photos.length === 0) {\n ctrl.photos.length = 0;\n ctrl.photos.push.apply(ctrl.photos, ctrl.getMainPhoto(photos));\n }\n if (ctrl.maxPhotoView != null) {\n ctrl.photos = ctrl.photos.slice(0, ctrl.maxPhotoView);\n }\n ctrl.numberals(ctrl.photos.length);\n return photos;\n };\n ctrl.process = function (productId) {\n return ctrl.getPhotos(productId).then(function (photos) {\n ctrl.fill(photos);\n $timeout(function () {\n ctrl.carouselInit = true;\n if (needCarouselUpdate === true && ctrl.getControl('photosCarousel') != null && ctrl.getControl('photosCarousel').carousel != null) {\n ctrl.getControl('photosCarousel').carousel.update();\n needCarouselUpdate = false;\n }\n }, 0);\n return photos;\n });\n };\n ctrl.clearPhotos = function () {\n photosStorage = null;\n needCarouselUpdate = true;\n };\n ctrl.enter = function () {\n if (ctrl.photosVisible === true) {\n return;\n }\n ctrl.photosVisible = true;\n return ctrl.process(ctrl.productId);\n };\n ctrl.leave = function () {\n ctrl.photosVisible = false;\n ctrl.carouselInit = false;\n };\n ctrl.changePhoto = function (photo) {\n ctrl.picture = photo;\n };\n ctrl.initColors = function (colorsViewer) {\n ctrl.addControl('colorsViewer', colorsViewer);\n if (colorsViewer.changeStartSelectedColor != null) {\n setTimeout(function () {\n colorsViewer.selectColorById(colorsViewer.changeStartSelectedColor);\n }, 500);\n }\n };\n ctrl.getSelectedColorId = function () {\n var colorsViewer = ctrl.getControl('colorsViewer'),\n colorId;\n if (colorsViewer != null && colorsViewer.colorSelected != null && colorsViewer.getDirtyState() === true) {\n colorId = colorsViewer.colorSelected.ColorId;\n }\n return colorId;\n };\n ctrl.scrollToStartImages = function () {\n let photosScrollContent = ctrl.getControl('productViewScrollPhotos');\n if (photosScrollContent != null) {\n return $timeout(() => photosScrollContent.scrollToStart(), 100);\n } else {\n return $q.resolve();\n }\n };\n ctrl.initColorsCarousel = function (carousel) {\n ctrl.addControl('colorsViewerCarousel', carousel);\n };\n ctrl.changeColor = function (color) {\n ctrl.setStateLoading(true);\n ctrl.getOffersProduct(ctrl.productId).then(function (result) {\n ctrl.productOffers = result;\n if (ctrl.productOffers != null && ctrl.productOffers.length > 0) {\n ctrl.selectedProductOffer = ctrl.productOffers.filter(function (offer) {\n return offer.Color.ColorId === color.ColorId;\n });\n if (ctrl.selectedProductOffer != null && ctrl.selectedProductOffer.length > 0) {\n var o = null;\n for (var i = 0; i < ctrl.selectedProductOffer.length; i++) {\n if (ctrl.selectedProductOffer[i].Amount > 0) {\n o = ctrl.selectedProductOffer[i];\n break;\n }\n }\n ctrl.offer = o == null ? ctrl.selectedProductOffer[0] : o;\n }\n }\n var defaultPhoto;\n if (photosStorage == null && isPhotosStorageMutation === false) {\n ctrl.getPhotos().then(function (result) {\n ctrl.photos = ctrl.filterPhotos(result, color.ColorId, ctrl.getControl('colorsViewer') != null ? ctrl.onlyPhotoWithColor : false);\n defaultPhoto = ctrl.getMainPhoto(ctrl.photos);\n //if (ctrl.photos.length === 0) {\n // ctrl.photos = defaultPhoto;\n //}\n //if (ctrl.maxPhotoView != null) {\n // ctrl.photos = ctrl.photos.slice(0, ctrl.maxPhotoView);\n //}\n ctrl.setColor(defaultPhoto);\n });\n } else {\n defaultPhoto = ctrl.getMainPhoto(photosStorage != null && photosStorage.length !== 0 ? photosStorage : ctrl.photos);\n ctrl.photos = ctrl.filterPhotos(photosStorage, color.ColorId, ctrl.getControl('colorsViewer') != null ? ctrl.onlyPhotoWithColor : false);\n ctrl.setColor(defaultPhoto);\n }\n ctrl.getControl(productViewItemControls.productListCtrl)?.filterPhotos({\n colorId: color.ColorId,\n onlyColorPhoto: ctrl.getControl('colorsViewer') != null ? ctrl.onlyPhotoWithColor : false\n });\n if (ctrl.onChangeColor != null) {\n $parse(ctrl.onChangeColor)($scope);\n }\n if (ctrl.photos.length === 0) {\n ctrl.photos.length = 0;\n ctrl.photos.push.apply(ctrl.photos, defaultPhoto);\n //ctrl.photos = ctrl.photos.concat(defaultPhoto);\n }\n if (ctrl.maxPhotoView != null) {\n ctrl.photos = ctrl.photos.slice(0, ctrl.maxPhotoView);\n }\n return ctrl.scrollToStartImages();\n }).catch(function (error) {\n console.error(error);\n }).finally(() => ctrl.setStateLoading(false));\n };\n ctrl.setColor = function (defaultPhoto) {\n ctrl.picture = ctrl.photos.length === 0 && defaultPhoto != null ? defaultPhoto[0] : ctrl.photos[0];\n ctrl.numberals(ctrl.photos.length);\n var photosCarousel = ctrl.getControl('photosCarousel');\n if (photosCarousel != null && photosCarousel.carousel != null) {\n $timeout(function () {\n photosCarousel.carousel.options.indexActive = 0;\n photosCarousel.carousel.update();\n });\n }\n if (ctrl.photoViewer != null) {\n ctrl.photoViewer.reinit();\n }\n };\n ctrl.addControl = function (name, scope) {\n controls[name] = scope;\n };\n ctrl.getControl = function (name) {\n return controls[name];\n };\n ctrl.filterPhotos = function (photos, colorId, onlyColorPhoto) {\n return productViewService.filterPhotos(photos, colorId, onlyColorPhoto);\n };\n ctrl.getUrl = function (url) {\n var result = url,\n colorId = ctrl.getSelectedColorId();\n if (colorId != null) {\n result = urlHelper.updateQueryStringParameter(result, 'color', colorId);\n }\n return result;\n };\n ctrl.addPhotoViewer = function (photoViewer) {\n ctrl.photoViewer = photoViewer;\n };\n ctrl.getPictureByViewMode = function (photosItem, lazyLoadMode, sourceOnlyParameters, photoSize) {\n if (lazyLoadMode === 'Carousel' && ctrl.isCarouselImgVisible !== true || lazyLoadMode === 'Default' && ctrl.isImgVisible !== true) {\n return null;\n }\n const picture = sourceOnlyParameters !== true && ctrl.picture != null && Object.keys(ctrl.picture).length > 0 ? ctrl.picture : photosItem != null ? Array.isArray(photosItem) ? photosItem[0] : photosItem : null;\n let size;\n if (picture == null) {\n return null;\n }\n const photoSizeProp = photoSize != null ? 'Path' + photoSize : null;\n if (ctrl.productViewMode != null) {\n if (['single'].includes(ctrl.productViewMode.viewName)) {\n size = 'PathBig';\n } else {\n size = photoSizeProp ?? (ctrl.productViewMode.isMobile || lazyLoadMode === 'middle' ? 'PathMiddle' : 'PathSmall');\n }\n } else {\n size = photoSizeProp ?? (isMobile || lazyLoadMode === 'middle' ? 'PathMiddle' : 'PathSmall');\n }\n return ctrl.getPictureBySize(size, picture);\n };\n ctrl.getStylePropByViewMode = function (prop, defaultValue, {\n viewName,\n value\n }) {\n const currentViewName = ctrl.productViewMode?.viewName || 'tile';\n let stylesItem = styles.get(prop) || {};\n stylesItem[prop] = viewName == currentViewName ? value : defaultValue;\n styles.set(prop, stylesItem);\n return stylesItem;\n };\n ctrl.lazyLoadImgInCarousel = function () {\n ctrl.isCarouselImgVisible = true;\n };\n ctrl.lazyLoadImg = function () {\n ctrl.isImgVisible = true;\n };\n ctrl.getPictureBySize = function (size, photos) {\n return photos[size];\n };\n ctrl.getMainPhoto = function (photos) {\n return photos.filter(function (photo) {\n return photo.Main === true;\n });\n };\n ctrl.setStateLoading = function (isLoading) {\n ctrl.isLoading = isLoading;\n };\n ctrl.getStateLoading = function () {\n return ctrl.isLoading;\n };\n}\nProductViewItemCtrl.$inject = [\"$document\", \"$q\", \"$timeout\", \"productViewService\", \"$translate\", \"$scope\", \"$parse\", \"urlHelper\", \"$attrs\"];\nexport default ProductViewItemCtrl;", "\uFEFFexport const productViewItemControls = {\n productListCtrl: 'productListCtrl',\n colorsViewer: 'colorsViewer',\n photosCarousel: 'photosCarousel',\n productViewScrollPhotos: 'productViewScrollPhotos',\n colorsViewerCarousel: 'colorsViewerCarousel',\n};\n", "function ProductViewModeCtrl($attrs, $element, productViewService, viewList, viewPrefix, $parse, $scope) {\n const ctrl = this;\n ctrl.$onInit = function () {\n ctrl.isMobile = $attrs.isMobile === 'true';\n ctrl.currentViewList = viewList[$attrs.viewListName || 'desktop'];\n ctrl.currentViewPrefix = viewPrefix[$attrs.viewListName || 'desktop'];\n ctrl.defaultViewMode = $attrs.defaultViewMode;\n ctrl.photoHeightByViewMode = $attrs.photoHeightByViewMode != null ? $parse($attrs.photoHeightByViewMode)($scope) : null;\n ctrl.photoHeightByViewModeDefault = $attrs.photoHeightByViewModeDefault != null ? $parse($attrs.photoHeightByViewModeDefault)($scope) : null;\n if (ctrl.isMobile === true) {\n ctrl.viewName = productViewService.getViewFromCookie('mobile_viewmode', ctrl.currentViewList, ctrl.defaultViewMode);\n $element[0].classList.add('products-view-' + ctrl.currentViewPrefix + ctrl.viewName);\n } else {\n ctrl.viewName = $attrs.current;\n }\n setPhotoSizeByViewMode();\n productViewService.addCallback('setView', onChangeMode);\n function onChangeMode(view) {\n ctrl.viewName = view.viewName;\n view.viewList.forEach(function (item) {\n $element[0].classList.remove('products-view-' + ctrl.currentViewPrefix + item);\n });\n requestAnimationFrame(() => {\n $element[0].classList.add('products-view-' + ctrl.currentViewPrefix + view.viewName);\n setPhotoSizeByViewMode();\n });\n }\n ctrl.getCurrentBlockPhotoHeight = () => {\n return ctrl.photoHeightByViewMode != null && ctrl.photoHeightByViewMode.viewName === ctrl.viewName ? ctrl.photoHeightByViewMode.value : ctrl.photoHeightByViewModeDefault;\n };\n function setPhotoSizeByViewMode() {\n if (ctrl.photoHeightByViewMode != null && ctrl.photoHeightByViewMode.viewName === ctrl.viewName) {\n $element[0].style.setProperty('--product-view-photo-size', ctrl.photoHeightByViewMode.value);\n return;\n }\n if (ctrl.photoHeightByViewModeDefault != null) {\n $element[0].style.setProperty('--product-view-photo-size', ctrl.photoHeightByViewModeDefault);\n return;\n }\n }\n };\n}\nProductViewModeCtrl.$inject = [\"$attrs\", \"$element\", \"productViewService\", \"viewList\", \"viewPrefix\", \"$parse\", \"$scope\"];\nexport default ProductViewModeCtrl;", "import { productViewItemControls } from '../productViewItem.controls.js';\nexport const productViewImageListMapperRequest = ({\n productId,\n viewMode,\n blockProductPhotoHeight,\n productImageType,\n photoWidth,\n photoHeight,\n isProductPhotoLazy,\n limitPhotoCount,\n colorInitialId,\n renderedPhotoId\n}) => {\n return {\n productId,\n productViewMode: viewMode,\n blockProductPhotoHeight,\n productImageType,\n photoWidth,\n photoHeight,\n isProductPhotoLazy,\n limitPhotoCount: limitPhotoCount - 1,\n colorId: colorInitialId,\n RenderedPhotoId: renderedPhotoId\n };\n};\n\n/* @ngInject */\nfunction ProductViewImageListCtrl($element, $attrs, $parse, $scope, $http, $q, productViewService, $compile) {\n const ctrl = this;\n ctrl.$onInit = function () {\n ctrl.productId = $attrs.productId != null ? $parse($attrs.productId)($scope) : null;\n ctrl.viewMode = $attrs.viewMode != null ? $parse($attrs.viewMode)($scope) : null;\n ctrl.blockProductPhotoHeight = $attrs.blockProductPhotoHeight != null ? $parse($attrs.blockProductPhotoHeight)($scope) : null;\n ctrl.productImageType = $attrs.productImageType != null ? $parse($attrs.productImageType)($scope) : null;\n ctrl.photoWidth = $attrs.photoWidth != null ? $parse($attrs.photoWidth)($scope) : null;\n ctrl.photoHeight = $attrs.photoHeight != null ? $parse($attrs.photoHeight)($scope) : null;\n ctrl.isProductPhotoLazy = $attrs.isProductPhotoLazy != null ? $parse($attrs.isProductPhotoLazy)($scope) : null;\n ctrl.limitPhotoCount = $attrs.limitPhotoCount != null ? $parse($attrs.limitPhotoCount)($scope) : 5;\n ctrl.colorInitialId = $parse($attrs.colorInitialId)($scope);\n ctrl.renderedPhotoId = $parse($attrs.renderedPhotoId)($scope);\n ctrl.isLoadedHtml = false;\n ctrl.photosStorage = null;\n ctrl.currentPhotos = [];\n ctrl.imageCtrls = [];\n ctrl.initial = true;\n ctrl.productViewItem.addControl(productViewItemControls.productListCtrl, ctrl);\n ctrl.currentColorId = ctrl.colorInitialId;\n productViewService.addCallback('setView', function (viewObj) {\n ctrl.viewMode = viewObj.viewName;\n ctrl.filterPhotos({\n isVisible: ctrl.isVisible,\n colorId: ctrl.currentColorId\n });\n });\n };\n ctrl.addImageCtrl = function (ctrlChild) {\n if (ctrl.imageCtrls.includes(ctrlChild)) return;\n return ctrl.imageCtrls.push(ctrlChild);\n };\n ctrl.removeImageCtrl = function (id) {\n ctrl.imageCtrls.splice(id, 1);\n };\n ctrl.updatePhotos = function () {\n if (ctrl.currentPhotos.length === 0) return;\n ctrl.imageCtrls.forEach((imageCtrl, i) => {\n if (ctrl.checkAvailablePhoto(i)) {\n imageCtrl.changeSrc(ctrl.currentPhotos[i], ctrl.viewMode);\n } else {\n imageCtrl.hiddenImage();\n }\n });\n };\n ctrl.checkAvailablePhoto = function (index) {\n return index >= 0 && index < Math.min(ctrl.limitPhotoCount, ctrl.currentPhotos.length);\n };\n ctrl.getPhoto = function (photoIndex) {\n return ctrl.currentPhotos[photoIndex];\n };\n ctrl.getPhotos = function () {\n var defer = $q.defer();\n if (ctrl.photosStorage != null && ctrl.photosStorage.length) return defer.resolve(ctrl.photosStorage);\n return productViewService.getPhotos(ctrl.productId).then(function (photos) {\n ctrl.photosStorage = photos;\n return photos;\n });\n };\n ctrl.filterPhotos = function ({\n isVisible,\n colorId,\n onlyColorPhoto\n }) {\n ctrl.isVisible = typeof isVisible === 'undefined' ? ctrl.isVisible : isVisible;\n ctrl.currentColorId = colorId;\n if (ctrl.isVisible === false) return;\n if (ctrl.photosStorage) {\n ctrl.currentPhotos = productViewService.filterPhotos(ctrl.photosStorage, colorId, onlyColorPhoto).slice(0, ctrl.limitPhotoCount);\n ctrl.updatePhotos();\n } else {\n ctrl.getPhotos().then(photos => {\n ctrl.currentPhotos = productViewService.filterPhotos(photos, colorId, onlyColorPhoto).slice(0, ctrl.limitPhotoCount);\n ctrl.updatePhotos();\n });\n }\n };\n productViewService.addCallback('setView', () => {\n requestAnimationFrame(() => {\n $element[0].scrollLeft = 0;\n });\n });\n ctrl.getPhotoHtml = function (data) {\n if (data.productId == null) return;\n return $http.post('/mobile/product/ProductViewPhoto', data).then(function (response) {\n return response.data;\n });\n };\n ctrl.insertHtml = function (replaceInner = false) {\n var defer = $q.defer();\n if (ctrl.isLoadedHtml) return defer.promise;\n const data = {\n productId: ctrl.productId,\n productImageType: ctrl.productImageType,\n photoWidth: ctrl.photoWidth,\n photoHeight: ctrl.photoHeight,\n isProductPhotoLazy: ctrl.isProductPhotoLazy,\n limitPhotoCount: ctrl.limitPhotoCount,\n colorInitialId: ctrl.colorInitialId,\n renderedPhotoId: ctrl.renderedPhotoId\n };\n if (ctrl.productViewMode != null) {\n data.viewMode = ctrl.productViewMode.viewName;\n data.blockProductPhotoHeight = ctrl.productViewMode.getCurrentBlockPhotoHeight();\n } else {\n data.viewMode = ctrl.viewMode;\n data.blockProductPhotoHeight = ctrl.blockProductPhotoHeight;\n }\n data.blockProductPhotoHeight = parseInt(data.blockProductPhotoHeight);\n return ctrl.getPhotoHtml(productViewImageListMapperRequest(data)).then(html => {\n if (html == null) return;\n ctrl.isLoadedHtml = true;\n $element.find('.js-skeleton-photos').remove();\n $element.append(html);\n $compile($element.children('.mobile-product-view-item-image-inner').slice(1))($scope.$new());\n });\n };\n}\nProductViewImageListCtrl.$inject = [\"$element\", \"$attrs\", \"$parse\", \"$scope\", \"$http\", \"$q\", \"productViewService\", \"$compile\"];\nexport default ProductViewImageListCtrl;", "export const PRODUCT_VIEW_IMAGE_CONTAINER_CLASS = 'js-product-view-image-container';\n\n/* @ngInject */\nfunction ProductViewImageCtrl($element, $attrs, $parse, $scope, $document) {\n const ctrl = this;\n const isMobile = $document[0].documentElement.classList.contains('mobile-version');\n ctrl.$onInit = function () {\n ctrl.photoSize = $attrs.photoSize != null ? $parse($attrs.photoSize)($scope) : null;\n ctrl.startPhotoJson = $attrs.startPhotoJson != null ? $parse($attrs.startPhotoJson)($scope) : null;\n ctrl.containerImage = $element[0].closest(`.${PRODUCT_VIEW_IMAGE_CONTAINER_CLASS}`);\n ctrl.productViewImageList?.addImageCtrl(ctrl);\n };\n ctrl.getPictureBySize = (size, photos) => {\n return photos[size];\n };\n ctrl.viewModeToPhotoSizeMapper = (viewMode, photoSizeProp, isMobile) => {\n switch (viewMode) {\n case 'single':\n return 'PathBig';\n default:\n return photoSizeProp ?? (isMobile ? 'PathMiddle' : 'PathSmall');\n }\n };\n ctrl.getPhotoSrc = (photo, viewMode) => {\n const picture = photo ?? (Array.isArray(ctrl.startPhotoJson) ? ctrl.startPhotoJson[0] : ctrl.startPhotoJson);\n let size;\n if (picture == null) {\n return null;\n }\n const photoSizeProp = ctrl.photoSize != null ? 'Path' + ctrl.photoSize : null;\n size = ctrl.productViewMode != null ? ctrl.viewModeToPhotoSizeMapper(viewMode ?? ctrl.productViewMode.viewName, photoSizeProp, ctrl.productViewMode.isMobile) : ctrl.viewModeToPhotoSizeMapper(null, photoSizeProp, isMobile);\n return ctrl.getPictureBySize(size, picture);\n };\n ctrl.hiddenImage = () => {\n ctrl.containerImage.classList.add('product-view-image-container--hidden');\n };\n ctrl.changeSrc = (photo, viewObj) => {\n ctrl.containerImage.classList.remove('product-view-image-container--hidden');\n ctrl.containerImage.classList.add('product-view-image-container--block');\n const newSrc = ctrl.getPhotoSrc(photo, viewObj?.viewMode);\n if (newSrc === $element[0].src) return;\n $element[0].src = newSrc;\n };\n}\nProductViewImageCtrl.$inject = [\"$element\", \"$attrs\", \"$parse\", \"$scope\", \"$document\"];\nexport default ProductViewImageCtrl;", "\uFEFFimport popoverBootstrap from 'angular-ui-bootstrap/src/popover/index.js';\nimport '../../../vendors/ui-bootstrap-custom/styles/ui-popover.css';\n\nimport rangeSliderModule from '../../../vendors/rangeSlider/rangeSlider.module.js';\nimport popoverModule from '../../_common/popover/popover.module.js';\nimport './styles/catalogFilter.scss';\n\nimport catalogFilterService from './services/catalogFilterService.js';\nimport { catalogFilterDirective, catalogFilterSortDirective, catalogFilterSelectSortDirective } from './directives/catalogFilterDirectives.js';\nimport CatalogFilterCtrl from './controllers/catalogFilterController.js';\nimport CatalogFilterSortCtrl from './controllers/catalogFilterSortController.js';\n\nconst moduleName = 'catalogFilter';\n\nangular\n .module(moduleName, [rangeSliderModule, popoverBootstrap, popoverModule])\n .constant('catalogFilterAdvPopoverOptionsDefault', {\n position: 'left',\n isFixed: false,\n showOnLoad: false,\n overlayEnabled: false,\n })\n .service('catalogFilterService', catalogFilterService)\n .controller('CatalogFilterCtrl', CatalogFilterCtrl)\n .controller('CatalogFilterSortCtrl', CatalogFilterSortCtrl)\n .directive('catalogFilter', catalogFilterDirective)\n .directive('catalogFilterSort', catalogFilterSortDirective)\n .directive('catalogFilterSelectSort', catalogFilterSelectSortDirective);\n\nexport default moduleName;\n", "\uFEFFimport './styles/angular.rangeSlider.css';\n\nimport './angular.rangeSlider.js';\n\nexport default 'ui-rangeSlider';", "import rangeSliderTemplate from \"./templates/rangeSlider.html\";\n/*\n * Angular RangeSlider Directive\n *\n * Version: 0.0.13\n *\n * Author: Daniel Crisp, danielcrisp.com\n *\n * The rangeSlider has been styled to match the default styling\n * of form elements styled using Twitter's Bootstrap\n *\n * Originally forked from https://github.com/leongersen/noUiSlider\n *\n\n This code is released under the MIT Licence - http://opensource.org/licenses/MIT\n\n Copyright (c) 2013 Daniel Crisp\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n THE SOFTWARE.\n\n*/\n\n(function() {\n 'use strict';\n\n // check if we need to support legacy angular\n var legacySupport = (angular.version.major === 1 && angular.version.minor === 0);\n\n /**\n * RangeSlider, allows user to define a range of values using a slider\n * Touch friendly.\n * @directive\n */\n angular.module('ui-rangeSlider', [])\n .directive('rangeSlider', ['$document', '$filter', '$log', '$parse', function($document, $filter, $log, $parse) {\n\n // test for mouse, pointer or touch\n var eventNamespace = '.rangeSlider',\n\n defaults = {\n disabled: false,\n orientation: 'horizontal',\n step: 0,\n decimalPlaces: 0,\n showValues: true,\n preventEqualMinMax: false,\n attachHandleValues: false,\n showInputs: true,\n caption: null\n },\n\n // Determine the events to bind. IE11 implements pointerEvents without\n // a prefix, which breaks compatibility with the IE10 implementation.\n /** @const */\n actions = window.navigator.pointerEnabled ? {\n start: 'pointerdown',\n move: 'pointermove',\n end: 'pointerup',\n over: 'pointerdown',\n out: 'mouseout'\n } : window.navigator.msPointerEnabled ? {\n start: 'MSPointerDown',\n move: 'MSPointerMove',\n end: 'MSPointerUp',\n over: 'MSPointerDown',\n out: 'mouseout'\n } : {\n start: 'mousedown touchstart',\n move: 'mousemove touchmove',\n end: 'mouseup touchend',\n over: 'mouseover touchstart',\n out: 'mouseout'\n },\n\n onEvent = actions.start + eventNamespace,\n moveEvent = actions.move + eventNamespace,\n offEvent = actions.end + eventNamespace,\n overEvent = actions.over + eventNamespace,\n outEvent = actions.out + eventNamespace,\n\n // get standarised clientX and clientY\n client = function(f) {\n try {\n return [(f.clientX || f.originalEvent.clientX || f.originalEvent.touches[0].clientX), (f.clientY || f.originalEvent.clientY || f.originalEvent.touches[0].clientY)];\n } catch (e) {\n return ['x', 'y'];\n }\n },\n\n restrict = function(value) {\n\n // normalize so it can't move out of bounds\n return (value < 0 ? 0 : (value > 100 ? 100 : value));\n\n },\n\n isNumber = function(n) {\n // console.log(n);\n return !isNaN(parseFloat(n)) && isFinite(n);\n },\n\n scopeOptions = {\n disabled: '=?',\n min: '=',\n max: '=',\n modelMin: '=?',\n modelMax: '=?',\n onHandleDown: '&', // calls optional function when handle is grabbed\n onHandleUp: '&', // calls optional function when handle is released\n onHandleMoveDown: '&', // calls optional function when handle is grabbed\n onHandleMoveUp: '&', // calls optional function when handle is released\n orientation: '@', // options: horizontal | vertical | vertical left | vertical right\n step: '<',\n decimalPlaces: '<',\n filter: '@',\n filterOptions: '@',\n showValues: '@',\n showInputs: '@',\n pinHandle: '@',\n preventEqualMinMax: '@',\n attachHandleValues: '@',\n caption: '@'\n };\n\n if (legacySupport) {\n // make optional properties required\n scopeOptions.disabled = '=';\n scopeOptions.modelMin = '=';\n scopeOptions.modelMax = '=';\n }\n\n // if (EVENT < 4) {\n // // some sort of touch has been detected\n // angular.element('html').addClass('ngrs-touch');\n // } else {\n // angular.element('html').addClass('ngrs-no-touch');\n // }\n\n\n return {\n restrict: 'A',\n replace: true,\n templateUrl: rangeSliderTemplate,\n scope: scopeOptions,\n link: function(scope, element, attrs, controller) {\n\n /**\n * FIND ELEMENTS\n */\n\n var $slider = angular.element(element),\n handles = [element.find('.ngrs-handle-min'), element.find('.ngrs-handle-max')],\n values = [element.find('.ngrs-value-min'), element.find('.ngrs-value-max')],\n join = element.find('.ngrs-join'),\n pos = 'left',\n posOpp = 'right',\n orientation = 0,\n allowedRange = [0, 0],\n range = 0,\n down = false;\n\n // filtered\n scope.filteredModelMin = scope.modelMin;\n scope.filteredModelMax = scope.modelMax;\n\n /**\n * FALL BACK TO DEFAULTS FOR SOME ATTRIBUTES\n */\n\n attrs.$observe('disabled', function(val) {\n if (!angular.isDefined(val)) {\n scope.disabled = defaults.disabled;\n }\n\n scope.$watch('disabled', setDisabledStatus);\n });\n\n attrs.$observe('orientation', function(val) {\n if (!angular.isDefined(val)) {\n scope.orientation = defaults.orientation;\n }\n\n var classNames = scope.orientation.split(' '),\n useClass;\n\n for (var i = 0, l = classNames.length; i < l; i++) {\n classNames[i] = 'ngrs-' + classNames[i];\n }\n\n useClass = classNames.join(' ');\n\n // add class to element\n $slider.addClass(useClass);\n\n // update pos\n if (scope.orientation === 'vertical' || scope.orientation === 'vertical left' || scope.orientation === 'vertical right') {\n pos = 'top';\n posOpp = 'bottom';\n orientation = 1;\n }\n });\n\n //attrs.$observe('step', function(val) {\n // if (!angular.isDefined(val)) {\n // scope.step = defaults.step;\n // }\n //});\n\n //attrs.$observe('decimalPlaces', function(val) {\n // if (!angular.isDefined(val)) {\n // scope.decimalPlaces = defaults.decimalPlaces;\n // }\n //});\n\n attrs.$observe('showValues', function(val) {\n if (!angular.isDefined(val)) {\n scope.showValues = defaults.showValues;\n } else {\n if (val === 'false') {\n scope.showValues = false;\n } else {\n scope.showValues = true;\n }\n }\n });\n\n attrs.$observe('showInputs', function (val) {\n if (!angular.isDefined(val)) {\n scope.showInputs = defaults.showInputs;\n } else {\n if (val === 'false') {\n scope.showInputs = false;\n } else {\n scope.showInputs = true;\n }\n }\n });\n\n attrs.$observe('pinHandle', function(val) {\n if (!angular.isDefined(val)) {\n scope.pinHandle = null;\n } else {\n if (val === 'min' || val === 'max') {\n scope.pinHandle = val;\n } else {\n scope.pinHandle = null;\n }\n }\n\n scope.$watch('pinHandle', setPinHandle);\n });\n\n attrs.$observe('preventEqualMinMax', function(val) {\n if (!angular.isDefined(val)) {\n scope.preventEqualMinMax = defaults.preventEqualMinMax;\n } else {\n if (val === 'false') {\n scope.preventEqualMinMax = false;\n } else {\n scope.preventEqualMinMax = true;\n }\n }\n });\n\n attrs.$observe('attachHandleValues', function(val) {\n if (!angular.isDefined(val)) {\n scope.attachHandleValues = defaults.attachHandleValues;\n } else {\n if (val === 'true' || val === '') {\n // flag as true\n scope.attachHandleValues = true;\n // add class to runner\n element.find('.ngrs-value-runner').addClass('ngrs-attached-handles');\n } else {\n scope.attachHandleValues = false;\n }\n }\n });\n\n\n // listen for changes to values\n scope.$watch('min', setMinMax);\n scope.$watch('max', setMinMax);\n\n scope.$watch('modelMin', setModelMinMax);\n scope.$watch('modelMax', setModelMinMax);\n\n /**\n * HANDLE CHANGES\n */\n\n function setPinHandle(status) {\n if (status === \"min\") {\n angular.element(handles[0]).css('display', 'none');\n angular.element(handles[1]).css('display', 'block');\n } else if (status === \"max\") {\n angular.element(handles[0]).css('display', 'block');\n angular.element(handles[1]).css('display', 'none');\n } else {\n angular.element(handles[0]).css('display', 'block');\n angular.element(handles[1]).css('display', 'block');\n }\n }\n\n function setDisabledStatus(status) {\n if (status) {\n $slider.addClass('ngrs-disabled');\n } else {\n $slider.removeClass('ngrs-disabled');\n }\n }\n\n function setMinMax() {\n\n if (scope.min > scope.max) {\n throwError('min must be less than or equal to max');\n }\n\n // only do stuff when both values are ready\n if (angular.isDefined(scope.min) && angular.isDefined(scope.max)) {\n\n // make sure they are numbers\n if (!isNumber(scope.min)) {\n throwError('min must be a number');\n }\n\n if (!isNumber(scope.max)) {\n throwError('max must be a number');\n }\n\n range = scope.max - scope.min;\n allowedRange = [scope.min, scope.max];\n\n // update models too\n setModelMinMax();\n\n }\n }\n\n scope.blurMin = function() {\n // make sure they are numbers\n if (!isNumber(scope.modelMin)) { //|| scope.modelMin < scope.min\n //if (scope.pinHandle !== 'min') {\n // throwWarning('modelMin must be a number');\n //}\n scope.modelMin = scope.min;\n }\n }\n\n scope.blurMax = function () {\n if (!isNumber(scope.modelMax) || scope.modelMax > scope.max) {\n //if (scope.pinHandle !== 'max') {\n // throwWarning('modelMax must be a number');\n //}\n scope.modelMax = scope.max;\n }\n }\n\n function setModelMinMax() {\n\n //if (scope.modelMin > scope.modelMax && scope.modelMax != null) {\n // throwWarning('modelMin must be less than or equal to modelMax');\n // // reset values to correct\n // scope.modelMin = scope.modelMax;\n //}\n\n // only do stuff when both values are ready\n if (\n (angular.isDefined(scope.modelMin) || scope.pinHandle === 'min') &&\n (angular.isDefined(scope.modelMax) || scope.pinHandle === 'max')\n ) {\n\n // make sure they are numbers\n //if (!isNumber(scope.modelMin)) { //|| scope.modelMin < scope.min\n // if (scope.pinHandle !== 'min') {\n // throwWarning('modelMin must be a number');\n // }\n // scope.modelMin = scope.min;\n //}\n\n //if (scope.modelMax == null) {\n // return;\n //}\n\n //if (!isNumber(scope.modelMax) || scope.modelMax > scope.max) {\n // if (scope.pinHandle !== 'max') {\n // throwWarning('modelMax must be a number');\n // }\n // scope.modelMax = scope.max;\n //}\n\n var handle1pos = restrict(((scope.modelMin - scope.min) / range) * 100),\n handle2pos = restrict(((scope.modelMax - scope.min) / range) * 100),\n value1pos,\n value2pos;\n\n if (scope.attachHandleValues) {\n value1pos = handle1pos;\n value2pos = handle2pos;\n }\n\n // make sure the model values are within the allowed range\n //scope.modelMin = Math.max(scope.min, scope.modelMin);\n //scope.modelMax = Math.min(scope.max, scope.modelMax);\n\n if (scope.filter && scope.filterOptions) {\n scope.filteredModelMin = $filter(scope.filter)(scope.modelMin, scope.filterOptions);\n scope.filteredModelMax = $filter(scope.filter)(scope.modelMax, scope.filterOptions);\n } else if (scope.filter) {\n\n var filterTokens = scope.filter.split(':'),\n filterName = scope.filter.split(':')[0],\n filterOptions = filterTokens.slice().slice(1),\n modelMinOptions,\n modelMaxOptions;\n\n // properly parse string and number args\n filterOptions = filterOptions.map(function (arg) {\n if (isNumber(arg)) {\n return +arg;\n } else if ((arg[0] == \"\\\"\" && arg[arg.length-1] == \"\\\"\") || (arg[0] == \"\\'\" && arg[arg.length-1] == \"\\'\")) {\n return arg.slice(1, -1);\n }\n });\n\n modelMinOptions = filterOptions.slice();\n modelMaxOptions = filterOptions.slice();\n modelMinOptions.unshift(scope.modelMin);\n modelMaxOptions.unshift(scope.modelMax);\n\n scope.filteredModelMin = $filter(filterName).apply(null, modelMinOptions);\n scope.filteredModelMax = $filter(filterName).apply(null, modelMaxOptions);\n } else {\n scope.filteredModelMin = scope.modelMin;\n scope.filteredModelMax = scope.modelMax;\n }\n\n // check for no range\n if (scope.min === scope.max && scope.modelMin == scope.modelMax) {\n\n // reposition handles\n angular.element(handles[0]).css(pos, '0%');\n angular.element(handles[1]).css(pos, '100%');\n\n if (scope.attachHandleValues) {\n // reposition values\n angular.element(values[0]).css(pos, '0%');\n angular.element(values[1]).css(pos, '100%');\n }\n\n // reposition join\n angular.element(join).css(pos, '0%').css(posOpp, '0%');\n\n } else {\n\n // reposition handles\n angular.element(handles[0]).css(pos, handle1pos + '%');\n angular.element(handles[1]).css(pos, handle2pos + '%');\n\n if (scope.attachHandleValues) {\n // reposition values\n angular.element(values[0]).css(pos, value1pos + '%');\n angular.element(values[1]).css(pos, value2pos + '%');\n angular.element(values[1]).css(posOpp, 'auto');\n }\n\n // reposition join\n angular.element(join).css(pos, handle1pos + '%').css(posOpp, (100 - handle2pos) + '%');\n\n // ensure min handle can't be hidden behind max handle\n if (handle1pos > 95) {\n angular.element(handles[0]).css('z-index', 3);\n }\n }\n\n }\n\n }\n\n function handleMove(index) {\n\n var $handle = handles[index];\n\n // on mousedown / touchstart\n $handle.bind(onEvent + 'X', function(event) {\n\n var handleDownClass = (index === 0 ? 'ngrs-handle-min' : 'ngrs-handle-max') + '-down',\n //unbind = $handle.add($document).add('body'),\n modelValue = (index === 0 ? scope.modelMin : scope.modelMax) - scope.min,\n originalPosition = (modelValue / range) * 100,\n originalClick = client(event),\n previousClick = originalClick,\n previousProposal = false;\n\n if (angular.isFunction(scope.onHandleDown)) {\n scope.onHandleDown({ event: originalClick, originalEvent: event });\n }\n\n // stop user accidentally selecting stuff\n angular.element('body').bind('selectstart' + eventNamespace, function() {\n return false;\n });\n\n // only do stuff if we are disabled\n if (!scope.disabled) {\n\n // flag as down\n down = true;\n\n // add down class\n $handle.addClass('ngrs-down');\n\n $slider.addClass('ngrs-focus ' + handleDownClass);\n\n // add touch class for MS styling\n angular.element('body').addClass('ngrs-touching');\n\n // listen for mousemove / touchmove document events\n $document.bind(moveEvent, function(e) {\n // prevent default\n\n if (e.type !== 'touchmove') {\n e.preventDefault();\n }\n\n var currentClick = client(e),\n movement,\n proposal,\n other,\n per = (scope.step / range) * 100,\n otherModelPosition = (((index === 0 ? scope.modelMax : scope.modelMin) - scope.min) / range) * 100;\n\n if (currentClick[0] === \"x\") {\n return;\n }\n\n // calculate deltas\n currentClick[0] -= originalClick[0];\n currentClick[1] -= originalClick[1];\n\n // has movement occurred on either axis?\n movement = [\n (previousClick[0] !== currentClick[0]), (previousClick[1] !== currentClick[1])\n ];\n\n // propose a movement\n proposal = originalPosition + ((currentClick[orientation] * 100) / (orientation ? $slider.height() : $slider.width()));\n\n // normalize so it can't move out of bounds\n proposal = restrict(proposal);\n\n if (scope.preventEqualMinMax) {\n\n if (per === 0) {\n per = (1 / range) * 100; // restrict to 1\n }\n\n if (index === 0) {\n otherModelPosition = otherModelPosition - per;\n } else if (index === 1) {\n otherModelPosition = otherModelPosition + per;\n }\n }\n\n // check which handle is being moved and add / remove margin\n if (index === 0) {\n proposal = proposal > otherModelPosition ? otherModelPosition : proposal;\n } else if (index === 1) {\n proposal = proposal < otherModelPosition ? otherModelPosition : proposal;\n }\n\n if (scope.step > 0) {\n // only change if we are within the extremes, otherwise we get strange rounding\n if (proposal < 100 && proposal > 0) {\n proposal = Math.round(proposal / per) * per;\n }\n }\n\n if (proposal > 95 && index === 0) {\n $handle.css('z-index', 3);\n } else {\n $handle.css('z-index', '');\n }\n\n if (movement[orientation] && proposal != previousProposal) {\n\n if (index === 0) {\n\n // update model as we slide\n scope.modelMin = parseFloat(parseFloat((((proposal * range) / 100) + scope.min)).toFixed(scope.decimalPlaces));\n\n if (angular.isFunction(scope.onHandleMoveDown)) {\n scope.onHandleMoveDown({ event: e, modelMin: scope.modelMin });\n }\n\n } else if (index === 1) {\n\n scope.modelMax = parseFloat(parseFloat((((proposal * range) / 100) + scope.min)).toFixed(scope.decimalPlaces));\n\n if (angular.isFunction(scope.onHandleMoveUp)) {\n scope.onHandleMoveUp({ event: e, modelMax: scope.modelMax });\n }\n }\n\n // update angular\n scope.$apply();\n\n previousProposal = proposal;\n\n }\n\n previousClick = currentClick;\n\n }).bind(offEvent, function(event) {\n\n if (angular.isFunction(scope.onHandleUp)) {\n scope.onHandleUp({ event: event });\n }\n\n // unbind listeners\n $document.off(moveEvent);\n $document.off(offEvent);\n\n angular.element('body').removeClass('ngrs-touching');\n\n // cancel down flag\n down = false;\n\n // remove down and over class\n $handle.removeClass('ngrs-down');\n $handle.removeClass('ngrs-over');\n\n // remove active class\n $slider.removeClass('ngrs-focus ' + handleDownClass);\n\n });\n }\n\n }).on(overEvent, function () {\n $handle.addClass('ngrs-over');\n }).on(outEvent, function () {\n if (!down) {\n $handle.removeClass('ngrs-over');\n }\n });\n }\n\n scope.inputChange = function (event) {\n\n if (angular.element(event.target).val() == '')\n return;\n\n if (angular.isFunction(scope.onHandleUp)) {\n scope.onHandleUp({ event: event });\n }\n };\n\n\n function throwError(message) {\n scope.disabled = true;\n throw new Error('RangeSlider: ' + message);\n }\n\n function throwWarning(message) {\n $log.warn(message);\n }\n\n /**\n * DESTROY\n */\n\n scope.$on('$destroy', function() {\n\n // unbind event from slider\n $slider.off(eventNamespace);\n\n // unbind from body\n angular.element('body').off(eventNamespace);\n\n // unbind from document\n $document.off(eventNamespace);\n\n // unbind from handles\n for (var i = 0, l = handles.length; i < l; i++) {\n handles[i].off(eventNamespace);\n handles[i].off(eventNamespace + 'X');\n }\n\n });\n\n /**\n * INIT\n */\n\n $slider\n // disable selection\n .bind('selectstart' + eventNamespace, function(event) {\n return false;\n })\n // stop propagation\n .bind('click', function(event) {\n event.stopPropagation();\n });\n\n // bind events to each handle\n handleMove(0);\n handleMove(1);\n\n }\n };\n }]);\n\n // requestAnimationFramePolyFill\n // http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/\n // shim layer with setTimeout fallback\n window.requestAnimFrame = (function() {\n return window.requestAnimationFrame ||\n window.webkitRequestAnimationFrame ||\n window.mozRequestAnimationFrame ||\n function(callback) {\n window.setTimeout(callback, 1000 / 60);\n };\n })();\n}());\n", "\uFEFFimport './styles/popover.scss';\n\nimport PopoverCtrl from './controllers/popoverController.js';\nimport PopoverControlCtrl from './controllers/popoverControlController.js';\nimport PopoverOverlayCtrl from './controllers/PopoverOverlayController.js';\nimport { popoverControlDirective, popoverDirective, popoverOverlayDirective } from './directives/popoverDirectives.js';\n\nimport popoverService from './services/popoverService.js';\n\nconst moduleName = 'popover';\n\nangular\n .module('popover', [])\n .constant('popoverConfig', {\n popoverTrigger: 'mouseenter',\n popoverTriggerHide: 'mouseleave',\n popoverShowOnLoad: false,\n popoverOverlayEnabled: false,\n popoverPosition: 'top',\n popoverIsFixed: false,\n popoverIsCanHover: false,\n popoverShowOne: false,\n popoverShowDelay: 0,\n popoverShowCross: false,\n })\n .service('popoverService', popoverService)\n .controller('PopoverCtrl', PopoverCtrl)\n .controller('PopoverControlCtrl', PopoverControlCtrl)\n .controller('PopoverOverlayCtrl', PopoverOverlayCtrl)\n .directive('popoverControl', popoverControlDirective)\n .directive('popover', popoverDirective)\n .directive('popoverOverlay', popoverOverlayDirective);\n\nexport default moduleName;\n", "function PopoverCtrl($q, $element, $window, $timeout, popoverService, popoverConfig) {\n var ctrl = this;\n ctrl.$onInit = function () {\n var popoverShowOnLoad = ctrl.popoverShowOnLoad(),\n popoverOverlayEnabled = ctrl.popoverOverlayEnabled(),\n popoverIsFixed = ctrl.popoverIsFixed(),\n popoverIsCanHover = ctrl.popoverIsCanHover();\n ctrl.popoverShowOnLoad = popoverShowOnLoad != null ? popoverShowOnLoad : popoverConfig.popoverShowOnLoad;\n ctrl.popoverOverlayEnabled = popoverOverlayEnabled != null ? popoverOverlayEnabled : popoverConfig.popoverOverlayEnabled;\n ctrl.popoverIsFixed = popoverShowOnLoad != null ? popoverIsFixed : popoverConfig.popoverIsFixed;\n ctrl.popoverIsCanHover = popoverIsCanHover != null ? popoverIsCanHover : popoverConfig.popoverIsCanHover;\n ctrl.popoverShowOne = ctrl.popoverShowOne != null ? ctrl.popoverShowOne : popoverConfig.popoverShowOne;\n ctrl.popoverShowDelay = ctrl.popoverShowDelay != null ? ctrl.popoverShowDelay : popoverConfig.popoverShowDelay;\n ctrl.popoverShowCross = ctrl.popoverShowCross != null ? ctrl.popoverShowCross : popoverConfig.popoverShowCross;\n popoverService.addStorage(ctrl.id, ctrl);\n };\n ctrl.updatePosition = function (targetElement) {\n ctrl.position = popoverService.getPosition($element[0], targetElement || ctrl.controlElement[0], ctrl.popoverPosition, ctrl.popoverIsFixed);\n };\n ctrl.active = function (targetElement) {\n if (ctrl.popoverShowOne === true && $window.localStorage.getItem(ctrl.id)) {\n return $q.resolve('Popover show is one');\n }\n return $timeout(function () {\n ctrl.popoverIsShow = true;\n $element[0].classList.add('active');\n if (!ctrl.popoverCustomStyles) {\n ctrl.updatePosition(targetElement);\n ctrl.popoverPosition = ctrl.position.position;\n }\n if (ctrl.popoverOverlayEnabled === true) {\n popoverService.showOverlay(ctrl.id);\n }\n if (ctrl.popoverOnOpen) {\n ctrl.popoverOnOpen();\n }\n }, ctrl.popoverShowDelay);\n };\n ctrl.deactive = function () {\n ctrl.popoverIsShow = false;\n $element[0].classList.remove('active');\n if (ctrl.popoverShowOne === true) {\n $window.localStorage.setItem(ctrl.id, true);\n }\n if (ctrl.popoverOverlayEnabled === true) {\n popoverService.getPopoverOverlay().then(function (overlayScope) {\n overlayScope.overlayHide();\n });\n }\n if (ctrl.popoverOnClose) {\n ctrl.popoverOnClose();\n }\n };\n ctrl.toggle = function () {\n if (ctrl.popoverIsShow === true) {\n ctrl.deactive();\n } else {\n ctrl.active();\n }\n };\n ctrl.getClasses = function () {\n var result = [];\n result.push('adv-popover-position-' + ctrl.popoverPosition);\n if (ctrl.popoverIsFixed === true) {\n result.push('adv-popover-fixed');\n }\n return result;\n };\n}\nPopoverCtrl.$inject = [\"$q\", \"$element\", \"$window\", \"$timeout\", \"popoverService\", \"popoverConfig\"];\nexport default PopoverCtrl;", "function PopoverControlCtrl($element, popoverService) {\n var ctrl = this,\n popoverScope;\n ctrl.$onInit = function () {\n popoverService.getPopoverScope(ctrl.popoverId).then(function () {\n return popoverService.addControl(ctrl.popoverId, $element[0]);\n }).then(function (result) {\n popoverScope = result;\n });\n };\n ctrl.active = function () {\n if (popoverScope != null) {\n popoverScope.active($element[0]);\n }\n };\n ctrl.deactive = function () {\n if (popoverScope != null) {\n popoverScope.deactive();\n }\n };\n ctrl.toggle = function () {\n if (popoverScope != null) {\n popoverScope.toggle();\n }\n };\n}\nPopoverControlCtrl.$inject = [\"$element\", \"popoverService\"];\nexport default PopoverControlCtrl;", "function PopoverOverlayCtrl(popoverService) {\n var ctrl = this;\n ctrl.overlayHide = function () {\n popoverService.getPopoverScope(ctrl.popoverId).then(function (popoverScope) {\n popoverScope.deactive();\n ctrl.popoverId = null;\n ctrl.isVisibleOverlay = false;\n });\n };\n popoverService.addPopoverOverlay(ctrl);\n}\nPopoverOverlayCtrl.$inject = [\"popoverService\"];\nexport default PopoverOverlayCtrl;", "import popoverTemplate from '../templates/popover.html';\n/* @ngInject */\nfunction popoverControlDirective(popoverConfig) {\n return {\n restrict: 'A',\n scope: {\n popoverId: '@',\n popoverTrigger: '@',\n popoverTriggerHide: '@',\n popoverOnOpen: '
    '].join('');\n }\n };\n}\npopoverControlDirective.$inject = [\"popoverConfig\"];\nfunction popoverDirective(popoverService, popoverConfig) {\n return {\n restrict: 'A',\n scope: {\n id: '@',\n popoverShowOnLoad: '&',\n popoverOverlayEnabled: '&',\n popoverPosition: '@',\n popoverIsFixed: '&',\n popoverIsCanHover: '&',\n popoverShowOne: '
    ',\n controller: 'PopoverOverlayCtrl',\n controllerAs: 'popoverOverlay',\n bindToController: true\n };\n}\nexport { popoverControlDirective, popoverDirective, popoverOverlayDirective };", "function popoverService($cacheFactory, $q, $rootScope, $compile, $window, $document) {\n var service = this,\n cache = $cacheFactory('cachePopover'),\n deferOverlay,\n defersPopover = {},\n defersPopoverControl = {},\n tileTriangle = 8,\n tileSize;\n service.addStorage = function (popoverId, obj) {\n var item = cache.get(popoverId),\n objForSave = {};\n if (item != null) {\n angular.extend(objForSave, item, obj);\n } else {\n objForSave = obj;\n }\n var popover = cache.put(popoverId, objForSave);\n if (defersPopover[popoverId] != null) {\n defersPopover[popoverId].resolve(popover);\n }\n return popover;\n };\n service.addControl = function (popoverId, control) {\n return service.getPopoverScope(popoverId).then(function (popoverScope) {\n popoverScope.controlElement = control;\n if (defersPopoverControl[popoverId] != null) {\n defersPopoverControl[popoverId].resolve(control);\n }\n return popoverScope;\n });\n };\n service.getControl = function (popoverId) {\n return service.getPopoverScope(popoverId).then(function (popoverScope) {\n var defer = $q.defer();\n if (popoverScope.controlElement == null) {\n defersPopoverControl[popoverId] = defer;\n } else {\n defer.resolve(popoverScope.controlElement);\n }\n return defer.promise;\n });\n };\n service.getPopoverScope = function (popoverId) {\n var popover = cache.get(popoverId),\n defer = $q.defer(),\n promise = defer.promise;\n if (popover == null) {\n defersPopover[popoverId] = defer;\n } else {\n defer.resolve(popover);\n }\n return promise;\n };\n service.addPopoverOverlay = function (overlayScope) {\n service.addStorage('popoverOverlay', overlayScope);\n if (deferOverlay != null) {\n deferOverlay.resolve(overlayScope);\n }\n };\n service.getPopoverOverlay = function () {\n var overlay = cache.get('popoverOverlay'),\n defer = $q.defer(),\n promise = defer.promise;\n if (overlay == null) {\n deferOverlay = defer;\n service.renderOverlay();\n } else {\n defer.resolve(overlay);\n }\n return promise;\n };\n service.showOverlay = function (popoverId) {\n return service.getPopoverOverlay().then(function (overlayScope) {\n overlayScope.isVisibleOverlay = true;\n overlayScope.popoverId = popoverId;\n return overlayScope;\n });\n };\n service.renderOverlay = function () {\n var overlay = angular.element('
    ');\n $document[0].body.appendChild(overlay[0]);\n $compile(overlay)($rootScope.$new(true));\n };\n service.getPosition = function (popoverElement, popoverControlElement, position, isFixed) {\n var popoverControlSize, popoverControlPos, popoverControlPosAbs, popoverSize, pos, positionData, tileSize, controlRect;\n popoverControlSize = {\n width: popoverControlElement.offsetWidth,\n height: popoverControlElement.offsetHeight\n };\n popoverControlPos = {\n top: popoverControlElement.offsetTop,\n left: popoverControlElement.offsetLeft\n };\n controlRect = popoverControlElement.getBoundingClientRect();\n popoverControlPosAbs = {\n top: controlRect.top,\n bottom: controlRect.bottom,\n left: controlRect.left,\n right: controlRect.right,\n width: controlRect.width\n };\n if (!(controlRect.top >= 0 && controlRect.bottom <= (window.innerHeight || document.documentElement.clientHeight))) {\n popoverControlPosAbs.top += $window.pageYOffset;\n popoverControlPosAbs.bottom += $window.pageYOffset;\n }\n popoverSize = {\n width: popoverElement.offsetWidth,\n height: popoverElement.offsetHeight\n };\n pos = {\n top: 0,\n left: 0,\n leftTile: 0,\n position: position\n };\n positionData = isFixed === true ? popoverControlPosAbs : popoverControlPos;\n switch (position) {\n case 'top':\n tileSize = tileSize || popoverElement.querySelector('.js-popover-tile').offsetHeight; //5 - \u0434\u043B\u044F \u043D\u0430\u0445\u043B\u0435\u0441\u0442\u0430\n pos.top = positionData.top - popoverSize.height - tileSize;\n pos.left = positionData.left + (popoverControlSize.width - popoverSize.width) / 2;\n break;\n case 'right':\n tileSize = tileSize || popoverElement.querySelector('.js-popover-tile').offsetWidth + tileTriangle; //5 - \u0434\u043B\u044F \u043D\u0430\u0445\u043B\u0435\u0441\u0442\u0430\n pos.top = positionData.top + (popoverControlSize.height - popoverSize.height) / 2;\n pos.left = positionData.left + popoverControlSize.width + tileSize;\n break;\n case 'bottom':\n tileSize = tileSize || popoverElement.querySelector('.js-popover-tile').offsetHeight; //5 - \u0434\u043B\u044F \u043D\u0430\u0445\u043B\u0435\u0441\u0442\u0430\n pos.top = positionData.top + popoverControlSize.height + tileSize;\n pos.left = positionData.left + (popoverControlSize.width - popoverSize.width) / 2;\n break;\n case 'left':\n tileSize = tileSize || popoverElement.querySelector('.js-popover-tile').offsetWidth + tileTriangle; //5 - \u0434\u043B\u044F \u043D\u0430\u0445\u043B\u0435\u0441\u0442\u0430\n pos.top = positionData.top + (popoverControlSize.height - popoverSize.height) / 2;\n if (isFixed === true) {\n pos.left = positionData.left - popoverSize.width;\n } else {\n pos.left = 'auto';\n pos.right = '100%';\n }\n if (popoverControlPosAbs.left <= popoverSize.width) {\n tileSize = tileSize || popoverElement.querySelector('.js-popover-tile').offsetWidth + tileTriangle; //5 - \u0434\u043B\u044F \u043D\u0430\u0445\u043B\u0435\u0441\u0442\u0430\n pos.left = positionData.left + popoverControlSize.width + tileSize;\n pos.position = 'right';\n pos.right = 'auto';\n }\n break;\n case 'topleft':\n tileSize = tileSize || popoverElement.querySelector('.js-popover-tile').offsetHeight; //5 - \u0434\u043B\u044F \u043D\u0430\u0445\u043B\u0435\u0441\u0442\u0430\n pos.top = positionData.top - popoverSize.height - tileSize;\n if (isFixed === true) {\n pos.left = positionData.left - popoverSize.width + positionData.width;\n } else {\n pos.left = 'auto';\n pos.right = '100%';\n }\n if (popoverControlPosAbs.left <= popoverSize.width) {\n tileSize = tileSize || popoverElement.querySelector('.js-popover-tile').offsetWidth + tileTriangle; //5 - \u0434\u043B\u044F \u043D\u0430\u0445\u043B\u0435\u0441\u0442\u0430\n pos.left = positionData.left + popoverControlSize.width + tileSize;\n pos.position = 'right';\n pos.right = 'auto';\n }\n pos.leftTile = popoverSize.width - positionData.width / 2 - tileSize / 2;\n break;\n default:\n throw new Error('Not register position:' + position);\n }\n return pos;\n };\n}\npopoverService.$inject = [\"$cacheFactory\", \"$q\", \"$rootScope\", \"$compile\", \"$window\", \"$document\"];\nexport default popoverService;", "\uFEFFfunction catalogFilterService() {\n var service = this,\n filterStorage;\n\n service.buildUrl = function (filterSelectedItems) {\n var result = [],\n obj;\n\n for (var item in filterSelectedItems) {\n if (filterSelectedItems[item] == null || filterSelectedItems[item] == '') {\n continue;\n }\n\n if (angular.isArray(filterSelectedItems[item]) === true) {\n obj =\n item +\n '=' +\n filterSelectedItems[item]\n .map(function (val) {\n return angular.isArray(val) ? val.join(',') : val;\n })\n .join('-');\n } else {\n obj = item + '=' + filterSelectedItems[item];\n }\n\n result.push(obj);\n }\n\n return result.join('&');\n };\n\n service.getSelectedData = function (filterData) {\n if (filterData == null) {\n return null;\n }\n\n var arraySelected, selectedItems, item, nameRangeMin, nameRangeMax;\n\n for (var i = filterData.length - 1; i >= 0; i--) {\n item = filterData[i];\n\n if (item == null) continue;\n\n selectedItems = null;\n\n //\u0438\u0449\u0435\u043C \u0432\u044B\u0431\u0440\u0430\u043D\u043D\u044B\u0435 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F\n if (item.Control == 'select' || item.Control == 'selectSearch') {\n if (item.Selected != null && item.Selected.Id !== '0') {\n selectedItems = item.Selected.Id;\n }\n } else {\n selectedItems = item.Values.filter(function (item) {\n return item.Selected;\n }).map(function (item) {\n return item.Id;\n });\n }\n\n //\u0434\u043E\u0431\u0430\u0432\u043B\u044F\u0435\u043C \u044D\u0442\u0438 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u0432 \u043C\u0430\u0441\u0441\u0438\u0432\n if (selectedItems != null && selectedItems.length > 0) {\n arraySelected = arraySelected || {};\n\n arraySelected[item.Type] = arraySelected[item.Type] || [];\n\n arraySelected[item.Type].push(selectedItems);\n }\n\n //\u0434\u043E\u0431\u0430\u0432\u043B\u044F\u0435\u043C \u0442\u0435\u043A\u0441\u0442 \u0434\u043B\u044F \u043F\u043E\u0438\u0441\u043A\u0430\n if (item.Control == 'input' && item.Text.length > 0) {\n arraySelected = arraySelected || {};\n arraySelected['q'] = [item.Text];\n }\n\n //\u0434\u043E\u0431\u0430\u0432\u043B\u044F\u0435\u043C \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u044F \u0438\u0437 \u043F\u043E\u043B\u0437\u0443\u043D\u043A\u043E\u0432\n if (item.Control == 'range') {\n arraySelected = arraySelected || {};\n\n if (item.Type == 'price') {\n nameRangeMin = 'pricefrom';\n nameRangeMax = 'priceto';\n } else {\n nameRangeMin = item.Type + '_' + item.Values[0].Id + '_min';\n nameRangeMax = item.Type + '_' + item.Values[0].Id + '_max';\n }\n\n if (item.Values[0].Min !== item.Values[0].CurrentMin || item.Values[0].Max !== item.Values[0].CurrentMax) {\n //if (item.dirty) {\n arraySelected[nameRangeMin] = [item.Values[0].CurrentMin];\n arraySelected[nameRangeMax] = [item.Values[0].CurrentMax];\n }\n\n //}\n }\n }\n\n return arraySelected;\n };\n\n service.parseSearchString = function (str) {\n var index = str.indexOf('?'),\n strNormalize = str,\n parameters = {},\n arrayKeyValues,\n temp;\n\n if (index > -1) {\n strNormalize = strNormalize.substring(index + 1);\n }\n\n arrayKeyValues = strNormalize.split('&');\n\n for (var i = arrayKeyValues.length - 1; i >= 0; i--) {\n temp = arrayKeyValues[i].split('=');\n\n if (temp.length === 2) {\n parameters[decodeURIComponent(temp[0])] = decodeURIComponent(temp[1]);\n }\n }\n\n return parameters;\n };\n\n service.saveFilterData = function (filter) {\n filterStorage = filter;\n };\n\n service.getFilterData = function () {\n return filterStorage;\n };\n}\n\nexport default catalogFilterService;\n", "\uFEFFimport catalogFilterTemplate from '../templates/catalogFilter.html';\nfunction catalogFilterDirective() {\n return {\n restrict: 'A',\n scope: {\n url: '@',\n urlCount: '@',\n parameters: '&',\n countVisibleCollapse: '&',\n onFilterInit: '&',\n advPopoverOptions: '',\n controller: 'CatalogFilterSortCtrl',\n controllerAs: 'catalogFilterSort',\n bindToController: true,\n };\n}\n\nfunction catalogFilterSelectSortDirective() {\n return {\n restrict: 'A',\n scope: true,\n controller: 'CatalogFilterSortCtrl',\n controllerAs: 'catalogFilterSort',\n bindToController: true,\n };\n}\n\nexport { catalogFilterDirective, catalogFilterSortDirective, catalogFilterSelectSortDirective };\n", "var isIE = /Windows Phone|iemobile|WPDesktop/.test(navigator.userAgent);\n\n/*@ngInject*/\nfunction CatalogFilterCtrl($http, $window, $timeout, popoverService, domService, catalogFilterService, catalogFilterAdvPopoverOptionsDefault) {\n var ctrl = this,\n pageParameters,\n timerPopoverHide,\n timerRange;\n ctrl.$onInit = function () {\n pageParameters = catalogFilterService.parseSearchString($window.location.search);\n ctrl.isIE = isIE;\n ctrl.countVisibleCollapse = ctrl.countVisibleCollapse() || 10;\n ctrl.collapsed = true;\n ctrl.isRenderBlock = false;\n ctrl.isLoaded = false;\n ctrl.itemsOptions = [];\n ctrl.advPopoverOptions = angular.extend({}, catalogFilterAdvPopoverOptionsDefault, ctrl.advPopoverOptions);\n ctrl.isShowLoader = true;\n ctrl.getFilterData().then(function (catalogFilterData) {\n ctrl.catalogFilterData = catalogFilterData?.map(function (filter) {\n filter.dirty = false;\n return filter;\n });\n ctrl.isRenderBlock = catalogFilterData != null && catalogFilterData.length > 0;\n ctrl.isLoaded = true;\n if (ctrl.onFilterInit) {\n ctrl.onFilterInit({\n visible: ctrl.isRenderBlock\n });\n }\n\n //Fill all