{ "version": 3, "sources": [ "../../../../../Foundation/JavascriptCommon/code/scripts/common/formUtils.js", "../../../../../Foundation/JavascriptCommon/code/scripts/common/spinner.js", "../../../../../Foundation/JavascriptCommon/code/scripts/common/slickSlider.js", "../../../../../Foundation/JavascriptCommon/code/scripts/common/productSlides.js", "ProductFeatures/productFeatures.js" ], "names": [], "mappings": "AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,ACrHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC/CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AC5BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,AClEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", "file": "ProductFeatures.js", "sourcesContent": [ "define('common/formUtils',[\r\n],\r\n function () {\r\n\r\n // Clears and deactivates all invalid feedback text on form fields\r\n function clearInvalidFeedback(formId) {\r\n if (!formId.startsWith(\"#\")) formId = \"#\" + formId;\r\n $(formId + \" .is-invalid\").removeClass(\"is-invalid\");\r\n $(formId + \" .invalid-feedback\").empty();\r\n }\r\n\r\n // Fills in and activates invalid feedback text on form fields\r\n function displayInvalidFeedback(invalidFields, formId) {\r\n if (!formId.startsWith(\"#\")) formId = \"#\" + formId;\r\n if (invalidFields) {\r\n invalidFields.forEach(function (fieldMessage) {\r\n var field = $(formId + \" [name='\" + fieldMessage.FieldName + \"']\");\r\n field.addClass(\"is-invalid\");\r\n field.siblings(\".invalid-feedback\").append(fieldMessage.MessageText);\r\n });\r\n }\r\n }\r\n\r\n // Collects the data from all form fields and returns them as object,\r\n // using \"name\" attribute values from form fields as object property names.\r\n function collectFormData(formId) {\r\n if (!formId.startsWith(\"#\")) formId = \"#\" + formId;\r\n // the serializeArray() jQuery method doesn't take the values from disabled fields, so first I'll\r\n // temporarily enable all disabled fields, and then disable them again\r\n var disabledFields = $(formId).find(\":input:disabled\").prop(\"disabled\", false);\r\n var serializedData = $(formId).serializeArray();\r\n disabledFields.prop(\"disabled\", true);\r\n var formData = {};\r\n serializedData.forEach(function (data) {\r\n formData[data.name] = data.value;\r\n });\r\n // serializeArray does not return anything for unchecked checkboxes, so we'll add them now with value false\r\n $(formId + \" input[type='checkbox']:not(:checked)\").each(function (index, element) {\r\n formData[element.name] = false;\r\n });\r\n // serializeArray returns \"on\" for checked checkboxes, so we'll set them to true now\r\n $(formId + \" input[type='checkbox']:checked\").each(function (index, element) {\r\n formData[element.name] = true;\r\n });\r\n return formData;\r\n }\r\n\r\n // Goes through all input elements on the form and fills them with data from the\r\n // given object, matching \"name\" attribute of the input element with object property name.\r\n function populateFormWithData(formId, data) {\r\n if (!formId.startsWith(\"#\")) formId = \"#\" + formId;\r\n $(formId + \" :input\").each(function (index, element) { \r\n if (element.type === \"radio\" ||\r\n element.type === \"checkbox\")\r\n {\r\n if (data[element.name] !== undefined)\r\n $(element).prop(\"checked\", $(element).val().toString() === data[element.name].toString());\r\n }\r\n else if (element.type === \"text\" ||\r\n element.type === \"email\" ||\r\n element.type === \"tel\" ||\r\n element.type === \"password\" ||\r\n element.type === \"textarea\" ||\r\n element.type === \"select-one\")\r\n {\r\n if (data[element.name] !== undefined)\r\n $(element).val(data[element.name]);\r\n else\r\n $(element).val(null);\r\n }\r\n });\r\n }\r\n\r\n function disableFields(formId) {\r\n if (!formId.startsWith(\"#\")) formId = \"#\" + formId;\r\n $(formId + \" :input\").prop(\"disabled\", true);\r\n }\r\n\r\n function enableFields(formId) {\r\n if (!formId.startsWith(\"#\")) formId = \"#\" + formId;\r\n $(formId + \" :input\").prop(\"disabled\", false);\r\n }\r\n\r\n function initializeFloatingLabels(formId) {\r\n if (!formId.startsWith(\"#\")) formId = \"#\" + formId;\r\n $(formId + \" .floating-label-container\").each(function (index, element) {\r\n var inputElement = $(element).find(\":input\")[0];\r\n if (inputElement.value) $(element).addClass(\"active\");\r\n else $(element).removeClass(\"active\");\r\n });\r\n }\r\n\r\n function setFocus(selector, delay) {\r\n // sometimes focus has to be set with a delay, so that some other processes have time to finish before that (e.g. initializing floating labels)\r\n if (delay) setTimeout(() => { $(selector).focus(); }, delay);\r\n else $(selector).focus();\r\n }\r\n\r\n //adds the form token to the object for use with [ValidateAntiforgeryToken] attribute\r\n function useToken(data) { \r\n var token = $('input[name=\"__RequestVerificationToken\"]').val();\r\n data.__RequestVerificationToken = token;\r\n }\r\n\r\n return {\r\n clearInvalidFeedback: clearInvalidFeedback,\r\n displayInvalidFeedback: displayInvalidFeedback,\r\n collectFormData: collectFormData,\r\n populateFormWithData: populateFormWithData,\r\n disableFields: disableFields,\r\n enableFields: enableFields,\r\n initializeFloatingLabels: initializeFloatingLabels,\r\n setFocus: setFocus,\r\n useToken: useToken\r\n };\r\n });\r\n\n", "define('common/spinner',[\r\n],\r\n function () {\r\n\r\n var spinnerShownAt = {};\r\n\r\n function show(spinnerSelector) {\r\n if (!spinnerSelector) return;\r\n $(spinnerSelector).removeClass(\"d-none\");\r\n var image = $(spinnerSelector).find(\"img\");\r\n if (image.length) {\r\n var alt = $(image).attr(\"alt\");\r\n if (!alt)\r\n $(image).attr(\"alt\", \"Spinner\");\r\n }\r\n // mark the time when this spinner was displayed\r\n spinnerShownAt[spinnerSelector] = Date.now();\r\n }\r\n\r\n function hide(spinnerSelector, callbackWhenHidden) {\r\n if (!spinnerSelector) return;\r\n // This logic ensures that the spinner is displayed for at least 500ms.\r\n // Otherwise it just flickers and that doesn't look good for the user.\r\n var waitTime = 500 - (Date.now() - spinnerShownAt[spinnerSelector]);\r\n if (waitTime > 0) {\r\n setTimeout(function () {\r\n $(spinnerSelector).addClass(\"d-none\");\r\n if (callbackWhenHidden) callbackWhenHidden();\r\n }, waitTime);\r\n }\r\n else {\r\n $(spinnerSelector).addClass(\"d-none\");\r\n if (callbackWhenHidden) callbackWhenHidden();\r\n }\r\n }\r\n\r\n function getSpinnerHtml(spinnerId) {\r\n return '
';\r\n }\r\n\r\n return {\r\n show: show,\r\n hide: hide,\r\n getSpinnerHtml: getSpinnerHtml\r\n };\r\n });\r\n\n", "define('common/slickSlider',[\r\n],\r\n function () {\r\n\r\n function init(selector, options) {\r\n if (!options) options = { dots: true };\r\n $(selector).each(function (index, element) {\r\n if ($(element).hasClass(\"slick-initialized\")) {\r\n $(element).slick(\"unslick\");\r\n }\r\n $(element).slick(options);\r\n });\r\n }\r\n\r\n function destroy(selector) {\r\n $(selector).each(function (index, element) {\r\n if ($(element).hasClass(\"slick-initialized\")) {\r\n $(element).slick(\"unslick\");\r\n }\r\n });\r\n }\r\n\r\n return {\r\n init: init,\r\n destroy: destroy\r\n };\r\n });\r\n\n", "define('common/productSlides',[\r\n],\r\n function () {\r\n\r\n const SLIDE = \".product-slide\";\r\n const NORMAL = \".product-slide-normal-wrapper\";\r\n const VIDEO = \".product-slide-video-wrapper\";\r\n\r\n let videoPlayers = [];\r\n\r\n function init(selector) {\r\n $(selector).find(\".cp-play-video\").off(\"click\").on(\"click\", videoPlayButtonClicked);\r\n $(selector).find(\".close-video\").off(\"click\").on(\"click\", closeVideoButtonClicked);\r\n videoPlayers = [];\r\n }\r\n\r\n function videoPlayButtonClicked(event) {\r\n // hide the \"normal\" slide content and display the video instead\r\n let slide = $(this).closest(SLIDE);\r\n let normal = $(slide).find(NORMAL);\r\n let video = $(slide).find(VIDEO);\r\n $(normal).addClass(\"d-none\");\r\n $(video).removeClass(\"d-none\");\r\n play(video);\r\n }\r\n function closeVideoButtonClicked(event) {\r\n // hide the video and display the \"normal\" slide content instead\r\n let slide = $(this).closest(SLIDE);\r\n let normal = $(slide).find(NORMAL);\r\n let video = $(slide).find(VIDEO);\r\n $(video).addClass(\"d-none\");\r\n $(normal).removeClass(\"d-none\");\r\n pauseAllVideos();\r\n }\r\n\r\n function play(videoWrapper) {\r\n let videoFrameId = $(videoWrapper).find(\".product-slide-video\").attr(\"id\");\r\n let existingPlayer = videoPlayers.find(p => p.frameId == videoFrameId);\r\n if (existingPlayer) {\r\n existingPlayer.ytPlayer.playVideo();\r\n }\r\n else if (YT) {\r\n // this is currently working only for YouTube videos\r\n let newPlayer = new YT.Player(videoFrameId, {\r\n events: {\r\n \"onReady\": playerReady\r\n }\r\n });\r\n }\r\n }\r\n\r\n function playerReady(event) {\r\n videoPlayers.push({ frameId: event.target.getIframe().id, ytPlayer: event.target });\r\n event.target.playVideo();\r\n }\r\n\r\n function pauseAllVideos() {\r\n videoPlayers.forEach(p => p.ytPlayer.pauseVideo());\r\n }\r\n\r\n return {\r\n init: init,\r\n pauseAllVideos: pauseAllVideos\r\n };\r\n });\r\n\n", "require([\r\n \"common/formUtils\",\r\n \"common/spinner\",\r\n \"common/slickSlider\",\r\n \"common/productSlides\"\r\n],\r\nfunction (formUtils, spinner, slickSlider, productSlides) {\r\n\r\n const FEATURES_SELECTOR = \".product-features\";\r\n const HOVERABLES_SELECTOR = FEATURES_SELECTOR + \" .product-feature-hoverable\";\r\n const MARKERS_SELECTOR = \".product-feature-marker\";\r\n\r\n const MODAL_SELECTOR = \"#product-features-modal\";\r\n const MODAL_TITLE_SELECTOR = MODAL_SELECTOR + \" .product-feature-modal-title\";\r\n const MODAL_BODY_SELECTOR = MODAL_SELECTOR + \" .product-feature-modal-body\";\r\n const MODAL_SLIDER_SELECTOR = MODAL_BODY_SELECTOR + \" .product-slides\";\r\n const SPINNER_SELECTOR = MODAL_SELECTOR + \" .spinner-wrapper\";\r\n\r\n function init() {\r\n $(HOVERABLES_SELECTOR)\r\n .on(\"mouseenter\", hoverIn)\r\n .on(\"mouseleave\", hoverOut)\r\n .on(\"click\", markerClicked);\r\n $(MODAL_SELECTOR).on(\"hidden.bs.modal\", productSlides.pauseAllVideos);\r\n }\r\n\r\n\r\n function hoverIn(event) {\r\n let featureId = getFeatureId(event.target);\r\n if (featureId) {\r\n $(FEATURES_SELECTOR + \" \" + MARKERS_SELECTOR + \"[data-feature-id='\" + featureId + \"']\").each(function (index, element) {\r\n let activeClass = $(element).data(\"activeClass\");\r\n $(element).addClass(activeClass);\r\n });\r\n }\r\n }\r\n\r\n function hoverOut(event) {\r\n removeActiveClassFromAllMarkers();\r\n }\r\n\r\n function removeActiveClassFromAllMarkers() {\r\n $(FEATURES_SELECTOR + \" \" + MARKERS_SELECTOR).each(function (index, element) {\r\n let activeClass = $(element).data(\"activeClass\");\r\n $(element).removeClass(activeClass);\r\n });\r\n }\r\n\r\n function getFeatureId(element) {\r\n let featureId = $(element).data(\"featureId\");\r\n if (!featureId) featureId = $(element).siblings(MARKERS_SELECTOR).data(\"featureId\");\r\n if (!featureId) featureId = $(element).find(MARKERS_SELECTOR).data(\"featureId\");\r\n return featureId;\r\n }\r\n\r\n function getFeatureTitle(featureId) {\r\n return $(HOVERABLES_SELECTOR + \" \" + MARKERS_SELECTOR + \"[data-feature-id='\" + featureId + \"']\").siblings(\".product-feature-title\").html();\r\n }\r\n\r\n function markerClicked(event) {\r\n let featureId = getFeatureId(event.target);\r\n let featureTitle = getFeatureTitle(featureId);\r\n showModal(featureId, featureTitle);\r\n }\r\n\r\n function showModal(featureId, featureTitle) {\r\n $(MODAL_TITLE_SELECTOR).empty().html(featureTitle);\r\n slickSlider.destroy(MODAL_SLIDER_SELECTOR)\r\n $(MODAL_BODY_SELECTOR).empty();\r\n spinner.show(SPINNER_SELECTOR);\r\n $(MODAL_SELECTOR).modal(\"show\");\r\n fetchDataFromBackEnd(featureId);\r\n }\r\n\r\n function fetchDataFromBackEnd(featureId) {\r\n let postData = { SlideGroupId: featureId, SlidesName: \"features\" };\r\n formUtils.useToken(postData);\r\n $.ajax({\r\n type: \"POST\",\r\n url: \"/customapi/Product/ProductSlides\",\r\n dataType: \"text\",\r\n data: postData,\r\n success: function (data) {\r\n // fill the fetched HTML into DOM\r\n $(MODAL_BODY_SELECTOR).html(data);\r\n // initializing the slider has to be done with a slight delay, because slick cannot act immediately on the freshly generated DOM\r\n // (the first slide comes out mangled if we try to initialize the slider immediately)\r\n setTimeout(function () {\r\n slickSlider.init(MODAL_SLIDER_SELECTOR);\r\n $(MODAL_SLIDER_SELECTOR).on('afterChange', productSlides.pauseAllVideos);\r\n spinner.hide(SPINNER_SELECTOR);\r\n productSlides.init(MODAL_SLIDER_SELECTOR);\r\n }, 500);\r\n },\r\n error: function (jq, status, errorThrown) {\r\n spinner.hide(SPINNER_SELECTOR);\r\n $(MODAL_BODY_SELECTOR).text(\"We're very sorry, but there were problems with fetching the data. Please try again later or call customer service for help.\");\r\n console.log(\"ERROR in fetching feature data. FeatureId= \" + featureId + \" Status=\" + status + \" \" + jq.status + \" Message=\" + errorThrown + \" \" + jq.responseText);\r\n },\r\n complete: function () {\r\n }\r\n });\r\n }\r\n\r\n init();\r\n\r\n});\r\n\ndefine(\"ProductFeatures/productFeatures\", function(){});\n\n" ] }